Skip to content

Commit

Permalink
Merge branch 'auxpow'
Browse files Browse the repository at this point in the history
  • Loading branch information
domob1812 committed Oct 3, 2023
2 parents 248e07e + 4f96336 commit 7cbe625
Show file tree
Hide file tree
Showing 24 changed files with 555 additions and 242 deletions.
1 change: 1 addition & 0 deletions src/Makefile.test.include
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ test_fuzz_fuzz_SOURCES = \
test/fuzz/netbase_dns_lookup.cpp \
test/fuzz/node_eviction.cpp \
test/fuzz/p2p_transport_serialization.cpp \
test/fuzz/package_eval.cpp \
test/fuzz/parse_hd_keypath.cpp \
test/fuzz/parse_numbers.cpp \
test/fuzz/parse_script.cpp \
Expand Down
3 changes: 2 additions & 1 deletion src/bench/load_external.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <bench/bench.h>
#include <bench/data.h>
#include <chainparams.h>
#include <clientversion.h>
#include <test/util/setup_common.h>
#include <util/chaintype.h>
#include <validation.h>
Expand Down Expand Up @@ -54,7 +55,7 @@ static void LoadExternalBlockFile(benchmark::Bench& bench)
bench.run([&] {
// "rb" is "binary, O_RDONLY", positioned to the start of the file.
// The file will be closed by LoadExternalBlockFile().
FILE* file{fsbridge::fopen(blkfile, "rb")};
CAutoFile file{fsbridge::fopen(blkfile, "rb"), CLIENT_VERSION};
testing_setup->m_node.chainman->LoadExternalBlockFile(file, &pos, &blocks_with_unknown_parent);
});
fs::remove(blkfile);
Expand Down
16 changes: 10 additions & 6 deletions src/bench/streams_findbyte.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,31 @@

#include <bench/bench.h>

#include <util/fs.h>
#include <streams.h>
#include <util/fs.h>

#include <cstddef>
#include <cstdint>
#include <cstdio>

static void FindByte(benchmark::Bench& bench)
{
// Setup
FILE* file = fsbridge::fopen("streams_tmp", "w+b");
CAutoFile file{fsbridge::fopen("streams_tmp", "w+b"), 0};
const size_t file_size = 200;
uint8_t data[file_size] = {0};
data[file_size-1] = 1;
fwrite(&data, sizeof(uint8_t), file_size, file);
rewind(file);
BufferedFile bf{file, /*nBufSize=*/file_size + 1, /*nRewindIn=*/file_size, 0};
file << data;
std::rewind(file.Get());
BufferedFile bf{file, /*nBufSize=*/file_size + 1, /*nRewindIn=*/file_size};

bench.run([&] {
bf.SetPos(0);
bf.FindByte(std::byte(1));
});

// Cleanup
bf.fclose();
file.fclose();
fs::remove("streams_tmp");
}

Expand Down
2 changes: 1 addition & 1 deletion src/index/txindex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ bool TxIndex::FindTx(const uint256& tx_hash, uint256& block_hash, CTransactionRe
return false;
}

CAutoFile file{m_chainstate->m_blockman.OpenBlockFile(postx, true), CLIENT_VERSION};
CAutoFile file{m_chainstate->m_blockman.OpenBlockFile(postx, true)};
if (file.IsNull()) {
return error("%s: OpenBlockFile failed", __func__);
}
Expand Down
73 changes: 24 additions & 49 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1002,8 +1002,7 @@ void V2Transport::StartSendingHandshake() noexcept
m_send_buffer.resize(EllSwiftPubKey::size() + m_send_garbage.size());
std::copy(std::begin(m_cipher.GetOurPubKey()), std::end(m_cipher.GetOurPubKey()), MakeWritableByteSpan(m_send_buffer).begin());
std::copy(m_send_garbage.begin(), m_send_garbage.end(), m_send_buffer.begin() + EllSwiftPubKey::size());
// We cannot wipe m_send_garbage as it will still be used to construct the garbage
// authentication packet.
// We cannot wipe m_send_garbage as it will still be used as AAD later in the handshake.
}

