Skip to content

Commit

Permalink
feat: serialize on the stack
Browse files Browse the repository at this point in the history
  • Loading branch information
PastaPastaPasta committed Dec 17, 2024
1 parent cd115c2 commit 4d09138
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 32 deletions.
34 changes: 20 additions & 14 deletions src/bls/bls.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,17 +123,25 @@ class CBLSWrapper
cachedHash.SetNull();
}

std::vector<uint8_t> ToByteVector(const bool specificLegacyScheme) const
std::array<uint8_t, SerSize> ToBytes(const bool specificLegacyScheme) const
{
if (!fValid) {
return std::array<uint8_t, SerSize>{};
}
return impl.SerializeToArray(specificLegacyScheme);
}

std::vector<uint8_t> ToActualByteVector(const bool specificLegacyScheme) const
{
if (!fValid) {
return std::vector<uint8_t>(SerSize, 0);
}
return impl.Serialize(specificLegacyScheme);
}

std::vector<uint8_t> ToByteVector() const
std::array<uint8_t, SerSize> ToBytes() const
{
return ToByteVector(bls::bls_legacy_scheme.load());
return ToBytes(bls::bls_legacy_scheme.load());
}

const uint256& GetHash() const
Expand Down Expand Up @@ -167,7 +175,7 @@ class CBLSWrapper
template <typename Stream>
inline void Serialize(Stream& s, const bool specificLegacyScheme) const
{
s.write(AsBytes(Span{ToByteVector(specificLegacyScheme).data(), SerSize}));
s.write(AsBytes(Span{ToBytes(specificLegacyScheme)}));
}

template <typename Stream>
Expand Down Expand Up @@ -206,7 +214,7 @@ class CBLSWrapper

