Merge #20464: refactor: Treat CDataStream bytes as uint8_t

fa29272459 Remove redundant MakeUCharSpan wrappers (MarcoFalke)
faf4aa2f47 Remove CDataStream::Init in favor of C++11 member initialization (MarcoFalke)
fada14b948 Treat CDataStream bytes as uint8_t (MarcoFalke)
fa8bdb048e refactor: Drop CDataStream constructors in favor of one taking a Span of bytes (MarcoFalke)
faa96f841f Remove unused CDataStream methods (MarcoFalke)

Pull request description:

  Using `uint8_t` for raw bytes has a style benefit:
  * The signedness is clear from reading the code, as it does not depend on the architecture

  Other clean-ups in this pull include:
  * Remove unused methods
  * Constructor is simplified with `Span`
  * Remove `Init()` member in favor of C++11 member initialization

ACKs for top commit:
  laanwj:
    code review ACK fa29272459
  theStack:
    ACK fa29272459 🍾

Tree-SHA512: 931ee28bd99843d7e894b48e90e1187ffb0278677c267044b3c0c255069d9bbd9298ab2e539b1002a30b543d240450eaec718ef4ee95a7fd4be0a295e926343f
This commit is contained in:
Wladimir J. van der Laan 2021-02-01 15:05:56 +01:00
commit 2c0fc856a6
No known key found for this signature in database
GPG key ID: 1E4AED62986CD25D
13 changed files with 63 additions and 122 deletions

View file

@ -76,7 +76,7 @@ static void PrevectorDeserialize(benchmark::Bench& bench)
for (auto x = 0; x < 1000; ++x) {
s0 >> t1;
}
s0.Init(SER_NETWORK, 0);
s0.Rewind();
});
}

View file

