Skip to content

Commit 4d09138

Browse files
feat: serialize on the stack
1 parent cd115c2 commit 4d09138

File tree

8 files changed

+85
-32
lines changed

8 files changed

+85
-32
lines changed

src/bls/bls.h

+20-14
Original file line numberDiff line numberDiff line change
@@ -123,17 +123,25 @@ class CBLSWrapper
123123
cachedHash.SetNull();
124124
}
125125

126-
std::vector<uint8_t> ToByteVector(const bool specificLegacyScheme) const
126+
std::array<uint8_t, SerSize> ToBytes(const bool specificLegacyScheme) const
127+
{
128+
if (!fValid) {
129+
return std::array<uint8_t, SerSize>{};
130+
}
131+
return impl.SerializeToArray(specificLegacyScheme);
132+
}
133+
134+
std::vector<uint8_t> ToActualByteVector(const bool specificLegacyScheme) const
127135
{
128136
if (!fValid) {
129137
return std::vector<uint8_t>(SerSize, 0);
130138
}
131139
return impl.Serialize(specificLegacyScheme);
132140
}
133141

134-
std::vector<uint8_t> ToByteVector() const
142+
std::array<uint8_t, SerSize> ToBytes() const
135143
{
136-
return ToByteVector(bls::bls_legacy_scheme.load());
144+
return ToBytes(bls::bls_legacy_scheme.load());
137145
}
138146

139147
const uint256& GetHash() const
@@ -167,7 +175,7 @@ class CBLSWrapper
167175
template <typename Stream>
168176
inline void Serialize(Stream& s, const bool specificLegacyScheme) const
169177
{
170-
s.write(AsBytes(Span{ToByteVector(specificLegacyScheme).data(), SerSize}));
178+
s.write(AsBytes(Span{ToBytes(specificLegacyScheme)}));
171179
}
172180

173181
template <typename Stream>
@@ -206,7 +214,7 @@ class CBLSWrapper
206214

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

223231
inline std::string ToString(const bool specificLegacyScheme) const
224232
{
225-
std::vector<uint8_t> buf = ToByteVector(specificLegacyScheme);
233+
auto buf = ToBytes(specificLegacyScheme);
226234
return HexStr(buf);
227235
}
228236

@@ -245,10 +253,12 @@ struct CBLSIdImplicit : public uint256
245253
memcpy(instance.begin(), buffer, sizeof(CBLSIdImplicit));
246254
return instance;
247255
}
248-
[[nodiscard]] std::vector<uint8_t> Serialize(const bool fLegacy) const
256+
[[nodiscard]] std::vector<uint8_t> SerializeToVec(const bool fLegacy) const
249257
{
250258
return {begin(), end()};
251259
}
260+
[[nodiscard]] std::array<uint8_t, WIDTH> Serialize(const bool fLegacy) const { return m_data; }
261+
[[nodiscard]] std::array<uint8_t, WIDTH> SerializeToArray(const bool fLegacy) const { return Serialize(fLegacy); }
252262
};
253263

254264
class CBLSId : public CBLSWrapper<CBLSIdImplicit, BLS_CURVE_ID_SIZE, CBLSId>
@@ -396,7 +406,7 @@ class CBLSLazyWrapper
396406
private:
397407
mutable std::mutex mutex;
398408

399-
mutable std::vector<uint8_t> vecBytes;
409+
mutable std::array<uint8_t, BLSObject::SerSize> vecBytes{};
400410
mutable bool bufValid{false};
401411
mutable bool bufLegacyScheme{true};
402412

@@ -407,7 +417,6 @@ class CBLSLazyWrapper
407417

408418
public:
409419
CBLSLazyWrapper() :
410-
vecBytes(BLSObject::SerSize, 0),
411420
bufLegacyScheme(bls::bls_legacy_scheme.load())
412421
{}
413422