inline bool CheckMalleable(Span<uint8_t> vecBytes, const bool specificLegacyScheme) const
{
if (memcmp(vecBytes.data(), ToByteVector(specificLegacyScheme).data(), SerSize)) {
if (memcmp(vecBytes.data(), ToBytes(specificLegacyScheme).data(), SerSize)) {
// TODO not sure if this is actually possible with the BLS libs. I'm assuming here that somewhere deep inside
// these libs masking might happen, so that 2 different binary representations could result in the same object
// representation
Expand All @@ -222,7 +230,7 @@ class CBLSWrapper

inline std::string ToString(const bool specificLegacyScheme) const
{
std::vector<uint8_t> buf = ToByteVector(specificLegacyScheme);
auto buf = ToBytes(specificLegacyScheme);
return HexStr(buf);
}

Expand All @@ -245,10 +253,12 @@ struct CBLSIdImplicit : public uint256
memcpy(instance.begin(), buffer, sizeof(CBLSIdImplicit));
return instance;
}
[[nodiscard]] std::vector<uint8_t> Serialize(const bool fLegacy) const
[[nodiscard]] std::vector<uint8_t> SerializeToVec(const bool fLegacy) const
{
return {begin(), end()};
}
[[nodiscard]] std::array<uint8_t, WIDTH> Serialize(const bool fLegacy) const { return m_data; }
[[nodiscard]] std::array<uint8_t, WIDTH> SerializeToArray(const bool fLegacy) const { return Serialize(fLegacy); }
};

class CBLSId : public CBLSWrapper<CBLSIdImplicit, BLS_CURVE_ID_SIZE, CBLSId>
Expand Down Expand Up @@ -396,7 +406,7 @@ class CBLSLazyWrapper
private:
mutable std::mutex mutex;

mutable std::vector<uint8_t> vecBytes;
mutable std::array<uint8_t, BLSObject::SerSize> vecBytes{};
mutable bool bufValid{false};
mutable bool bufLegacyScheme{true};

Expand All @@ -407,7 +417,6 @@ class CBLSLazyWrapper

public:
CBLSLazyWrapper() :
vecBytes(BLSObject::SerSize, 0),
bufLegacyScheme(bls::bls_legacy_scheme.load())
{}

Expand All @@ -425,7 +434,6 @@ class CBLSLazyWrapper
if (r.bufValid) {
vecBytes = r.vecBytes;
} else {
vecBytes.resize(BLSObject::SerSize);
std::fill(vecBytes.begin(), vecBytes.end(), 0);
}
objInitialized = r.objInitialized;
Expand All @@ -448,10 +456,9 @@ class CBLSLazyWrapper
{
std::unique_lock<std::mutex> l(mutex);
if (!objInitialized && !bufValid) {
vecBytes.resize(BLSObject::SerSize);
std::fill(vecBytes.begin(), vecBytes.end(), 0);
} else if (!bufValid || (bufLegacyScheme != specificLegacyScheme)) {
vecBytes = obj.ToByteVector(specificLegacyScheme);
vecBytes = obj.ToBytes(specificLegacyScheme);
bufValid = true;
bufLegacyScheme = specificLegacyScheme;
hash.SetNull();
Expand Down Expand Up @@ -533,11 +540,10 @@ class CBLSLazyWrapper
{
std::unique_lock<std::mutex> l(mutex);
if (!objInitialized && !bufValid) {
vecBytes.resize(BLSObject::SerSize);
std::fill(vecBytes.begin(), vecBytes.end(), 0);
hash.SetNull();
} else if (!bufValid) {
vecBytes = obj.ToByteVector(bufLegacyScheme);
vecBytes = obj.ToBytes(bufLegacyScheme);
bufValid = true;
hash.SetNull();
}
Expand Down
15 changes: 5 additions & 10 deletions src/bls/bls_ies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ bool CBLSIESEncryptedBlob::Encrypt(size_t idx, const CBLSPublicKey& peerPubKey,
return false;
}

std::vector<unsigned char> symKey = pk.ToByteVector();
symKey.resize(32);
auto symKey = pk.ToBytes();

uint256 iv = GetIV(idx);
return EncryptBlob(plainTextData, dataSize, data, symKey.data(), iv.begin());
Expand All @@ -63,10 +62,9 @@ bool CBLSIESEncryptedBlob::Decrypt(size_t idx, const CBLSSecretKey& secretKey, C
return false;
}

std::vector<unsigned char> symKey = pk.ToByteVector();
symKey.resize(32);

uint256 iv = GetIV(idx);
auto symKey = pk.ToBytes();

return DecryptBlob(data.data(), data.size(), decryptedDataRet, symKey.data(), iv.begin());
}

Expand Down Expand Up @@ -117,8 +115,7 @@ bool CBLSIESMultiRecipientBlobs::Encrypt(size_t idx, const CBLSPublicKey& recipi
return false;
}

std::vector<uint8_t> symKey = pk.ToByteVector();
symKey.resize(32);
auto symKey = pk.ToBytes();

return EncryptBlob(blob.data(), blob.size(), blobs[idx], symKey.data(), ivVector[idx].begin());
}
Expand All @@ -134,13 +131,11 @@ bool CBLSIESMultiRecipientBlobs::Decrypt(size_t idx, const CBLSSecretKey& sk, Bl
return false;
}

std::vector<uint8_t> symKey = pk.ToByteVector();
symKey.resize(32);

uint256 iv = ivSeed;
for (size_t i = 0; i < idx; i++) {
iv = ::SerializeHash(iv);
}
auto symKey = pk.ToBytes();

return DecryptBlob(blobs[idx].data(), blobs[idx].size(), blobRet, symKey.data(), iv.begin());
}
4 changes: 2 additions & 2 deletions src/coinjoin/coinjoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ bool CCoinJoinQueue::Sign(const CActiveMasternodeManager& mn_activeman)
if (!sig.IsValid()) {
return false;
}
vchSig = sig.ToByteVector(false);
vchSig = sig.ToBytes(false);

return true;
}
Expand Down Expand Up @@ -94,7 +94,7 @@ bool CCoinJoinBroadcastTx::Sign(const CActiveMasternodeManager& mn_activeman)
if (!sig.IsValid()) {
return false;
}
vchSig = sig.ToByteVector(false);
vchSig = sig.ToBytes(false);

return true;
}
Expand Down
5 changes: 3 additions & 2 deletions src/coinjoin/coinjoin.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <coinjoin/common.h>