@ -8,9 +8,10 @@
#include <clientversion.h>
#include <fs.h>
#include <serialize.h>
#include <span.h>
#include <streams.h>
#include <util/system.h>
#include <util/strencodings.h>
#include <util/system.h>
#include <leveldb/db.h>
#include <leveldb/write_batch.h>
@ -73,12 +74,12 @@ public:
{
ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
ssKey << key;
leveldb::Slice slKey(ssKey.data(), ssKey.size());
leveldb::Slice slKey((const char*)ssKey.data(), ssKey.size());
ssValue.reserve(DBWRAPPER_PREALLOC_VALUE_SIZE);
ssValue << value;
ssValue.Xor(dbwrapper_private::GetObfuscateKey(parent));
leveldb::Slice slValue(ssValue.data(), ssValue.size());
leveldb::Slice slValue((const char*)ssValue.data(), ssValue.size());
batch.Put(slKey, slValue);
// LevelDB serializes writes as:
@ -98,7 +99,7 @@ public:
{
ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
ssKey << key;
leveldb::Slice slKey(ssKey.data(), ssKey.size());
leveldb::Slice slKey((const char*)ssKey.data(), ssKey.size());
batch.Delete(slKey);
// LevelDB serializes erases as:
@ -137,7 +138,7 @@ public:
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
ssKey << key;
leveldb::Slice slKey(ssKey.data(), ssKey.size());
leveldb::Slice slKey((const char*)ssKey.data(), ssKey.size());
piter->Seek(slKey);
}
@ -146,7 +147,7 @@ public:
template<typename K> bool GetKey(K& key) {
leveldb::Slice slKey = piter->key();
try {
CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
CDataStream ssKey(MakeUCharSpan(slKey), SER_DISK, CLIENT_VERSION);
ssKey >> key;
} catch (const std::exception&) {
return false;
@ -157,7 +158,7 @@ public:
template<typename V> bool GetValue(V& value) {
leveldb::Slice slValue = piter->value();
try {
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
CDataStream ssValue(MakeUCharSpan(slValue), SER_DISK, CLIENT_VERSION);
ssValue.Xor(dbwrapper_private::GetObfuscateKey(parent));
ssValue >> value;
} catch (const std::exception&) {
@ -232,7 +233,7 @@ public:
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
ssKey << key;
leveldb::Slice slKey(ssKey.data(), ssKey.size());
leveldb::Slice slKey((const char*)ssKey.data(), ssKey.size());
std::string strValue;
leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
@ -243,7 +244,7 @@ public:
dbwrapper_private::HandleError(status);
}
try {
CDataStream ssValue(strValue.data(), strValue.data() + strValue.size(), SER_DISK, CLIENT_VERSION);
CDataStream ssValue(MakeUCharSpan(strValue), SER_DISK, CLIENT_VERSION);
ssValue.Xor(obfuscate_key);
ssValue >> value;
} catch (const std::exception&) {
@ -266,7 +267,7 @@ public:
CDataStream ssKey(SER_DISK, CLIENT_VERSION);
ssKey.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
ssKey << key;
leveldb::Slice slKey(ssKey.data(), ssKey.size());
leveldb::Slice slKey((const char*)ssKey.data(), ssKey.size());
std::string strValue;
leveldb::Status status = pdb->Get(readoptions, slKey, &strValue);
@ -310,8 +311,8 @@ public:
ssKey2.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
ssKey1 << key_begin;
ssKey2 << key_end;
leveldb::Slice slKey1(ssKey1.data(), ssKey1.size());
leveldb::Slice slKey2(ssKey2.data(), ssKey2.size());
leveldb::Slice slKey1((const char*)ssKey1.data(), ssKey1.size());
leveldb::Slice slKey2((const char*)ssKey2.data(), ssKey2.size());
uint64_t size = 0;
leveldb::Range range(slKey1, slKey2);
pdb->GetApproximateSizes(&range, 1, &size);
@ -329,11 +330,10 @@ public:
ssKey2.reserve(DBWRAPPER_PREALLOC_KEY_SIZE);
ssKey1 << key_begin;
ssKey2 << key_end;
leveldb::Slice slKey1(ssKey1.data(), ssKey1.size());
leveldb::Slice slKey2(ssKey2.data(), ssKey2.size());
leveldb::Slice slKey1((const char*)ssKey1.data(), ssKey1.size());
leveldb::Slice slKey2((const char*)ssKey2.data(), ssKey2.size());
pdb->CompactRange(&slKey1, &slKey2);
}
};
#endif // BITCOIN_DBWRAPPER_H

View file

@ -363,7 +363,7 @@ bool DecodeBase64PSBT(PartiallySignedTransaction& psbt, const std::string& base6
bool DecodeRawPSBT(PartiallySignedTransaction& psbt, const std::string& tx_data, std::string& error)
{
CDataStream ss_data(tx_data.data(), tx_data.data() + tx_data.size(), SER_NETWORK, PROTOCOL_VERSION);
CDataStream ss_data(MakeUCharSpan(tx_data), SER_NETWORK, PROTOCOL_VERSION);
try {
ss_data >> psbt;
if (!ss_data.empty()) {

View file

@ -181,7 +181,7 @@ void RecentRequestsTableModel::addNewRequest(const SendCoinsRecipient &recipient
// called from ctor when loading from wallet
void RecentRequestsTableModel::addNewRequest(const std::string &recipient)
{
std::vector<char> data(recipient.begin(), recipient.end());
std::vector<uint8_t> data(recipient.begin(), recipient.end());
CDataStream ss(data, SER_DISK, CLIENT_VERSION);
RecentRequestEntry entry;

View file

@ -245,7 +245,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
ssTx << *newTx;
transaction_array.append(&(ssTx[0]), ssTx.size());
transaction_array.append((const char*)&(ssTx[0]), ssTx.size());
}
// Add addresses / update labels that we've sent to the address book,

View file

@ -1345,7 +1345,7 @@ static RPCHelpMan combinepsbt()
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
ssTx << merged_psbt;
return EncodeBase64(MakeUCharSpan(ssTx));
return EncodeBase64(ssTx);
},
};
}
@ -1484,7 +1484,7 @@ static RPCHelpMan createpsbt()
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
ssTx << psbtx;
return EncodeBase64(MakeUCharSpan(ssTx));
return EncodeBase64(ssTx);
},
};
}
@ -1553,7 +1553,7 @@ static RPCHelpMan converttopsbt()
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
ssTx << psbtx;
return EncodeBase64(MakeUCharSpan(ssTx));
return EncodeBase64(ssTx);
},
};
}
@ -1644,7 +1644,7 @@ static RPCHelpMan utxoupdatepsbt()
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
ssTx << psbtx;
return EncodeBase64(MakeUCharSpan(ssTx));
return EncodeBase64(ssTx);
},
};
}
@ -1740,7 +1740,7 @@ static RPCHelpMan joinpsbts()
CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION);
ssTx << shuffled_psbt;
return EncodeBase64(MakeUCharSpan(ssTx));
return EncodeBase64(ssTx);
},
};
}