V2Transport::V2Transport(NodeId nodeid, bool initiating, int type_in, int version_in, const CKey& key, Span<const std::byte> ent32, std::vector<uint8_t> garbage) noexcept :
Expand Down Expand Up @@ -1037,9 +1036,6 @@ void V2Transport::SetReceiveState(RecvState recv_state) noexcept
Assume(recv_state == RecvState::GARB_GARBTERM);
break;
case RecvState::GARB_GARBTERM:
Assume(recv_state == RecvState::GARBAUTH);
break;
case RecvState::GARBAUTH:
Assume(recv_state == RecvState::VERSION);
break;
case RecvState::VERSION:
Expand Down Expand Up @@ -1171,24 +1167,15 @@ bool V2Transport::ProcessReceivedKeyBytes() noexcept
m_cipher.GetSendGarbageTerminator().end(),
MakeWritableByteSpan(m_send_buffer).last(BIP324Cipher::GARBAGE_TERMINATOR_LEN).begin());

// Construct garbage authentication packet in the send buffer (using the garbage data which
// is still there).
m_send_buffer.resize(m_send_buffer.size() + BIP324Cipher::EXPANSION);
m_cipher.Encrypt(
/*contents=*/{},
/*aad=*/MakeByteSpan(m_send_garbage),
/*ignore=*/false,
/*output=*/MakeWritableByteSpan(m_send_buffer).last(BIP324Cipher::EXPANSION));
// We no longer need the garbage.
ClearShrink(m_send_garbage);