#include <bls/bls.h>
#include <core_io.h>
#include <netaddress.h>
#include <primitives/block.h>
Expand Down Expand Up @@ -183,7 +184,7 @@ class CCoinJoinQueue
uint256 m_protxHash;
int64_t nTime{0};
bool fReady{false}; //ready for submit
std::vector<unsigned char> vchSig;
std::array<unsigned char, BLS_CURVE_SIG_SIZE> vchSig;
// memory only
bool fTried{false};

Expand Down Expand Up @@ -243,7 +244,7 @@ class CCoinJoinBroadcastTx
CTransactionRef tx;
COutPoint masternodeOutpoint;
uint256 m_protxHash;
std::vector<unsigned char> vchSig;
std::array<unsigned char, BLS_CURVE_SIG_SIZE> vchSig;
int64_t sigTime{0};
CCoinJoinBroadcastTx() :
tx(MakeTransactionRef(CMutableTransaction{}))
Expand Down
2 changes: 1 addition & 1 deletion src/governance/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ bool CGovernanceObject::Sign(const CActiveMasternodeManager& mn_activeman)
if (!sig.IsValid()) {
return false;
}
m_obj.vchSig = sig.ToByteVector(false);
m_obj.vchSig = sig.ToActualByteVector(false);
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion src/governance/vote.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ bool CGovernanceVote::Sign(const CActiveMasternodeManager& mn_activeman)
if (!sig.IsValid()) {
return false;
}
vchSig = sig.ToByteVector(false);
vchSig = sig.ToActualByteVector(false);
return true;
}

Expand Down
4 changes: 2 additions & 2 deletions src/llmq/dkgsession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1017,12 +1017,12 @@ void CDKGSession::SendCommitment(CDKGPendingMessages& pendingMessages)

if (lieType == 3) {
const bool is_bls_legacy = bls::bls_legacy_scheme.load();
std::vector<uint8_t> buf = qc.sig.ToByteVector(is_bls_legacy);
auto buf = qc.sig.ToBytes(is_bls_legacy);
buf[5]++;
qc.sig.SetByteVector(buf, is_bls_legacy);
} else if (lieType == 4) {
const bool is_bls_legacy = bls::bls_legacy_scheme.load();
std::vector<uint8_t> buf = qc.quorumSig.ToByteVector(is_bls_legacy);
auto buf = qc.quorumSig.ToBytes(is_bls_legacy);
buf[5]++;
qc.quorumSig.SetByteVector(buf, is_bls_legacy);
}
Expand Down
51 changes: 51 additions & 0 deletions src/serialize.h
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,9 @@ template<typename Stream, unsigned int N, typename T> inline void Unserialize(St
template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v);
template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v);

template <typename Stream, typename T, std::size_t N> void Serialize(Stream& os, const std::array<T, N>& a);
template <typename Stream, typename T, std::size_t N> void Unserialize(Stream& is, std::array<T, N>& a);

/**
* pair
*/
Expand Down Expand Up @@ -1028,6 +1031,54 @@ void Unserialize(Stream& is, std::vector<T, A>& v)
}
}

/**
* array
*/
template <typename Stream, typename T, std::size_t N>
void Serialize(Stream& os, const std::array<T, N>& a)
{
if constexpr (std::is_same_v<T, unsigned char>) {
// Directly write the byte data without writing the size
if (!a.empty()) {
os.write(MakeByteSpan(a));
}
}
else if constexpr (std::is_same_v<T, bool>) {
// Serialize each bool individually
for (const bool& elem : a) {
::Serialize(os, elem);
}
}
else {
// Serialize each element using the default Serialize function
for (const T& elem : a) {
::Serialize(os, elem);
}
}
}

template <typename Stream, typename T, std::size_t N>
void Unserialize(Stream& is, std::array<T, N>& a)
{
if constexpr (std::is_same_v<T, unsigned char>) {
// Directly read the byte data without reading the size
if (N > 0) {
is.read(AsWritableBytes(Span{a}));
}
}
else if constexpr (std::is_same_v<T, bool>) {
// Unserialize each bool individually
for (bool& elem : a) {
::Unserialize(is, elem);
}
}
else {
// Unserialize each element using the default Unserialize function
for (T& elem : a) {
::Unserialize(is, elem);
}
}
}

/**
* pair
Expand Down

0 comments on commit 4d09138

Please sign in to comment.