View file

@ -6,17 +6,19 @@
#ifndef BITCOIN_STREAMS_H
#define BITCOIN_STREAMS_H
#include <support/allocators/zeroafterfree.h>
#include <serialize.h>
#include <span.h>
#include <support/allocators/zeroafterfree.h>
#include <algorithm>
#include <assert.h>
#include <ios>
#include <limits>
#include <optional>
#include <stdint.h>
#include <stdio.h>
#include <string>
#include <string.h>
#include <string>
#include <utility>
#include <vector>
@ -202,14 +204,14 @@ public:
class CDataStream
{
protected:
typedef CSerializeData vector_type;
using vector_type = SerializeData;
vector_type vch;
unsigned int nReadPos;
unsigned int nReadPos{0};
int nType;
int nVersion;
public:
public:
typedef vector_type::allocator_type allocator_type;
typedef vector_type::size_type size_type;
typedef vector_type::difference_type difference_type;
@ -221,62 +223,22 @@ public:
typedef vector_type::reverse_iterator reverse_iterator;
explicit CDataStream(int nTypeIn, int nVersionIn)
{
Init(nTypeIn, nVersionIn);
}
: nType{nTypeIn},
nVersion{nVersionIn} {}
CDataStream(const_iterator pbegin, const_iterator pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend)
{
Init(nTypeIn, nVersionIn);
}
CDataStream(const char* pbegin, const char* pend, int nTypeIn, int nVersionIn) : vch(pbegin, pend)
{
Init(nTypeIn, nVersionIn);
}
CDataStream(const vector_type& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end())
{
Init(nTypeIn, nVersionIn);
}
CDataStream(const std::vector<char>& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end())
{
Init(nTypeIn, nVersionIn);
}
CDataStream(const std::vector<unsigned char>& vchIn, int nTypeIn, int nVersionIn) : vch(vchIn.begin(), vchIn.end())
{
Init(nTypeIn, nVersionIn);
}
explicit CDataStream(Span<const uint8_t> sp, int nTypeIn, int nVersionIn)
: vch(sp.data(), sp.data() + sp.size()),
nType{nTypeIn},
nVersion{nVersionIn} {}
template <typename... Args>
CDataStream(int nTypeIn, int nVersionIn, Args&&... args)
: nType{nTypeIn},
nVersion{nVersionIn}
{
Init(nTypeIn, nVersionIn);
::SerializeMany(*this, std::forward<Args>(args)...);
}
void Init(int nTypeIn, int nVersionIn)
{
nReadPos = 0;
nType = nTypeIn;
nVersion = nVersionIn;
}
CDataStream& operator+=(const CDataStream& b)
{
vch.insert(vch.end(), b.begin(), b.end());
return *this;
}
friend CDataStream operator+(const CDataStream& a, const CDataStream& b)
{
CDataStream ret = a;
ret += b;
return (ret);
}
std::string str() const
{
return (std::string(begin(), end()));
@ -297,12 +259,12 @@ public:
const_reference operator[](size_type pos) const { return vch[pos + nReadPos]; }
reference operator[](size_type pos) { return vch[pos + nReadPos]; }
void clear() { vch.clear(); nReadPos = 0; }
iterator insert(iterator it, const char x=char()) { return vch.insert(it, x); }
void insert(iterator it, size_type n, const char x) { vch.insert(it, n, x); }
iterator insert(iterator it, const uint8_t x) { return vch.insert(it, x); }
void insert(iterator it, size_type n, const uint8_t x) { vch.insert(it, n, x); }
value_type* data() { return vch.data() + nReadPos; }
const value_type* data() const { return vch.data() + nReadPos; }
void insert(iterator it, std::vector<char>::const_iterator first, std::vector<char>::const_iterator last)
void insert(iterator it, std::vector<uint8_t>::const_iterator first, std::vector<uint8_t>::const_iterator last)
{
if (last == first) return;
assert(last - first > 0);
@ -373,12 +335,17 @@ public:
nReadPos = 0;
}
bool Rewind(size_type n)
bool Rewind(std::optional<size_type> n = std::nullopt)
{
// Total rewind if no size is passed
if (!n) {
nReadPos = 0;
return true;
}
// Rewind by n characters if the buffer hasn't been compacted yet
if (n > nReadPos)
if (*n > nReadPos)
return false;
nReadPos -= n;
nReadPos -= *n;
return true;
}
@ -462,11 +429,6 @@ public:
return (*this);
}
void GetAndClear(CSerializeData &d) {
d.insert(d.end(), begin(), end());
clear();
}
/**
* XOR the contents of this stream with a certain key.
*

View file

@ -42,7 +42,7 @@ struct zero_after_free_allocator : public std::allocator<T> {
}
};
// Byte-vector that clears its contents before deletion.
typedef std::vector<char, zero_after_free_allocator<char> > CSerializeData;
/** Byte-vector that clears its contents before deletion. */
using SerializeData = std::vector<uint8_t, zero_after_free_allocator<uint8_t>>;
#endif // BITCOIN_SUPPORT_ALLOCATORS_ZEROAFTERFREE_H

View file

@ -42,11 +42,7 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize)
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
stream << filter;
std::vector<unsigned char> vch = ParseHex("03614e9b050000000000000001");
std::vector<char> expected(vch.size());
for (unsigned int i = 0; i < vch.size(); i++)
expected[i] = (char)vch[i];
std::vector<uint8_t> expected = ParseHex("03614e9b050000000000000001");
BOOST_CHECK_EQUAL_COLLECTIONS(stream.begin(), stream.end(), expected.begin(), expected.end());
@ -72,11 +68,7 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak)
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
stream << filter;
std::vector<unsigned char> vch = ParseHex("03ce4299050000000100008001");
std::vector<char> expected(vch.size());
for (unsigned int i = 0; i < vch.size(); i++)
expected[i] = (char)vch[i];
std::vector<uint8_t> expected = ParseHex("03ce4299050000000100008001");
BOOST_CHECK_EQUAL_COLLECTIONS(stream.begin(), stream.end(), expected.begin(), expected.end());
}
@ -96,11 +88,7 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_key)
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
stream << filter;
std::vector<unsigned char> vch = ParseHex("038fc16b080000000000000001");
std::vector<char> expected(vch.size());
for (unsigned int i = 0; i < vch.size(); i++)
expected[i] = (char)vch[i];
std::vector<unsigned char> expected = ParseHex("038fc16b080000000000000001");
BOOST_CHECK_EQUAL_COLLECTIONS(stream.begin(), stream.end(), expected.begin(), expected.end());
}
@ -352,11 +340,7 @@ BOOST_AUTO_TEST_CASE(merkle_block_3_and_serialize)
CDataStream merkleStream(SER_NETWORK, PROTOCOL_VERSION);
merkleStream << merkleBlock;
std::vector<unsigned char> vch = ParseHex("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630100000001b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f19630101");
std::vector<char> expected(vch.size());
for (unsigned int i = 0; i < vch.size(); i++)
expected[i] = (char)vch[i];
std::vector<uint8_t> expected = ParseHex("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630100000001b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f19630101");
BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), merkleStream.begin(), merkleStream.end());
}