@@ -425,7 +434,6 @@ class CBLSLazyWrapper
425434
if (r.bufValid) {
426435
vecBytes = r.vecBytes;
427436
} else {
428-
vecBytes.resize(BLSObject::SerSize);
429437
std::fill(vecBytes.begin(), vecBytes.end(), 0);
430438
}
431439
objInitialized = r.objInitialized;
@@ -448,10 +456,9 @@ class CBLSLazyWrapper
448456
{
449457
std::unique_lock<std::mutex> l(mutex);
450458
if (!objInitialized && !bufValid) {
451-
vecBytes.resize(BLSObject::SerSize);
452459
std::fill(vecBytes.begin(), vecBytes.end(), 0);
453460
} else if (!bufValid || (bufLegacyScheme != specificLegacyScheme)) {
454-
vecBytes = obj.ToByteVector(specificLegacyScheme);
461+
vecBytes = obj.ToBytes(specificLegacyScheme);
455462
bufValid = true;
456463
bufLegacyScheme = specificLegacyScheme;
457464
hash.SetNull();
@@ -533,11 +540,10 @@ class CBLSLazyWrapper
533540
{
534541
std::unique_lock<std::mutex> l(mutex);
535542
if (!objInitialized && !bufValid) {
536-
vecBytes.resize(BLSObject::SerSize);
537543
std::fill(vecBytes.begin(), vecBytes.end(), 0);
538544
hash.SetNull();
539545
} else if (!bufValid) {
540-
vecBytes = obj.ToByteVector(bufLegacyScheme);
546+
vecBytes = obj.ToBytes(bufLegacyScheme);
541547
bufValid = true;
542548
hash.SetNull();
543549
}

src/bls/bls_ies.cpp

+5-10
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ bool CBLSIESEncryptedBlob::Encrypt(size_t idx, const CBLSPublicKey& peerPubKey,
4949
return false;
5050
}
5151

52-
std::vector<unsigned char> symKey = pk.ToByteVector();
53-
symKey.resize(32);
52+
auto symKey = pk.ToBytes();
5453

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

66-
std::vector<unsigned char> symKey = pk.ToByteVector();
67-
symKey.resize(32);
68-
6965
uint256 iv = GetIV(idx);
66+
auto symKey = pk.ToBytes();
67+
7068
return DecryptBlob(data.data(), data.size(), decryptedDataRet, symKey.data(), iv.begin());
7169
}
7270

@@ -117,8 +115,7 @@ bool CBLSIESMultiRecipientBlobs::Encrypt(size_t idx, const CBLSPublicKey& recipi
117115
return false;
118116
}
119117

120-
std::vector<uint8_t> symKey = pk.ToByteVector();
121-
symKey.resize(32);
118+
auto symKey = pk.ToBytes();
122119

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

137-
std::vector<uint8_t> symKey = pk.ToByteVector();
138-
symKey.resize(32);
139-
140134
uint256 iv = ivSeed;
141135
for (size_t i = 0; i < idx; i++) {
142136
iv = ::SerializeHash(iv);
143137
}
138+
auto symKey = pk.ToBytes();
144139

145140
return DecryptBlob(blobs[idx].data(), blobs[idx].size(), blobRet, symKey.data(), iv.begin());
146141
}

src/coinjoin/coinjoin.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ bool CCoinJoinQueue::Sign(const CActiveMasternodeManager& mn_activeman)
5555
if (!sig.IsValid()) {
5656
return false;
5757
}
58-
vchSig = sig.ToByteVector(false);
58+
vchSig = sig.ToBytes(false);
5959

6060
return true;
6161
}
@@ -94,7 +94,7 @@ bool CCoinJoinBroadcastTx::Sign(const CActiveMasternodeManager& mn_activeman)
9494
if (!sig.IsValid()) {
9595
return false;
9696
}
97-
vchSig = sig.ToByteVector(false);
97+
vchSig = sig.ToBytes(false);
9898

9999
return true;
100100
}

src/coinjoin/coinjoin.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <coinjoin/common.h>
99

10+
#include <bls/bls.h>
1011
#include <core_io.h>
1112
#include <netaddress.h>
1213
#include <primitives/block.h>
@@ -183,7 +184,7 @@ class CCoinJoinQueue
183184
uint256 m_protxHash;
184185
int64_t nTime{0};
185186
bool fReady{false}; //ready for submit
186-
std::vector<unsigned char> vchSig;
187+
std::array<unsigned char, BLS_CURVE_SIG_SIZE> vchSig;
187188
// memory only
188189
bool fTried{false};
189190

@@ -243,7 +244,7 @@ class CCoinJoinBroadcastTx
243244
CTransactionRef tx;
244245
COutPoint masternodeOutpoint;
245246
uint256 m_protxHash;
246-
std::vector<unsigned char> vchSig;
247+
std::array<unsigned char, BLS_CURVE_SIG_SIZE> vchSig;
247248
int64_t sigTime{0};
248249
CCoinJoinBroadcastTx() :
249250
tx(MakeTransactionRef(CMutableTransaction{}))