// Construct version packet in the send buffer.
// Construct version packet in the send buffer, with the sent garbage data as AAD.
m_send_buffer.resize(m_send_buffer.size() + BIP324Cipher::EXPANSION + VERSION_CONTENTS.size());
m_cipher.Encrypt(
/*contents=*/VERSION_CONTENTS,
/*aad=*/{},
/*aad=*/MakeByteSpan(m_send_garbage),
/*ignore=*/false,
/*output=*/MakeWritableByteSpan(m_send_buffer).last(BIP324Cipher::EXPANSION + VERSION_CONTENTS.size()));
// We no longer need the garbage.
ClearShrink(m_send_garbage);
} else {
// We still have to receive more key bytes.
}
Expand All @@ -1202,11 +1189,11 @@ bool V2Transport::ProcessReceivedGarbageBytes() noexcept
Assume(m_recv_buffer.size() <= MAX_GARBAGE_LEN + BIP324Cipher::GARBAGE_TERMINATOR_LEN);
if (m_recv_buffer.size() >= BIP324Cipher::GARBAGE_TERMINATOR_LEN) {
if (MakeByteSpan(m_recv_buffer).last(BIP324Cipher::GARBAGE_TERMINATOR_LEN) == m_cipher.GetReceiveGarbageTerminator()) {
// Garbage terminator received. Switch to receiving garbage authentication packet.
m_recv_garbage = std::move(m_recv_buffer);
m_recv_garbage.resize(m_recv_garbage.size() - BIP324Cipher::GARBAGE_TERMINATOR_LEN);
// Garbage terminator received. Store garbage to authenticate it as AAD later.
m_recv_aad = std::move(m_recv_buffer);
m_recv_aad.resize(m_recv_aad.size() - BIP324Cipher::GARBAGE_TERMINATOR_LEN);
m_recv_buffer.clear();
SetReceiveState(RecvState::GARBAUTH);
SetReceiveState(RecvState::VERSION);
} else if (m_recv_buffer.size() == MAX_GARBAGE_LEN + BIP324Cipher::GARBAGE_TERMINATOR_LEN) {
// We've reached the maximum length for garbage + garbage terminator, and the
// terminator still does not match. Abort.
Expand All @@ -1225,8 +1212,7 @@ bool V2Transport::ProcessReceivedGarbageBytes() noexcept
bool V2Transport::ProcessReceivedPacketBytes() noexcept
{
AssertLockHeld(m_recv_mutex);
Assume(m_recv_state == RecvState::GARBAUTH || m_recv_state == RecvState::VERSION ||
m_recv_state == RecvState::APP);
Assume(m_recv_state == RecvState::VERSION || m_recv_state == RecvState::APP);

// The maximum permitted contents length for a packet, consisting of:
// - 0x00 byte: indicating long message type encoding
Expand All @@ -1249,45 +1235,37 @@ bool V2Transport::ProcessReceivedPacketBytes() noexcept
// as GetMaxBytesToProcess only allows up to LENGTH_LEN into the buffer before that point.
m_recv_decode_buffer.resize(m_recv_len);
bool ignore{false};
Span<const std::byte> aad;
if (m_recv_state == RecvState::GARBAUTH) aad = MakeByteSpan(m_recv_garbage);
bool ret = m_cipher.Decrypt(
/*input=*/MakeByteSpan(m_recv_buffer).subspan(BIP324Cipher::LENGTH_LEN),
/*aad=*/aad,
/*aad=*/MakeByteSpan(m_recv_aad),
/*ignore=*/ignore,
/*contents=*/MakeWritableByteSpan(m_recv_decode_buffer));
if (!ret) {
LogPrint(BCLog::NET, "V2 transport error: packet decryption failure (%u bytes), peer=%d\n", m_recv_len, m_nodeid);
return false;
}
// We have decrypted a valid packet with the AAD we expected, so clear the expected AAD.
ClearShrink(m_recv_aad);
// Feed the last 4 bytes of the Poly1305 authentication tag (and its timing) into our RNG.
RandAddEvent(ReadLE32(m_recv_buffer.data() + m_recv_buffer.size() - 4));

// At this point we have a valid packet decrypted into m_recv_decode_buffer. Depending on
// the current state, decide what to do with it.
switch (m_recv_state) {
case RecvState::GARBAUTH:
// Ignore flag does not matter for garbage authentication. Any valid packet functions
// as authentication. Receive and process the version packet next.
SetReceiveState(RecvState::VERSION);
ClearShrink(m_recv_garbage);
break;
case RecvState::VERSION:
if (!ignore) {
// At this point we have a valid packet decrypted into m_recv_decode_buffer. If it's not a
// decoy, which we simply ignore, use the current state to decide what to do with it.
if (!ignore) {
switch (m_recv_state) {
case RecvState::VERSION:
// Version message received; transition to application phase. The contents is
// ignored, but can be used for future extensions.
SetReceiveState(RecvState::APP);
}
break;
case RecvState::APP:
if (!ignore) {
break;
case RecvState::APP:
// Application message decrypted correctly. It can be extracted using GetMessage().
SetReceiveState(RecvState::APP_READY);
break;
default:
// Any other state is invalid (this function should not have been called).
Assume(false);
}
break;
default:
// Any other state is invalid (this function should not have been called).
Assume(false);
}
// Wipe the receive buffer where the next packet will be received into.
ClearShrink(m_recv_buffer);
Expand Down Expand Up @@ -1323,7 +1301,6 @@ size_t V2Transport::GetMaxBytesToProcess() noexcept
case RecvState::GARB_GARBTERM:
// Process garbage bytes one by one (because terminator may appear anywhere).
return 1;
case RecvState::GARBAUTH:
case RecvState::VERSION:
case RecvState::APP:
// These three states all involve decoding a packet. Process the length descriptor first,
Expand Down Expand Up @@ -1377,7 +1354,6 @@ bool V2Transport::ReceivedBytes(Span<const uint8_t>& msg_bytes) noexcept
// bytes).
m_recv_buffer.reserve(MAX_GARBAGE_LEN + BIP324Cipher::GARBAGE_TERMINATOR_LEN);
break;
case RecvState::GARBAUTH:
case RecvState::VERSION:
case RecvState::APP: {
// During states where a packet is being received, as much as is expected but never
Expand Down Expand Up @@ -1421,7 +1397,6 @@ bool V2Transport::ReceivedBytes(Span<const uint8_t>& msg_bytes) noexcept
if (!ProcessReceivedGarbageBytes()) return false;
break;

case RecvState::GARBAUTH:
case RecvState::VERSION:
case RecvState::APP:
if (!ProcessReceivedPacketBytes()) return false;
Expand Down
41 changes: 18 additions & 23 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -466,10 +466,10 @@ class V2Transport final : public Transport
*
* start(responder)
* |
* | start(initiator) /---------\
* | | | |
* v v v |
* KEY_MAYBE_V1 -> KEY -> GARB_GARBTERM -> GARBAUTH -> VERSION -> APP -> APP_READY
* | start(initiator) /---------\
* | | | |
* v v v |
* KEY_MAYBE_V1 -> KEY -> GARB_GARBTERM -> VERSION -> APP -> APP_READY
* |
* \-------> V1
*/
Expand All @@ -491,24 +491,19 @@ class V2Transport final : public Transport
/** Garbage and garbage terminator.
*
* Whenever a byte is received, the last 16 bytes are compared with the expected garbage
* terminator. When that happens, the state becomes GARBAUTH. If no matching terminator is
* terminator. When that happens, the state becomes VERSION. If no matching terminator is
* received in 4111 bytes (4095 for the maximum garbage length, and 16 bytes for the
* terminator), the connection aborts. */
GARB_GARBTERM,

/** Garbage authentication packet.
*
* A packet is received, and decrypted/verified with AAD set to the garbage received during
* the GARB_GARBTERM state. If that succeeds, the state becomes VERSION. If it fails the
* connection aborts. */
GARBAUTH,

/** Version packet.
*
* A packet is received, and decrypted/verified. If that succeeds, the state becomes APP,
* and the decrypted contents is interpreted as version negotiation (currently, that means
* ignoring it, but it can be used for negotiating future extensions). If it fails, the
* connection aborts. */
* A packet is received, and decrypted/verified. If that fails, the connection aborts. The
* first received packet in this state (whether it's a decoy or not) is expected to
* authenticate the garbage received during the GARB_GARBTERM state as associated
* authenticated data (AAD). The first non-decoy packet in this state is interpreted as
* version negotiation (currently, that means ignoring the contents, but it can be used for
* negotiating future extensions), and afterwards the state becomes APP. */
VERSION,

/** Application packet.
Expand Down Expand Up @@ -562,9 +557,9 @@ class V2Transport final : public Transport
/** Normal sending state.
*
* In this state, the ciphers are initialized, so packets can be sent. When this state is
* entered, the garbage terminator, garbage authentication packet, and version
* packet are appended to the send buffer (in addition to the key and garbage which may
* still be there). In this state a message can be provided if the send buffer is empty. */
* entered, the garbage terminator and version packet are appended to the send buffer (in
* addition to the key and garbage which may still be there). In this state a message can be
* provided if the send buffer is empty. */
READY,

/** This transport is using v1 fallback.
Expand All @@ -584,13 +579,13 @@ class V2Transport final : public Transport

/** Lock for receiver-side fields. */
mutable Mutex m_recv_mutex ACQUIRED_BEFORE(m_send_mutex);
/** In {GARBAUTH, VERSION, APP}, the decrypted packet length, if m_recv_buffer.size() >=
/** In {VERSION, APP}, the decrypted packet length, if m_recv_buffer.size() >=
* BIP324Cipher::LENGTH_LEN. Unspecified otherwise. */
uint32_t m_recv_len GUARDED_BY(m_recv_mutex) {0};
/** Receive buffer; meaning is determined by m_recv_state. */
std::vector<uint8_t> m_recv_buffer GUARDED_BY(m_recv_mutex);
/** During GARBAUTH, the garbage received during GARB_GARBTERM. */
std::vector<uint8_t> m_recv_garbage GUARDED_BY(m_recv_mutex);
/** AAD expected in next received packet (currently used only for garbage). */
std::vector<uint8_t> m_recv_aad GUARDED_BY(m_recv_mutex);
/** Buffer to put decrypted contents in, for converting to CNetMessage. */
std::vector<uint8_t> m_recv_decode_buffer GUARDED_BY(m_recv_mutex);
/** Deserialization type. */
Expand Down Expand Up @@ -630,7 +625,7 @@ class V2Transport final : public Transport
bool ProcessReceivedKeyBytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex, !m_send_mutex);
/** Process bytes in m_recv_buffer, while in GARB_GARBTERM state. */
bool ProcessReceivedGarbageBytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex);
/** Process bytes in m_recv_buffer, while in GARBAUTH/VERSION/APP state. */
/** Process bytes in m_recv_buffer, while in VERSION/APP state. */
bool ProcessReceivedPacketBytes() noexcept EXCLUSIVE_LOCKS_REQUIRED(m_recv_mutex);

public:
Expand Down
Loading

0 comments on commit 7cbe625

Please sign in to comment.