View file

@ -61,7 +61,7 @@ void CallOneOf(FuzzedDataProvider& fuzzed_data_provider, Callables... callables)
[[nodiscard]] inline CDataStream ConsumeDataStream(FuzzedDataProvider& fuzzed_data_provider, const size_t max_length = 4096) noexcept
{
return {ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length), SER_NETWORK, INIT_PROTO_VERSION};
return CDataStream{ConsumeRandomLengthByteVector(fuzzed_data_provider, max_length), SER_NETWORK, INIT_PROTO_VERSION};
}
[[nodiscard]] inline std::vector<std::string> ConsumeRandomLengthStringVector(FuzzedDataProvider& fuzzed_data_provider, const size_t max_vector_size = 16, const size_t max_string_length = 16) noexcept

View file

@ -320,7 +320,7 @@ BOOST_AUTO_TEST_CASE(insert_delete)
ss.insert(ss.end(), c);
BOOST_CHECK_EQUAL(ss.size(), 6U);
BOOST_CHECK_EQUAL(ss[4], (char)0xff);
BOOST_CHECK_EQUAL(ss[4], 0xff);
BOOST_CHECK_EQUAL(ss[5], c);
ss.insert(ss.begin()+2, c);
@ -334,19 +334,14 @@ BOOST_AUTO_TEST_CASE(insert_delete)
ss.erase(ss.begin()+ss.size()-1);
BOOST_CHECK_EQUAL(ss.size(), 5U);
BOOST_CHECK_EQUAL(ss[4], (char)0xff);
BOOST_CHECK_EQUAL(ss[4], 0xff);
ss.erase(ss.begin()+1);
BOOST_CHECK_EQUAL(ss.size(), 4U);
BOOST_CHECK_EQUAL(ss[0], 0);
BOOST_CHECK_EQUAL(ss[1], 1);
BOOST_CHECK_EQUAL(ss[2], 2);
BOOST_CHECK_EQUAL(ss[3], (char)0xff);
// Make sure GetAndClear does the right thing:
CSerializeData d;
ss.GetAndClear(d);
BOOST_CHECK_EQUAL(ss.size(), 0U);
BOOST_CHECK_EQUAL(ss[3], 0xff);
}
BOOST_AUTO_TEST_CASE(class_methods)

View file

@ -149,7 +149,7 @@ BOOST_AUTO_TEST_CASE(bitstream_reader_writer)
BOOST_AUTO_TEST_CASE(streams_serializedata_xor)
{
std::vector<char> in;
std::vector<uint8_t> in;
std::vector<char> expected_xor;
std::vector<unsigned char> key;
CDataStream ds(in, 0, 0);

View file

@ -488,9 +488,9 @@ bool BerkeleyDatabase::Rewrite(const char* pszSkip)
break;
}
if (pszSkip &&
strncmp(ssKey.data(), pszSkip, std::min(ssKey.size(), strlen(pszSkip))) == 0)
strncmp((const char*)ssKey.data(), pszSkip, std::min(ssKey.size(), strlen(pszSkip))) == 0)
continue;
if (strncmp(ssKey.data(), "\x07version", 8) == 0) {
if (strncmp((const char*)ssKey.data(), "\x07version", 8) == 0) {
// Update version:
ssValue.clear();
ssValue << CLIENT_VERSION;