src/governance/object.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ bool CGovernanceObject::Sign(const CActiveMasternodeManager& mn_activeman)
258258
if (!sig.IsValid()) {
259259
return false;
260260
}
261-
m_obj.vchSig = sig.ToByteVector(false);
261+
m_obj.vchSig = sig.ToActualByteVector(false);
262262
return true;
263263
}
264264

src/governance/vote.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ bool CGovernanceVote::Sign(const CActiveMasternodeManager& mn_activeman)
175175
if (!sig.IsValid()) {
176176
return false;
177177
}
178-
vchSig = sig.ToByteVector(false);
178+
vchSig = sig.ToActualByteVector(false);
179179
return true;
180180
}
181181

src/llmq/dkgsession.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1017,12 +1017,12 @@ void CDKGSession::SendCommitment(CDKGPendingMessages& pendingMessages)
10171017

10181018
if (lieType == 3) {
10191019
const bool is_bls_legacy = bls::bls_legacy_scheme.load();
1020-
std::vector<uint8_t> buf = qc.sig.ToByteVector(is_bls_legacy);
1020+
auto buf = qc.sig.ToBytes(is_bls_legacy);
10211021
buf[5]++;
10221022
qc.sig.SetByteVector(buf, is_bls_legacy);
10231023
} else if (lieType == 4) {
10241024
const bool is_bls_legacy = bls::bls_legacy_scheme.load();
1025-
std::vector<uint8_t> buf = qc.quorumSig.ToByteVector(is_bls_legacy);
1025+
auto buf = qc.quorumSig.ToBytes(is_bls_legacy);
10261026
buf[5]++;
10271027
qc.quorumSig.SetByteVector(buf, is_bls_legacy);
10281028
}

src/serialize.h

+51
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,9 @@ template<typename Stream, unsigned int N, typename T> inline void Unserialize(St
797797
template<typename Stream, typename T, typename A> inline void Serialize(Stream& os, const std::vector<T, A>& v);
798798
template<typename Stream, typename T, typename A> inline void Unserialize(Stream& is, std::vector<T, A>& v);
799799

800+
template <typename Stream, typename T, std::size_t N> void Serialize(Stream& os, const std::array<T, N>& a);
801+
template <typename Stream, typename T, std::size_t N> void Unserialize(Stream& is, std::array<T, N>& a);
802+
800803
/**
801804
* pair
802805
*/
@@ -1028,6 +1031,54 @@ void Unserialize(Stream& is, std::vector<T, A>& v)
10281031
}
10291032
}
10301033

1034+
/**
1035+
* array
1036+
*/
1037+
template <typename Stream, typename T, std::size_t N>
1038+
void Serialize(Stream& os, const std::array<T, N>& a)
1039+
{
1040+
if constexpr (std::is_same_v<T, unsigned char>) {
1041+
// Directly write the byte data without writing the size
1042+
if (!a.empty()) {
1043+
os.write(MakeByteSpan(a));
1044+
}
1045+
}
1046+
else if constexpr (std::is_same_v<T, bool>) {
1047+
// Serialize each bool individually
1048+
for (const bool& elem : a) {
1049+
::Serialize(os, elem);
1050+
}
1051+
}
1052+
else {
1053+
// Serialize each element using the default Serialize function
1054+
for (const T& elem : a) {
1055+
::Serialize(os, elem);
1056+
}
1057+
}
1058+
}
1059+
1060+
template <typename Stream, typename T, std::size_t N>
1061+
void Unserialize(Stream& is, std::array<T, N>& a)
1062+
{
1063+
if constexpr (std::is_same_v<T, unsigned char>) {
1064+
// Directly read the byte data without reading the size
1065+
if (N > 0) {
1066+
is.read(AsWritableBytes(Span{a}));
1067+
}
1068+
}
1069+
else if constexpr (std::is_same_v<T, bool>) {
1070+
// Unserialize each bool individually
1071+
for (bool& elem : a) {
1072+
::Unserialize(is, elem);
1073+
}
1074+
}
1075+
else {
1076+
// Unserialize each element using the default Unserialize function
1077+
for (T& elem : a) {
1078+
::Unserialize(is, elem);
1079+
}
1080+
}
1081+
}
10311082

10321083
/**
10331084
* pair

0 commit comments

Comments
 (0)