From 689f1aee80cee4ede852eba4d39320a42d391585 Mon Sep 17 00:00:00 2001 From: Peter Bushnell Date: Tue, 8 Mar 2022 16:48:22 +0000 Subject: [PATCH 1/2] Remove VLA and resolve warnings in SPV --- src/spv/bitcoin/BRMerkleBlock.cpp | 58 ++++++------ src/spv/bitcoin/BRPaymentProtocol.cpp | 26 +++--- src/spv/bitcoin/BRPeer.cpp | 122 ++++++++++++-------------- src/spv/bitcoin/BRPeerManager.cpp | 82 ++++++++--------- src/spv/bitcoin/BRTransaction.cpp | 93 ++++++++++---------- src/spv/bitcoin/BRWallet.cpp | 44 +++++----- src/spv/spv_wrapper.cpp | 2 + src/spv/support/BRAddress.cpp | 20 +++-- src/spv/support/BRArray.h | 14 ++- src/spv/support/BRBIP32Sequence.cpp | 14 +-- src/spv/support/BRBIP39Mnemonic.cpp | 24 +++-- src/spv/support/BRBase58.cpp | 30 +++---- src/spv/support/BRBech32.cpp | 4 +- src/spv/support/BRCrypto.cpp | 101 ++++++++++----------- src/spv/support/BRKey.cpp | 32 +++---- src/spv/support/BRSet.cpp | 4 +- 16 files changed, 323 insertions(+), 347 deletions(-) diff --git a/src/spv/bitcoin/BRMerkleBlock.cpp b/src/spv/bitcoin/BRMerkleBlock.cpp index 994b3d5ec9..86aa02d2fb 100644 --- a/src/spv/bitcoin/BRMerkleBlock.cpp +++ b/src/spv/bitcoin/BRMerkleBlock.cpp @@ -43,36 +43,36 @@ inline static int _ceil_log2(int x) return r; } -// from https://en.bitcoin.it/wiki/Protocol_specification#Merkle_Trees -// Merkle trees are binary trees of hashes. Merkle trees in bitcoin use a double SHA-256, the SHA-256 hash of the -// SHA-256 hash of something. If, when forming a row in the tree (other than the root of the tree), it would have an odd -// number of elements, the final double-hash is duplicated to ensure that the row has an even number of hashes. First -// form the bottom row of the tree with the ordered double-SHA-256 hashes of the byte streams of the transactions in the -// block. Then the row above it consists of half that number of hashes. Each entry is the double-SHA-256 of the 64-byte -// concatenation of the corresponding two hashes below it in the tree. This procedure repeats recursively until we reach -// a row consisting of just a single double-hash. This is the merkle root of the tree. -// -// from https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki#Partial_Merkle_branch_format -// The encoding works as follows: we traverse the tree in depth-first order, storing a bit for each traversed node, -// signifying whether the node is the parent of at least one matched leaf txid (or a matched txid itself). In case we -// are at the leaf level, or this bit is 0, its merkle node hash is stored, and its children are not explored further. -// Otherwise, no hash is stored, but we recurse into both (or the only) child branch. During decoding, the same -// depth-first traversal is performed, consuming bits and hashes as they were written during encoding. -// -// example tree with three transactions, where only tx2 is matched by the bloom filter: -// -// merkleRoot -// / \ -// m1 m2 -// / \ / \ -// tx1 tx2 tx3 tx3 -// -// flag bits (little endian): 00001011 [merkleRoot = 1, m1 = 1, tx1 = 0, tx2 = 1, m2 = 0, byte padding = 000] -// hashes: [tx1, tx2, m2] -// -// NOTE: this merkle tree design has a security vulnerability (CVE-2012-2459), which can be defended against by -// considering the merkle root invalid if there are duplicate hashes in any rows with an even number of elements +/* from https://en.bitcoin.it/wiki/Protocol_specification#Merkle_Trees + Merkle trees are binary trees of hashes. Merkle trees in bitcoin use a double SHA-256, the SHA-256 hash of the + SHA-256 hash of something. If, when forming a row in the tree (other than the root of the tree), it would have an odd + number of elements, the final double-hash is duplicated to ensure that the row has an even number of hashes. First + form the bottom row of the tree with the ordered double-SHA-256 hashes of the byte streams of the transactions in the + block. Then the row above it consists of half that number of hashes. Each entry is the double-SHA-256 of the 64-byte + concatenation of the corresponding two hashes below it in the tree. This procedure repeats recursively until we reach + a row consisting of just a single double-hash. This is the merkle root of the tree. + + from https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki#Partial_Merkle_branch_format + The encoding works as follows: we traverse the tree in depth-first order, storing a bit for each traversed node, + signifying whether the node is the parent of at least one matched leaf txid (or a matched txid itself). In case we + are at the leaf level, or this bit is 0, its merkle node hash is stored, and its children are not explored further. + Otherwise, no hash is stored, but we recurse into both (or the only) child branch. During decoding, the same + depth-first traversal is performed, consuming bits and hashes as they were written during encoding. + + example tree with three transactions, where only tx2 is matched by the bloom filter: + + merkleRoot + / \ + m1 m2 + / \ / \ + tx1 tx2 tx3 tx3 + + flag bits (little endian): 00001011 [merkleRoot = 1, m1 = 1, tx1 = 0, tx2 = 1, m2 = 0, byte padding = 000] + hashes: [tx1, tx2, m2] + NOTE: this merkle tree design has a security vulnerability (CVE-2012-2459), which can be defended against by + considering the merkle root invalid if there are duplicate hashes in any rows with an even number of elements +*/ // returns a newly allocated merkle block struct that must be freed by calling BRMerkleBlockFree() BRMerkleBlock *BRMerkleBlockNew(void) { diff --git a/src/spv/bitcoin/BRPaymentProtocol.cpp b/src/spv/bitcoin/BRPaymentProtocol.cpp index 4a7ad904f9..74ee6d5962 100644 --- a/src/spv/bitcoin/BRPaymentProtocol.cpp +++ b/src/spv/bitcoin/BRPaymentProtocol.cpp @@ -168,18 +168,17 @@ static void _ProtoBufSetInt(uint8_t *buf, size_t bufLen, uint64_t i, uint64_t ke static void _ProtoBufUnknown(uint8_t **unknown, uint64_t key, uint64_t i, const void *data, size_t dataLen) { size_t bufLen = 10 + ((key & 0x07) == PROTOBUF_LENDELIM ? dataLen : 0); - uint8_t _buf[(bufLen <= 0x1000) ? bufLen : 0], *buf = (bufLen <= 0x1000) ? _buf : (uint8_t *)malloc(bufLen); + std::vector buf(bufLen); size_t off = 0, o = 0, l; uint64_t k; - assert(buf != NULL); - _ProtoBufSetVarInt(buf, bufLen, key, &off); + _ProtoBufSetVarInt(buf.data(), bufLen, key, &off); switch (key & 0x07) { - case PROTOBUF_VARINT: _ProtoBufSetVarInt(buf, bufLen, i, &off); break; - case PROTOBUF_64BIT: _ProtoBufSetFixed(buf, bufLen, i, &off, sizeof(uint64_t)); break; - case PROTOBUF_LENDELIM: _ProtoBufSetLenDelim(buf, bufLen, data, dataLen, &off); break; - case PROTOBUF_32BIT: _ProtoBufSetFixed(buf, bufLen, i, &off, sizeof(uint32_t)); break; + case PROTOBUF_VARINT: _ProtoBufSetVarInt(buf.data(), bufLen, i, &off); break; + case PROTOBUF_64BIT: _ProtoBufSetFixed(buf.data(), bufLen, i, &off, sizeof(uint64_t)); break; + case PROTOBUF_LENDELIM: _ProtoBufSetLenDelim(buf.data(), bufLen, data, dataLen, &off); break; + case PROTOBUF_32BIT: _ProtoBufSetFixed(buf.data(), bufLen, i, &off, sizeof(uint32_t)); break; default: break; } @@ -195,8 +194,7 @@ static void _ProtoBufUnknown(uint8_t **unknown, uint64_t key, uint64_t i, const if (k >= key) break; } - array_insert_array(*unknown, o, buf, bufLen); - if (buf != _buf) free(buf); + array_insert_array(*unknown, o, buf.data(), bufLen); } typedef enum { @@ -699,12 +697,12 @@ BRPaymentProtocolPayment *BRPaymentProtocolPaymentNew(const uint8_t *merchantDat } array_new(payment->refundTo, refundToCount); - + std::vector script; for (size_t i = 0; i < refundToCount; i++) { - uint8_t script[BRAddressScriptPubKey(NULL, 0, refundToAddresses[i].s)]; - size_t scriptLen = BRAddressScriptPubKey(script, sizeof(script), refundToAddresses[i].s); + script.resize(BRAddressScriptPubKey(NULL, 0, refundToAddresses[i].s)); + size_t scriptLen = BRAddressScriptPubKey(script.data(), script.size(), refundToAddresses[i].s); - array_add(payment->refundTo, _BRPaymentProtocolOutput(refundToAmounts[i], script, scriptLen)); + array_add(payment->refundTo, _BRPaymentProtocolOutput(refundToAmounts[i], script.data(), scriptLen)); } payment->refundToCount = refundToCount; @@ -1394,7 +1392,7 @@ size_t BRPaymentProtocolEncryptedMessageDecrypt(BRPaymentProtocolEncryptedMessag if (! ctx->defaults[encrypted_msg_status_code]) { snprintf(ad, adLen, "%" PRIu64 "%s", msg->statusCode, (msg->statusMsg) ? msg->statusMsg : ""); } - else if (msg->statusMsg) strncpy(ad, msg->statusMsg, adLen); + else if (msg->statusMsg) strcpy(ad, msg->statusMsg); outLen = BRChacha20Poly1305AEADDecrypt(out, outLen, cek, iv, msg->message, msg->msgLen, ad, strlen(ad)); mem_clean(cek, sizeof(cek)); diff --git a/src/spv/bitcoin/BRPeer.cpp b/src/spv/bitcoin/BRPeer.cpp index 536c1a95e9..bf044063cf 100644 --- a/src/spv/bitcoin/BRPeer.cpp +++ b/src/spv/bitcoin/BRPeer.cpp @@ -193,11 +193,8 @@ static int _BRPeerAcceptVersionMessage(BRPeer *peer, const uint8_t *msg, size_t { BRPeerContext *ctx = (BRPeerContext *)peer; size_t off = 0, strLen = 0, len = 0; - uint64_t recvServices, fromServices, nonce; - UInt128 recvAddr, fromAddr; - uint16_t recvPort, fromPort; int r = 1; - + if (85 > msgLen) { peer_log(peer, "malformed version message, length is %zu, should be >= 85", msgLen); r = 0; @@ -209,20 +206,13 @@ static int _BRPeerAcceptVersionMessage(BRPeer *peer, const uint8_t *msg, size_t off += sizeof(uint64_t); peer->timestamp = UInt64GetLE(&msg[off]); off += sizeof(uint64_t); - recvServices = UInt64GetLE(&msg[off]); - off += sizeof(uint64_t); - recvAddr = UInt128Get(&msg[off]); - off += sizeof(UInt128); - recvPort = UInt16GetBE(&msg[off]); - off += sizeof(uint16_t); - fromServices = UInt64GetLE(&msg[off]); - off += sizeof(uint64_t); - fromAddr = UInt128Get(&msg[off]); - off += sizeof(UInt128); - fromPort = UInt16GetBE(&msg[off]); - off += sizeof(uint16_t); - nonce = UInt64GetLE(&msg[off]); - off += sizeof(uint64_t); + off += sizeof(uint64_t); // recvServices + off += sizeof(UInt128); // recvAddr + off += sizeof(uint16_t); // recvPort + off += sizeof(uint64_t); // fromServices + off += sizeof(UInt128); // fromAddr + off += sizeof(uint16_t); // fromPort + off += sizeof(uint64_t); // nonce strLen = (size_t)BRVarInt(&msg[off], (off <= msgLen ? msgLen - off : 0), &len); off += len; @@ -288,7 +278,8 @@ static int _BRPeerAcceptAddrMessage(BRPeer *peer, const uint8_t *msg, size_t msg peer_log(peer, "dropping addr message, %zu is too many addresses, max is 1000", count); } else if (ctx->sentGetaddr) { // simple anti-tarpitting tactic, don't accept unsolicited addresses - BRPeer peers[count], p; + BRPeer p; + std::vector peers(count); size_t peersCount = 0; time_t now = time(NULL); @@ -308,12 +299,12 @@ static int _BRPeerAcceptAddrMessage(BRPeer *peer, const uint8_t *msg, size_t msg if (! _BRPeerIsIPv4(&p)) continue; // ignore IPv6 for now // if address time is more than 10 min in the future or unknown, set to 5 days old - if (p.timestamp > now + 10*60 || p.timestamp == 0) p.timestamp = now - 5*24*60*60; + if (p.timestamp > static_cast(now) + 10*60 || p.timestamp == 0) p.timestamp = now - 5*24*60*60; p.timestamp -= 2*60*60; // subtract two hours peers[peersCount++] = p; // add it to the list } - if (peersCount > 0 && ctx->relayedPeers) ctx->relayedPeers(ctx->info, peers, peersCount); + if (peersCount > 0 && ctx->relayedPeers) ctx->relayedPeers(ctx->info, peers.data(), peersCount); } return r; @@ -335,7 +326,7 @@ static int _BRPeerAcceptInvMessage(BRPeer *peer, const uint8_t *msg, size_t msgL } else { inv_type type; - const uint8_t *transactions[count], *blocks[count]; + std::vector transactions(count), blocks(count); size_t i, j, txCount = 0, blockCount = 0; peer_log(peer, "got inv with %zu item(s)", count); @@ -370,7 +361,8 @@ static int _BRPeerAcceptInvMessage(BRPeer *peer, const uint8_t *msg, size_t msgL if (blockCount == 1 && UInt256Eq(ctx->lastBlockHash, UInt256Get(blocks[0]))) blockCount = 0; if (blockCount == 1) ctx->lastBlockHash = UInt256Get(blocks[0]); - UInt256 hash, blockHashes[blockCount], txHashes[txCount]; + UInt256 hash; + std::vector blockHashes(blockCount), txHashes(txCount); for (i = 0; i < blockCount; i++) { blockHashes[i] = UInt256Get(blocks[i]); @@ -393,8 +385,8 @@ static int _BRPeerAcceptInvMessage(BRPeer *peer, const uint8_t *msg, size_t msgL else txHashes[j++] = hash; } - _BRPeerAddKnownTxHashes(peer, txHashes, j); - if (j > 0 || blockCount > 0) BRPeerSendGetdata(peer, txHashes, j, blockHashes, blockCount); + _BRPeerAddKnownTxHashes(peer, txHashes.data(), j); + if (j > 0 || blockCount > 0) BRPeerSendGetdata(peer, txHashes.data(), j, blockHashes.data(), blockCount); // to improve chain download performance, if we received 500 block hashes, request the next 500 block hashes if (blockCount >= 500) { @@ -553,7 +545,7 @@ static int _BRPeerAcceptGetdataMessage(BRPeer *peer, const uint8_t *msg, size_t else { struct inv_item { uint8_t item[36]; } *notfound = NULL; BRTransaction *tx = NULL; - + std::vector buf; peer_log(peer, "got getdata with %zu item(s)", count); for (size_t i = 0; i < count; i++) { @@ -566,16 +558,18 @@ static int _BRPeerAcceptGetdataMessage(BRPeer *peer, const uint8_t *msg, size_t if (ctx->requestedTx) tx = ctx->requestedTx(ctx->info, hash); if (tx && BRTransactionVSize(tx) < TX_MAX_SIZE) { - uint8_t buf[BRTransactionSerialize(tx, NULL, 0)]; - size_t bufLen = BRTransactionSerialize(tx, buf, sizeof(buf)); - char txHex[bufLen*2 + 1]; + buf.resize(BRTransactionSerialize(tx, NULL, 0)); + size_t bufLen = BRTransactionSerialize(tx, buf.data(), buf.size()); + std::string txHex; for (size_t j = 0; j < bufLen; j++) { - sprintf(&txHex[j*2], "%02x", buf[j]); + char hex[3]; + sprintf(hex, "%02x", buf[j]); + txHex += hex; } - peer_log(peer, "publishing tx: %s", txHex); - BRPeerSendMessage(peer, buf, bufLen, MSG_TX); + peer_log(peer, "publishing tx: %s", txHex.c_str()); + BRPeerSendMessage(peer, buf.data(), bufLen, MSG_TX); break; } @@ -592,15 +586,13 @@ static int _BRPeerAcceptGetdataMessage(BRPeer *peer, const uint8_t *msg, size_t if (notfound) { size_t bufLen = BRVarIntSize(array_count(notfound)) + 36*array_count(notfound), o = 0; - uint8_t *buf = (uint8_t *)malloc(bufLen); + buf.resize(bufLen); - assert(buf != NULL); o += BRVarIntSet(&buf[o], (o <= bufLen ? bufLen - o : 0), array_count(notfound)); memcpy(&buf[o], notfound, 36*array_count(notfound)); o += 36*array_count(notfound); array_free(notfound); - BRPeerSendMessage(peer, buf, o, MSG_NOTFOUND); - free(buf); + BRPeerSendMessage(peer, buf.data(), o, MSG_NOTFOUND); } } @@ -744,17 +736,14 @@ static int _BRPeerAcceptMerkleblockMessage(BRPeer *peer, const uint8_t *msg, siz } else { size_t count = BRMerkleBlockTxHashes(block, NULL, 0); - UInt256 _hashes[128], *hashes = (count <= 128) ? _hashes : (UInt256 *)malloc(count*sizeof(UInt256)); + std::vector hashes(count); - assert(hashes != NULL); - count = BRMerkleBlockTxHashes(block, hashes, count); + count = BRMerkleBlockTxHashes(block, hashes.data(), count); for (size_t i = count; i > 0; i--) { // reverse order for more efficient removal as tx arrive if (BRSetContains(ctx->knownTxHashSet, &hashes[i - 1])) continue; array_add(ctx->currentBlockTxHashes, hashes[i - 1]); } - - if (hashes != _hashes) free(hashes); } if (block) { @@ -783,37 +772,33 @@ static int _BRPeerAcceptRejectMessage(BRPeer *peer, const uint8_t *msg, size_t m r = 0; } else { - char type[(strLen < 0x1000) ? strLen + 1 : 0x1000]; uint8_t code; size_t len = 0, hashLen = 0; - strncpy(type, (const char *)&msg[off], sizeof(type) - 1); - type[sizeof(type) - 1] = '\0'; + std::string type((const char *)&msg[off], strLen); off += strLen; code = msg[off++]; strLen = (size_t)BRVarInt(&msg[off], (off <= msgLen ? msgLen - off : 0), &len); off += len; - if (strncmp(type, MSG_TX, sizeof(type)) == 0) hashLen = sizeof(UInt256); + if (type == MSG_TX) hashLen = sizeof(UInt256); if (off + strLen + hashLen > msgLen) { peer_log(peer, "malformed reject message, length is %zu, should be >= %zu", msgLen, off + strLen + hashLen); r = 0; } else { - char reason[(strLen < 0x1000) ? strLen + 1 : 0x1000]; UInt256 txHash = UINT256_ZERO; - strncpy(reason, (const char *)&msg[off], sizeof(reason) - 1); - reason[sizeof(reason) - 1] = '\0'; + std::string reason((const char *)&msg[off], strLen); off += strLen; if (hashLen == sizeof(UInt256)) txHash = UInt256Get(&msg[off]); off += hashLen; if (! UInt256IsZero(txHash)) { - peer_log(peer, "rejected %s code: 0x%x reason: \"%s\" txid: %s", type, code, reason, u256hex(txHash).c_str()); + peer_log(peer, "rejected %s code: 0x%x reason: \"%s\" txid: %s", type.c_str(), code, reason.c_str(), u256hex(txHash).c_str()); if (ctx->rejectedTx) ctx->rejectedTx(ctx->info, txHash, code); } - else peer_log(peer, "rejected %s code: 0x%x reason: \"%s\"", type, code, reason); + else peer_log(peer, "rejected %s code: 0x%x reason: \"%s\"", type.c_str(), code, reason.c_str()); } } @@ -1433,7 +1418,8 @@ void BRPeerSendMessage(BRPeer *peer, const uint8_t *msg, size_t msgLen, const ch } else { BRPeerContext *ctx = (BRPeerContext *)peer; - uint8_t buf[HEADER_LENGTH + msgLen], hash[32]; + uint8_t hash[32]; + std::vector buf(HEADER_LENGTH + msgLen); size_t off = 0; ssize_t n = 0; struct timeval tv; @@ -1455,8 +1441,8 @@ void BRPeerSendMessage(BRPeer *peer, const uint8_t *msg, size_t msgLen, const ch socket = _peerGetSocket(ctx); if (socket == INVALID_SOCKET) error = ENOTCONN; - while (socket != INVALID_SOCKET && ! error && msgLen < sizeof(buf)) { - n = send(socket, &buf[msgLen], sizeof(buf) - msgLen, MSG_NOSIGNAL); + while (socket != INVALID_SOCKET && ! error && msgLen < buf.size()) { + n = send(socket, &buf[msgLen], buf.size() - msgLen, MSG_NOSIGNAL); if (n >= 0) msgLen += n; if (n < 0 && WSAGetLastError() != WSAEWOULDBLOCK) error = WSAGetLastError(); gettimeofday(&tv, NULL); @@ -1475,7 +1461,7 @@ void BRPeerSendVersionMessage(BRPeer *peer) { BRPeerContext *ctx = (BRPeerContext *)peer; size_t off = 0, userAgentLen = strlen(USER_AGENT); - uint8_t msg[80 + BRVarIntSize(userAgentLen) + userAgentLen + 5]; + std::vector msg(80 + BRVarIntSize(userAgentLen) + userAgentLen + 5); UInt32SetLE(&msg[off], BR_PROTOCOL_VERSION); // version off += sizeof(uint32_t); @@ -1498,13 +1484,13 @@ void BRPeerSendVersionMessage(BRPeer *peer) ctx->nonce = ((uint64_t)BRRand(0) << 32) | (uint64_t)BRRand(0); // random nonce UInt64SetLE(&msg[off], ctx->nonce); off += sizeof(uint64_t); - off += BRVarIntSet(&msg[off], (off <= sizeof(msg) ? sizeof(msg) - off : 0), userAgentLen); - strncpy((char *)&msg[off], USER_AGENT, userAgentLen); // user agent string + off += BRVarIntSet(&msg[off], (off <= msg.size() ? msg.size() - off : 0), userAgentLen); + memcpy(&msg[off], USER_AGENT, userAgentLen); // user agent string off += userAgentLen; UInt32SetLE(&msg[off], 0); // last block received off += sizeof(uint32_t); msg[off++] = 0; // relay transactions (0 for SPV bloom filter mode) - BRPeerSendMessage(peer, msg, sizeof(msg), MSG_VERSION); + BRPeerSendMessage(peer, msg.data(), msg.size(), MSG_VERSION); } void BRPeerSendVerackMessage(BRPeer *peer) @@ -1515,11 +1501,11 @@ void BRPeerSendVerackMessage(BRPeer *peer) void BRPeerSendAddr(BRPeer *peer) { - uint8_t msg[BRVarIntSize(0)]; - size_t msgLen = BRVarIntSet(msg, sizeof(msg), 0); + std::vector msg(BRVarIntSize(0)); + size_t msgLen = BRVarIntSet(msg.data(), msg.size(), 0); //TODO: send peer addresses we know about - BRPeerSendMessage(peer, msg, msgLen, MSG_ADDR); + BRPeerSendMessage(peer, msg.data(), msgLen, MSG_ADDR); } void BRPeerSendFilterload(BRPeer *peer, const uint8_t *filter, size_t filterLen) @@ -1564,7 +1550,7 @@ void BRPeerSendGetheaders(BRPeer *peer, const UInt256 locators[], size_t locator { size_t i, off = 0; size_t msgLen = sizeof(uint32_t) + BRVarIntSize(locatorsCount) + sizeof(*locators)*locatorsCount + sizeof(hashStop); - uint8_t msg[msgLen]; + std::vector msg(msgLen); UInt32SetLE(&msg[off], BR_PROTOCOL_VERSION); off += sizeof(uint32_t); @@ -1581,7 +1567,7 @@ void BRPeerSendGetheaders(BRPeer *peer, const UInt256 locators[], size_t locator if (locatorsCount > 0) { peer_log(peer, "calling getheaders with %zu locators: [%s,%s %s]", locatorsCount, u256hex(locators[0]).c_str(), (locatorsCount > 2 ? " ...," : ""), (locatorsCount > 1 ? u256hex(locators[locatorsCount - 1]).c_str() : "")); - BRPeerSendMessage(peer, msg, off, MSG_GETHEADERS); + BRPeerSendMessage(peer, msg.data(), off, MSG_GETHEADERS); } } @@ -1589,7 +1575,7 @@ void BRPeerSendGetblocks(BRPeer *peer, const UInt256 locators[], size_t locators { size_t i, off = 0; size_t msgLen = sizeof(uint32_t) + BRVarIntSize(locatorsCount) + sizeof(*locators)*locatorsCount + sizeof(hashStop); - uint8_t msg[msgLen]; + std::vector msg(msgLen); UInt32SetLE(&msg[off], BR_PROTOCOL_VERSION); off += sizeof(uint32_t); @@ -1606,7 +1592,7 @@ void BRPeerSendGetblocks(BRPeer *peer, const UInt256 locators[], size_t locators if (locatorsCount > 0) { peer_log(peer, "calling getblocks with %zu locators: [%s,%s %s]", locatorsCount, u256hex(locators[0]).c_str(), (locatorsCount > 2 ? " ...," : ""), (locatorsCount > 1 ? u256hex(locators[locatorsCount - 1]).c_str() : "")); - BRPeerSendMessage(peer, msg, off, MSG_GETBLOCKS); + BRPeerSendMessage(peer, msg.data(), off, MSG_GETBLOCKS); } } @@ -1620,7 +1606,7 @@ void BRPeerSendInv(BRPeer *peer, const UInt256 txHashes[], size_t txCount) if (txCount > 0) { size_t i, off = 0, msgLen = BRVarIntSize(txCount) + (sizeof(uint32_t) + sizeof(*txHashes))*txCount; - uint8_t msg[msgLen]; + std::vector msg(msgLen); off += BRVarIntSet(&msg[off], (off <= msgLen ? msgLen - off : 0), txCount); @@ -1631,7 +1617,7 @@ void BRPeerSendInv(BRPeer *peer, const UInt256 txHashes[], size_t txCount) off += sizeof(UInt256); } - BRPeerSendMessage(peer, msg, off, MSG_INV); + BRPeerSendMessage(peer, msg.data(), off, MSG_INV); } } @@ -1645,7 +1631,7 @@ void BRPeerSendGetdata(BRPeer *peer, const UInt256 txHashes[], size_t txCount, c } else if (count > 0) { size_t msgLen = BRVarIntSize(count) + (sizeof(uint32_t) + sizeof(UInt256))*(count); - uint8_t msg[msgLen]; + std::vector msg(msgLen); off += BRVarIntSet(&msg[off], (off <= msgLen ? msgLen - off : 0), count); @@ -1664,7 +1650,7 @@ void BRPeerSendGetdata(BRPeer *peer, const UInt256 txHashes[], size_t txCount, c } ((BRPeerContext *)peer)->sentGetdata = 1; - BRPeerSendMessage(peer, msg, off, MSG_GETDATA); + BRPeerSendMessage(peer, msg.data(), off, MSG_GETDATA); } } diff --git a/src/spv/bitcoin/BRPeerManager.cpp b/src/spv/bitcoin/BRPeerManager.cpp index 58b4525698..6c95451a63 100644 --- a/src/spv/bitcoin/BRPeerManager.cpp +++ b/src/spv/bitcoin/BRPeerManager.cpp @@ -186,7 +186,7 @@ inline static int _BRBlockHeightEq(const void *block, const void *otherBlock) struct BRPeerManagerStruct { const BRChainParams *params; BRWallet *wallet; - int isConnected, connectFailureCount, misbehavinCount, dnsThreadCount, peerThreadCount, maxConnectCount, isConnectRun; + uint32_t isConnected, connectFailureCount, misbehavinCount, dnsThreadCount, peerThreadCount, maxConnectCount, isConnectRun; BRPeer *peers, *downloadPeer, fixedPeer, **connectedPeers; char downloadPeerName[INET6_ADDRSTRLEN + 6]; uint32_t earliestKeyTime, syncStartHeight, filterUpdateHeight, estimatedHeight; @@ -265,7 +265,7 @@ static size_t _BRPeerManagerBlockLocators(BRPeerManager *manager, UInt256 locato // append 10 most recent block hashes, decending, then continue appending, doubling the step back each time, // finishing with the genesis block (top, -1, -2, -3, -4, -5, -6, -7, -8, -9, -11, -15, -23, -39, -71, -135, ..., 0) BRMerkleBlock *block = manager->lastBlock; - int32_t step = 1, i = 0, j; + uint32_t step = 1, i = 0, j; while (block && block->height > 0) { if (locators && i < locatorsCount) locators[i] = block->blockHash; @@ -359,10 +359,10 @@ static void _BRPeerManagerLoadBloomFilter(BRPeerManager *manager, BRPeer *peer) manager->bloomFilter = filter; // TODO: XXX if already synced, recursively add inputs of unconfirmed receives - uint8_t data[BRBloomFilterSerialize(filter, NULL, 0)]; - size_t len = BRBloomFilterSerialize(filter, data, sizeof(data)); + std::vector data(BRBloomFilterSerialize(filter, NULL, 0)); + size_t len = BRBloomFilterSerialize(filter, data.data(), data.size()); - BRPeerSendFilterload(peer, data, len); + BRPeerSendFilterload(peer, data.data(), len); } static void _updateFilterRerequestDone(void *info, int success) @@ -376,10 +376,10 @@ static void _updateFilterRerequestDone(void *info, int success) manager->lock.lock(); if ((peer->flags & PEER_FLAG_NEEDSUPDATE) == 0) { - UInt256 locators[_BRPeerManagerBlockLocators(manager, NULL, 0)]; - size_t count = _BRPeerManagerBlockLocators(manager, locators, sizeof(locators)/sizeof(*locators)); + std::vector locators(_BRPeerManagerBlockLocators(manager, NULL, 0)); + size_t count = _BRPeerManagerBlockLocators(manager, locators.data(), locators.size()); - BRPeerSendGetblocks(peer, locators, count, UINT256_ZERO); + BRPeerSendGetblocks(peer, locators.data(), count, UINT256_ZERO); } manager->lock.unlock(); @@ -495,9 +495,9 @@ static void _requestUnrelayedTxGetdataDone(void *info, int success) if (count >= manager->maxConnectCount) { UInt256 hash; size_t txCount = BRWalletTxUnconfirmedBefore(manager->wallet, NULL, 0, TX_UNCONFIRMED); - BRTransaction *tx[(txCount*sizeof(BRTransaction *) <= 0x1000) ? txCount : 0x1000/sizeof(BRTransaction *)]; + std::vector tx(txCount); - txCount = BRWalletTxUnconfirmedBefore(manager->wallet, tx, sizeof(tx)/sizeof(*tx), TX_UNCONFIRMED); + txCount = BRWalletTxUnconfirmedBefore(manager->wallet, tx.data(), tx.size(), TX_UNCONFIRMED); for (size_t i = txCount; i > 0; i--) { hash = tx[i - 1]->txHash; @@ -528,10 +528,10 @@ static void _BRPeerManagerRequestUnrelayedTx(BRPeerManager *manager, BRPeer *pee { BRPeerCallbackInfo *info; size_t hashCount = 0, txCount = BRWalletTxUnconfirmedBefore(manager->wallet, NULL, 0, TX_UNCONFIRMED); - BRTransaction *tx[txCount]; - UInt256 txHashes[txCount]; + std::vector tx(txCount); + std::vector txHashes(txCount); - txCount = BRWalletTxUnconfirmedBefore(manager->wallet, tx, txCount, TX_UNCONFIRMED); + txCount = BRWalletTxUnconfirmedBefore(manager->wallet, tx.data(), txCount, TX_UNCONFIRMED); for (size_t i = 0; i < txCount; i++) { if (! _BRTxPeerListHasPeer(manager->txRelays, tx[i]->txHash, peer) && @@ -542,7 +542,7 @@ static void _BRPeerManagerRequestUnrelayedTx(BRPeerManager *manager, BRPeer *pee } if (hashCount > 0) { - BRPeerSendGetdata(peer, txHashes, hashCount, NULL, 0); + BRPeerSendGetdata(peer, txHashes.data(), hashCount, NULL, 0); if ((peer->flags & PEER_FLAG_SYNCED) == 0) { info = (BRPeerCallbackInfo *)calloc(1, sizeof(*info)); @@ -812,7 +812,7 @@ static void _peerConnected(void *info) BRPeer *peer = ((BRPeerCallbackInfo *)info)->peer; BRPeerManager *manager = ((BRPeerCallbackInfo *)info)->manager; BRPeerCallbackInfo *peerInfo; - time_t now = time(NULL); + uint64_t now = time(NULL); manager->lock.lock(); if (peer->timestamp > now + 2*60*60 || peer->timestamp < now - 2*60*60) peer->timestamp = now; // sanity check @@ -872,17 +872,17 @@ static void _peerConnected(void *info) _BRPeerManagerPublishPendingTx(manager, peer); if (manager->lastBlock->height < BRPeerLastBlock(peer)) { // start blockchain sync - UInt256 locators[_BRPeerManagerBlockLocators(manager, NULL, 0)]; - size_t count = _BRPeerManagerBlockLocators(manager, locators, sizeof(locators)/sizeof(*locators)); + std::vector locators(_BRPeerManagerBlockLocators(manager, NULL, 0)); + size_t count = _BRPeerManagerBlockLocators(manager, locators.data(), locators.size()); BRPeerScheduleDisconnect(peer, PROTOCOL_TIMEOUT); // schedule sync timeout // request just block headers up to a week before earliestKeyTime, and then merkleblocks after that // we do not reset connect failure count yet incase this request times out if (manager->lastBlock->timestamp + 7*24*60*60 >= manager->earliestKeyTime) { - BRPeerSendGetblocks(peer, locators, count, UINT256_ZERO); + BRPeerSendGetblocks(peer, locators.data(), count, UINT256_ZERO); } - else BRPeerSendGetheaders(peer, locators, count, UINT256_ZERO); + else BRPeerSendGetheaders(peer, locators.data(), count, UINT256_ZERO); } else { // we're already synced manager->connectFailureCount = 0; // reset connect failure count @@ -904,7 +904,7 @@ static void _peerDisconnected(void *info, int error) //free(info); manager->lock.lock(); - BRPublishedTx pubTx[array_count(manager->publishedTx)]; + std::vector pubTx(array_count(manager->publishedTx)); if (error == EPROTO) { // if it's protocol error, the peer isn't following standard policy _BRPeerManagerPeerMisbehavin(manager, peer); @@ -986,7 +986,7 @@ static void _peerRelayedPeers(void *info, const BRPeer peers[], size_t peersCoun { BRPeer *peer = ((BRPeerCallbackInfo *)info)->peer; BRPeerManager *manager = ((BRPeerCallbackInfo *)info)->manager; - time_t now = time(NULL); + uint64_t now = time(NULL); manager->lock.lock(); peer_log(peer, "relayed %zu peer(s)", peersCount); @@ -1002,14 +1002,14 @@ static void _peerRelayedPeers(void *info, const BRPeer peers[], size_t peersCoun while (peersCount > 1000 && manager->peers[peersCount - 1].timestamp + 3*60*60 < now) peersCount--; array_set_count(manager->peers, peersCount); - BRPeer save[peersCount]; + std::vector save(peersCount); for (size_t i = 0; i < peersCount; i++) save[i] = manager->peers[i]; manager->lock.unlock(); // peer relaying is complete when we receive <1000 if (peersCount > 1 && peersCount < 1000 && - manager->savePeers) manager->savePeers(manager->info, 1, save, peersCount); + manager->savePeers) manager->savePeers(manager->info, 1, save.data(), peersCount); } static void _peerRelayedTx(void *info, BRTransaction *tx) @@ -1247,13 +1247,12 @@ static void _peerRelayedBlock(void *info, BRMerkleBlock *block) BRPeer *peer = ((BRPeerCallbackInfo *)info)->peer; BRPeerManager *manager = ((BRPeerCallbackInfo *)info)->manager; size_t txCount = BRMerkleBlockTxHashes(block, NULL, 0); - UInt256 _txHashes[128], *txHashes = (txCount <= 128) ? _txHashes : (UInt256 *)malloc(txCount*sizeof(UInt256)); + std::vector txHashes(txCount); size_t i, j, fpCount = 0, saveCount = 0; BRMerkleBlock orphan, *b, *b2, *prev, *next = NULL; uint32_t txTime = 0; - assert(txHashes != NULL); - txCount = BRMerkleBlockTxHashes(block, txHashes, txCount); + txCount = BRMerkleBlockTxHashes(block, txHashes.data(), txCount); manager->lock.lock(); prev = (BRMerkleBlock *)BRSetGet(manager->blocks, &block->prevBlock); @@ -1317,12 +1316,11 @@ static void _peerRelayedBlock(void *info, BRMerkleBlock *block) // call getblocks, unless we already did with the previous block, or we're still syncing if (manager->lastBlock->height >= BRPeerLastBlock(peer) && (! manager->lastOrphan || ! UInt256Eq(manager->lastOrphan->blockHash, block->prevBlock))) { - UInt256 locators[_BRPeerManagerBlockLocators(manager, NULL, 0)]; - size_t locatorsCount = _BRPeerManagerBlockLocators(manager, locators, - sizeof(locators)/sizeof(*locators)); + std::vector locators(_BRPeerManagerBlockLocators(manager, NULL, 0)); + size_t locatorsCount = _BRPeerManagerBlockLocators(manager, locators.data(), locators.size()); peer_log(peer, "calling getblocks"); - BRPeerSendGetblocks(peer, locators, locatorsCount, UINT256_ZERO); + BRPeerSendGetblocks(peer, locators.data(), locatorsCount, UINT256_ZERO); } BRSetAdd(manager->orphans, block); // BUG: limit total orphans to avoid memory exhaustion attack @@ -1342,7 +1340,7 @@ static void _peerRelayedBlock(void *info, BRMerkleBlock *block) BRSetAdd(manager->blocks, block); manager->lastBlock = block; - if (txCount > 0) BRWalletUpdateTransactions(manager->wallet, txHashes, txCount, block->height, txTime, block->blockHash); + if (txCount > 0) BRWalletUpdateTransactions(manager->wallet, txHashes.data(), txCount, block->height, txTime, block->blockHash); if (manager->downloadPeer) BRPeerSetCurrentBlockHeight(manager->downloadPeer, block->height); if (block->height < manager->estimatedHeight && peer == manager->downloadPeer) { @@ -1369,7 +1367,7 @@ static void _peerRelayedBlock(void *info, BRMerkleBlock *block) assert (NULL != b); if (BRMerkleBlockEq(b, block)) { // if it's not on a fork, set block heights for its transactions - if (txCount > 0) BRWalletUpdateTransactions(manager->wallet, txHashes, txCount, block->height, txTime, block->blockHash); + if (txCount > 0) BRWalletUpdateTransactions(manager->wallet, txHashes.data(), txCount, block->height, txTime, block->blockHash); if (block->height == manager->lastBlock->height) manager->lastBlock = block; } @@ -1420,16 +1418,14 @@ static void _peerRelayedBlock(void *info, BRMerkleBlock *block) uint32_t height = b->height, timestamp = b->timestamp; if (count > txCount) { - txHashes = (txHashes != _txHashes) ? (UInt256 *)realloc(txHashes, count*sizeof(*txHashes)) : - (UInt256 *)malloc(count*sizeof(*txHashes)); - assert(txHashes != NULL); + txHashes.resize(count); txCount = count; } - count = BRMerkleBlockTxHashes(b, txHashes, count); + count = BRMerkleBlockTxHashes(b, txHashes.data(), count); b = (BRMerkleBlock *)BRSetGet(manager->blocks, &b->prevBlock); if (b) timestamp = timestamp/2 + b->timestamp/2; - if (count > 0) BRWalletUpdateTransactions(manager->wallet, txHashes, count, height, timestamp, b->blockHash); + if (count > 0) BRWalletUpdateTransactions(manager->wallet, txHashes.data(), count, height, timestamp, b->blockHash); } manager->lastBlock = block; @@ -1447,8 +1443,6 @@ static void _peerRelayedBlock(void *info, BRMerkleBlock *block) manager->blockNotify(manager->info, manager->lastBlock->blockHash); } - if (txHashes != _txHashes) free(txHashes); - if (block && block->height != BLOCK_UNKNOWN_HEIGHT) { if (block->height > manager->estimatedHeight) manager->estimatedHeight = block->height; @@ -1457,7 +1451,7 @@ static void _peerRelayedBlock(void *info, BRMerkleBlock *block) next = (BRMerkleBlock *)BRSetRemove(manager->orphans, &orphan); } - BRMerkleBlock *saveBlocks[saveCount]; + std::vector saveBlocks(saveCount); for (i = 0, b = block; b && i < saveCount; i++) { assert(b->height != BLOCK_UNKNOWN_HEIGHT); // verify all blocks to be saved are in the chain @@ -1469,7 +1463,7 @@ static void _peerRelayedBlock(void *info, BRMerkleBlock *block) j = (i > 0) ? saveBlocks[i - 1]->height % BLOCK_DIFFICULTY_INTERVAL : 0; if (j > 0) i -= (i > BLOCK_DIFFICULTY_INTERVAL - j) ? BLOCK_DIFFICULTY_INTERVAL - j : i; assert(i == 0 || (saveBlocks[i - 1]->height % BLOCK_DIFFICULTY_INTERVAL) == 0); - if (i > 0 && manager->saveBlocks) manager->saveBlocks(manager->info, (i > 1 ? 1 : 0), saveBlocks, i); + if (i > 0 && manager->saveBlocks) manager->saveBlocks(manager->info, (i > 1 ? 1 : 0), saveBlocks.data(), i); manager->lock.unlock(); if (block && block->height != BLOCK_UNKNOWN_HEIGHT && block->height >= BRPeerLastBlock(peer) && @@ -1755,7 +1749,7 @@ void BRPeerManagerConnect(BRPeerManager *manager) if (ShutdownRequested()) { break; } - time_t now = time(NULL); + uint64_t now = time(NULL); if (array_count(manager->peers) < manager->maxConnectCount || manager->peers[manager->maxConnectCount - 1].timestamp + 3*24*60*60 < now) { @@ -1925,7 +1919,7 @@ static BRMerkleBlock *_BRPeerManagerLookupBlockFromBlockNumber(BRPeerManager *ma } // blockNumber not in the (abbreviated) chain - look through checkpoints - for (int i = 0; i < manager->params->checkpointsCount; i++) + for (uint32_t i = 0; i < manager->params->checkpointsCount; i++) if (manager->params->checkpoints[i].height == blockNumber) { UInt256 hash = UInt256Reverse(manager->params->checkpoints[i].hash); return (BRMerkleBlock *)BRSetGet(manager->blocks, &hash); @@ -2198,7 +2192,7 @@ void BRPeerManagerCancelPendingTxs(BRPeerManager *manager) manager->lock.lock(); // do not free txs itself - it will be done by manager - BRPublishedTx pubTx[array_count(manager->publishedTx)]; + std::vector pubTx(array_count(manager->publishedTx)); for (size_t i = array_count(manager->publishedTx); i > 0; i--) { if (manager->publishedTx[i - 1].callback == NULL) continue; diff --git a/src/spv/bitcoin/BRTransaction.cpp b/src/spv/bitcoin/BRTransaction.cpp index 60e1469bb4..df66268205 100644 --- a/src/spv/bitcoin/BRTransaction.cpp +++ b/src/spv/bitcoin/BRTransaction.cpp @@ -200,24 +200,24 @@ static size_t _BRTransactionWitnessData(const BRTransaction *tx, uint8_t *data, off += sizeof(uint32_t); if (! anyoneCanPay) { - uint8_t buf[(sizeof(UInt256) + sizeof(uint32_t))*tx->inCount]; + std::vector buf((sizeof(UInt256) + sizeof(uint32_t))*tx->inCount); for (i = 0; i < tx->inCount; i++) { UInt256Set(&buf[(sizeof(UInt256) + sizeof(uint32_t))*i], tx->inputs[i].txHash); UInt32SetLE(&buf[(sizeof(UInt256) + sizeof(uint32_t))*i + sizeof(UInt256)], tx->inputs[i].index); } - if (data && off + sizeof(UInt256) <= dataLen) BRSHA256_2(&data[off], buf, sizeof(buf)); // inputs hash + if (data && off + sizeof(UInt256) <= dataLen) BRSHA256_2(&data[off], buf.data(), buf.size()); // inputs hash } else if (data && off + sizeof(UInt256) <= dataLen) UInt256Set(&data[off], UINT256_ZERO); // anyone-can-pay off += sizeof(UInt256); if (! anyoneCanPay && sigHash != SIGHASH_SINGLE && sigHash != SIGHASH_NONE) { - uint8_t buf[sizeof(uint32_t)*tx->inCount]; + std::vector buf(sizeof(uint32_t)*tx->inCount); for (i = 0; i < tx->inCount; i++) UInt32SetLE(&buf[sizeof(uint32_t)*i], tx->inputs[i].sequence); - if (data && off + sizeof(UInt256) <= dataLen) BRSHA256_2(&data[off], buf, sizeof(buf)); // sequence hash + if (data && off + sizeof(UInt256) <= dataLen) BRSHA256_2(&data[off], buf.data(), buf.size()); // sequence hash } else if (data && off + sizeof(UInt256) <= dataLen) UInt256Set(&data[off], UINT256_ZERO); @@ -243,10 +243,10 @@ static size_t _BRTransactionWitnessData(const BRTransaction *tx, uint8_t *data, if (buf != _buf) free(buf); } else if (sigHash == SIGHASH_SINGLE && index < tx->outCount) { - uint8_t buf[_BRTransactionOutputData(tx, NULL, 0, index)]; - size_t bufLen = _BRTransactionOutputData(tx, buf, sizeof(buf), index); + std::vector buf(_BRTransactionOutputData(tx, NULL, 0, index)); + size_t bufLen = _BRTransactionOutputData(tx, buf.data(), buf.size(), index); - if (data && off + sizeof(UInt256) <= dataLen) BRSHA256_2(&data[off], buf, bufLen); //SIGHASH_SINGLE outputs hash + if (data && off + sizeof(UInt256) <= dataLen) BRSHA256_2(&data[off], buf.data(), bufLen); //SIGHASH_SINGLE outputs hash } else if (data && off + sizeof(UInt256) <= dataLen) UInt256Set(&data[off], UINT256_ZERO); // SIGHASH_NONE @@ -587,15 +587,12 @@ size_t BRTransactionSize(const BRTransaction *tx) size_t BRTransactionHTLCSize(const BRTransaction *tx, const size_t sigSize) { - BRTxInput *input; size_t size; size = (tx) ? 8 + BRVarIntSize(tx->inCount) + BRVarIntSize(tx->outCount) : 0; for (size_t i = 0; i < tx->inCount; i++) { - input = &tx->inputs[i]; - size += sigSize + TX_HTLC_INPUT_NOSIG; } @@ -661,7 +658,7 @@ int BRTransactionIsSigned(const BRTransaction *tx) // returns true if tx is signed int BRTransactionSign(BRTransaction *tx, int forkId, BRKey keys[], size_t keysCount, HTLCScriptType htlcType, const uint8_t* seed) { - UInt160 pkh[keysCount]; + std::vector pkh(keysCount); size_t i, j; assert(tx != NULL); @@ -690,54 +687,56 @@ int BRTransactionSign(BRTransaction *tx, int forkId, BRKey keys[], size_t keysCo while (j < keysCount && (! hash || ! UInt160Eq(pkh[j], UInt160Get(hash)))) j++; if (j >= keysCount) continue; - const uint8_t *elems[BRScriptElements(NULL, 0, input->script, input->scriptLen)]; - size_t elemsCount = BRScriptElements(elems, sizeof(elems)/sizeof(*elems), input->script, input->scriptLen); - uint8_t pubKey[BRKeyPubKey(&keys[j], NULL, 0)]; - size_t pkLen = BRKeyPubKey(&keys[j], pubKey, sizeof(pubKey)); - uint8_t sig[73], script[1 + sizeof(sig) + 1 + (seed ? seed[0] + (htlcType == ScriptTypeSeller ? 1 /* OP_1 */ : 0) + 1 /* pushdata */ + input->scriptLen /* length */ + input->script[0] : sizeof(pubKey))]; + std::vector elems(BRScriptElements(NULL, 0, input->script, input->scriptLen)); + size_t elemsCount = BRScriptElements(elems.data(), elems.size(), input->script, input->scriptLen); + std::vector pubKey(BRKeyPubKey(&keys[j], NULL, 0)); + size_t pkLen = BRKeyPubKey(&keys[j], pubKey.data(), pubKey.size()); + uint8_t sig[73]; + std::vector script(1 + sizeof(sig) + 1 + (seed ? seed[0] + (htlcType == ScriptTypeSeller ? 1 /* OP_1 */ : 0) + 1 /* pushdata */ + input->scriptLen /* length */ + input->script[0] : pubKey.size())); size_t sigLen, scriptLen; UInt256 md = UINT256_ZERO; + std::vector data; if (elemsCount == 2 && *elems[0] == OP_0 && *elems[1] == 20) { // pay-to-witness-pubkey-hash - uint8_t data[_BRTransactionWitnessData(tx, NULL, 0, i, forkId | SIGHASH_ALL)]; - size_t dataLen = _BRTransactionWitnessData(tx, data, sizeof(data), i, forkId | SIGHASH_ALL); + data.resize(_BRTransactionWitnessData(tx, NULL, 0, i, forkId | SIGHASH_ALL)); + size_t dataLen = _BRTransactionWitnessData(tx, data.data(), data.size(), i, forkId | SIGHASH_ALL); - BRSHA256_2(&md, data, dataLen); + BRSHA256_2(&md, data.data(), dataLen); sigLen = BRKeySign(&keys[j], sig, sizeof(sig) - 1, md); sig[sigLen++] = forkId | SIGHASH_ALL; - scriptLen = BRScriptPushData(script, sizeof(script), sig, sigLen); - scriptLen += BRScriptPushData(&script[scriptLen], sizeof(script) - scriptLen, pubKey, pkLen); - BRTxInputSetSignature(input, script, 0); - BRTxInputSetWitness(input, script, scriptLen); + scriptLen = BRScriptPushData(script.data(), script.size(), sig, sigLen); + scriptLen += BRScriptPushData(&script[scriptLen], script.size() - scriptLen, pubKey.data(), pkLen); + BRTxInputSetSignature(input, script.data(), 0); + BRTxInputSetWitness(input, script.data(), scriptLen); } else if (elemsCount >= 2 && *elems[elemsCount - 2] == OP_EQUALVERIFY) { // pay-to-pubkey-hash - uint8_t data[_BRTransactionData(tx, NULL, 0, i, forkId | SIGHASH_ALL)]; - size_t dataLen = _BRTransactionData(tx, data, sizeof(data), i, forkId | SIGHASH_ALL); + data.resize(_BRTransactionData(tx, NULL, 0, i, forkId | SIGHASH_ALL)); + size_t dataLen = _BRTransactionData(tx, data.data(), data.size(), i, forkId | SIGHASH_ALL); - BRSHA256_2(&md, data, dataLen); + BRSHA256_2(&md, data.data(), dataLen); sigLen = BRKeySign(&keys[j], sig, sizeof(sig) - 1, md); sig[sigLen++] = forkId | SIGHASH_ALL; - scriptLen = BRScriptPushData(script, sizeof(script), sig, sigLen); - scriptLen += BRScriptPushData(&script[scriptLen], sizeof(script) - scriptLen, pubKey, pkLen); - BRTxInputSetSignature(input, script, scriptLen); - BRTxInputSetWitness(input, script, 0); + scriptLen = BRScriptPushData(script.data(), script.size(), sig, sigLen); + scriptLen += BRScriptPushData(&script[scriptLen], script.size() - scriptLen, pubKey.data(), pkLen); + BRTxInputSetSignature(input, script.data(), scriptLen); + BRTxInputSetWitness(input, script.data(), 0); } else if (elemsCount == 12 && *elems[0] == OP_IF && *elems[1] == OP_SHA256 && *elems[3] == OP_EQUALVERIFY && // HTLC *elems[5] == OP_ELSE && *elems[7] == OP_CHECKSEQUENCEVERIFY && *elems[8] == OP_DROP && *elems[10] == OP_ENDIF && *elems[11] == OP_CHECKSIG) { - uint8_t data[_BRTransactionData(tx, NULL, 0, i, forkId | SIGHASH_ALL)]; - size_t dataLen = _BRTransactionData(tx, data, sizeof(data), i, forkId | SIGHASH_ALL); + data.resize(_BRTransactionData(tx, NULL, 0, i, forkId | SIGHASH_ALL)); + size_t dataLen = _BRTransactionData(tx, data.data(), data.size(), i, forkId | SIGHASH_ALL); - BRSHA256_2(&md, data, dataLen); + BRSHA256_2(&md, data.data(), dataLen); sigLen = BRKeySign(&keys[j], sig, sizeof(sig) - 1, md); sig[sigLen++] = forkId | SIGHASH_ALL; // Add signature - scriptLen = BRScriptPushData(script, sizeof(script), sig, sigLen); + scriptLen = BRScriptPushData(script.data(), script.size(), sig, sigLen); // Add seed - scriptLen += BRScriptPushData(&script[scriptLen], sizeof(script) - scriptLen, &seed[1], seed[0]); + scriptLen += BRScriptPushData(&script[scriptLen], script.size() - scriptLen, &seed[1], seed[0]); if (htlcType == ScriptTypeSeller) { @@ -747,28 +746,28 @@ int BRTransactionSign(BRTransaction *tx, int forkId, BRKey keys[], size_t keysCo } // Add redeemscript - scriptLen += BRScriptPushData(&script[scriptLen], sizeof(script) - scriptLen, input->script, input->scriptLen); + scriptLen += BRScriptPushData(&script[scriptLen], script.size() - scriptLen, input->script, input->scriptLen); - BRTxInputSetSignature(input, script, scriptLen); - BRTxInputSetWitness(input, script, 0); + BRTxInputSetSignature(input, script.data(), scriptLen); + BRTxInputSetWitness(input, script.data(), 0); } else { // pay-to-pubkey - uint8_t data[_BRTransactionData(tx, NULL, 0, i, forkId | SIGHASH_ALL)]; - size_t dataLen = _BRTransactionData(tx, data, sizeof(data), i, forkId | SIGHASH_ALL); + data.resize(_BRTransactionData(tx, NULL, 0, i, forkId | SIGHASH_ALL)); + size_t dataLen = _BRTransactionData(tx, data.data(), data.size(), i, forkId | SIGHASH_ALL); - BRSHA256_2(&md, data, dataLen); + BRSHA256_2(&md, data.data(), dataLen); sigLen = BRKeySign(&keys[j], sig, sizeof(sig) - 1, md); sig[sigLen++] = forkId | SIGHASH_ALL; - scriptLen = BRScriptPushData(script, sizeof(script), sig, sigLen); - BRTxInputSetSignature(input, script, scriptLen); - BRTxInputSetWitness(input, script, 0); + scriptLen = BRScriptPushData(script.data(), script.size(), sig, sigLen); + BRTxInputSetSignature(input, script.data(), scriptLen); + BRTxInputSetWitness(input, script.data(), 0); } } if (tx && BRTransactionIsSigned(tx)) { - uint8_t data[BRTransactionSerialize(tx, NULL, 0)]; - size_t len = BRTransactionSerialize(tx, data, sizeof(data)); - BRTransaction *t = BRTransactionParse(data, len); + std::vector data(BRTransactionSerialize(tx, NULL, 0)); + size_t len = BRTransactionSerialize(tx, data.data(), data.size()); + BRTransaction *t = BRTransactionParse(data.data(), len); if (t) tx->txHash = t->txHash, tx->wtxHash = t->wtxHash; if (t) BRTransactionFree(t); diff --git a/src/spv/bitcoin/BRWallet.cpp b/src/spv/bitcoin/BRWallet.cpp index edda8d51fe..dbb988a168 100644 --- a/src/spv/bitcoin/BRWallet.cpp +++ b/src/spv/bitcoin/BRWallet.cpp @@ -135,13 +135,13 @@ inline static int _BRWalletTxIsAscending(BRWallet *wallet, const BRTransaction * inline static int _BRWalletTxCompare(BRWallet *wallet, const BRTransaction *tx1, const BRTransaction *tx2) { - size_t i = -1, j = -1; + size_t i = -1, j = -1, err = -1; if (_BRWalletTxIsAscending(wallet, tx1, tx2)) return 1; if (_BRWalletTxIsAscending(wallet, tx2, tx1)) return -1; - if ((i = _txChainIndex(tx1, wallet->internalChain)) != -1) j = _txChainIndex(tx2, wallet->internalChain); - if (j == -1 && (i = _txChainIndex(tx1, wallet->externalChain)) != -1) j = _txChainIndex(tx2, wallet->externalChain); - if (i != -1 && j != -1 && i != j) return (i > j) ? 1 : -1; + if ((i = _txChainIndex(tx1, wallet->internalChain)) != err) j = _txChainIndex(tx2, wallet->internalChain); + if (j == err && (i = _txChainIndex(tx1, wallet->externalChain)) != err) j = _txChainIndex(tx2, wallet->externalChain); + if (i != err && j != err && i != j) return (i > j) ? 1 : -1; return 0; } @@ -584,12 +584,13 @@ size_t BRWalletUnusedAddrs(BRWallet *wallet, BRAddress addrs[], uint32_t gapLimi // keep only the trailing contiguous block of addresses with no transactions while (i > 0 && ! BRSetContains(wallet->usedPKH, &chain[i - 1])) i--; + std::vector pubKey; while (i + gapLimit > count) { // generate new addresses up to gapLimit BRKey key; - uint8_t pubKey[BRBIP32PubKey(NULL, 0, wallet->masterPubKey, internal, count)]; - size_t len = BRBIP32PubKey(pubKey, sizeof(pubKey), wallet->masterPubKey, internal, (uint32_t)count); + pubKey.resize(BRBIP32PubKey(NULL, 0, wallet->masterPubKey, internal, count)); + size_t len = BRBIP32PubKey(pubKey.data(), pubKey.size(), wallet->masterPubKey, internal, (uint32_t)count); - if (! BRKeySetPubKey(&key, pubKey, len)) break; + if (! BRKeySetPubKey(&key, pubKey.data(), len)) break; array_add(chain, BRKeyHash160(&key)); count++; if (BRSetContains(wallet->usedPKH, &chain[array_count(chain) - 1])) i = count; @@ -1030,14 +1031,14 @@ BRTransaction *BRWalletCreateTxForOutputs(BRWallet *wallet, const BRTxOutput out wallet->lock.unlock(); if (outputs[outCount - 1].amount > amount + feeAmount + minAmount - balance) { - BRTxOutput newOutputs[outCount]; + std::vector newOutputs(outCount); for (j = 0; j < outCount; j++) { newOutputs[j] = outputs[j]; } newOutputs[outCount - 1].amount -= amount + feeAmount - balance; // reduce last output amount - transaction = BRWalletCreateTxForOutputs(wallet, newOutputs, outCount, changeAddress, errorMsg); + transaction = BRWalletCreateTxForOutputs(wallet, newOutputs.data(), outCount, changeAddress, errorMsg); } else transaction = BRWalletCreateTxForOutputs(wallet, outputs, outCount - 1, changeAddress, errorMsg); // remove last output @@ -1074,10 +1075,10 @@ BRTransaction *BRWalletCreateTxForOutputs(BRWallet *wallet, const BRTxOutput out } else if (transaction && balance - (amount + feeAmount) > minAmount) { // add change output BRWalletUnusedAddrs(wallet, &addr, 1, 1); - uint8_t script[BRAddressScriptPubKey(NULL, 0, changeAddress.c_str())]; - size_t scriptLen = BRAddressScriptPubKey(script, sizeof(script), changeAddress.c_str()); + std::vector script(BRAddressScriptPubKey(NULL, 0, changeAddress.c_str())); + size_t scriptLen = BRAddressScriptPubKey(script.data(), script.size(), changeAddress.c_str()); - BRTransactionAddOutput(transaction, balance - (amount + feeAmount), script, scriptLen); + BRTransactionAddOutput(transaction, balance - (amount + feeAmount), script.data(), scriptLen); BRTransactionShuffleOutputs(transaction); } @@ -1089,7 +1090,8 @@ BRTransaction *BRWalletCreateTxForOutputs(BRWallet *wallet, const BRTxOutput out // returns true if all inputs were signed, or false if there was an error or not all inputs were able to be signed int BRWalletSignTransaction(BRWallet *wallet, BRTransaction *tx, const void *seed, size_t seedLen) { - uint32_t j, internalIdx[tx->inCount], externalIdx[tx->inCount]; + uint32_t j; + std::vector internalIdx(tx->inCount), externalIdx(tx->inCount); size_t i, internalCount = 0, externalCount = 0; int forkId, r = 0; @@ -1112,14 +1114,14 @@ int BRWalletSignTransaction(BRWallet *wallet, BRTransaction *tx, const void *see wallet->lock.unlock(); - BRKey keys[internalCount + externalCount]; + std::vector keys(internalCount + externalCount); if (seed) { - BRBIP32PrivKeyList(keys, internalCount, seed, seedLen, SEQUENCE_INTERNAL_CHAIN, internalIdx); - BRBIP32PrivKeyList(&keys[internalCount], externalCount, seed, seedLen, SEQUENCE_EXTERNAL_CHAIN, externalIdx); + BRBIP32PrivKeyList(keys.data(), internalCount, seed, seedLen, SEQUENCE_INTERNAL_CHAIN, internalIdx.data()); + BRBIP32PrivKeyList(&keys[internalCount], externalCount, seed, seedLen, SEQUENCE_EXTERNAL_CHAIN, externalIdx.data()); // TODO: XXX wipe seed callback seed = NULL; - if (tx) r = BRTransactionSign(tx, forkId, keys, internalCount + externalCount); + if (tx) r = BRTransactionSign(tx, forkId, keys.data(), internalCount + externalCount); for (i = 0; i < internalCount + externalCount; i++) BRKeyClean(&keys[i]); } else r = -1; // user canceled authentication @@ -1362,7 +1364,7 @@ void BRWalletUpdateTransactions(BRWallet *wallet, const UInt256 txHashes[], size uint32_t timestamp, const UInt256& blockHash) { BRTransaction *tx; - UInt256 hashes[txCount]; + std::vector hashes(txCount); int needsUpdate = 0; size_t i, j, k; @@ -1396,7 +1398,7 @@ void BRWalletUpdateTransactions(BRWallet *wallet, const UInt256 txHashes[], size if (needsUpdate) _BRWalletUpdateBalance(wallet); wallet->lock.unlock(); - if (j > 0 && wallet->txUpdated) wallet->txUpdated(wallet->callbackInfo, hashes, j, blockHeight, timestamp, blockHash); + if (j > 0 && wallet->txUpdated) wallet->txUpdated(wallet->callbackInfo, hashes.data(), j, blockHeight, timestamp, blockHash); } // marks all transactions confirmed after blockHeight as unconfirmed (useful for chain re-orgs) @@ -1411,7 +1413,7 @@ void BRWalletSetTxUnconfirmedAfter(BRWallet *wallet, uint32_t blockHeight) while (i > 0 && wallet->transactions[i - 1]->blockHeight > blockHeight) i--; count -= i; - UInt256 hashes[count]; + std::vector hashes(count); for (j = 0; j < count; j++) { wallet->transactions[i + j]->blockHeight = TX_UNCONFIRMED; @@ -1420,7 +1422,7 @@ void BRWalletSetTxUnconfirmedAfter(BRWallet *wallet, uint32_t blockHeight) if (count > 0) _BRWalletUpdateBalance(wallet); wallet->lock.unlock(); - if (count > 0 && wallet->txUpdated) wallet->txUpdated(wallet->callbackInfo, hashes, count, TX_UNCONFIRMED, 0, UINT256_ZERO); + if (count > 0 && wallet->txUpdated) wallet->txUpdated(wallet->callbackInfo, hashes.data(), count, TX_UNCONFIRMED, 0, UINT256_ZERO); } // returns the amount received by the wallet from the transaction (total outputs to change and/or receive addresses) diff --git a/src/spv/spv_wrapper.cpp b/src/spv/spv_wrapper.cpp index ae37735169..11f21f64e5 100644 --- a/src/spv/spv_wrapper.cpp +++ b/src/spv/spv_wrapper.cpp @@ -246,6 +246,7 @@ void CSpvWrapper::Load() auto htlcAddresses = new BRUserAddresses; const auto wallets = GetWallets(); for (const auto& item : wallets) { + LOCK(item->cs_wallet); for (const auto& entry : item->mapAddressBook) { if (entry.second.purpose == "spv") @@ -1355,6 +1356,7 @@ UniValue CSpvWrapper::RefundAllHTLC(CWallet* const pwallet, const char *destinat std::set htlcAddresses; const auto wallets = GetWallets(); for (const auto& item : wallets) { + LOCK(item->cs_wallet); for (const auto& entry : item->mapAddressBook) { if (entry.second.purpose == "htlc") { htlcAddresses.insert(*boost::get(&entry.first)); diff --git a/src/spv/support/BRAddress.cpp b/src/spv/support/BRAddress.cpp index db8ce4aa15..45d3c3ad2b 100644 --- a/src/spv/support/BRAddress.cpp +++ b/src/spv/support/BRAddress.cpp @@ -236,8 +236,9 @@ const uint8_t *BRScriptPKH(const uint8_t *script, size_t scriptLen) assert(script != NULL || scriptLen == 0); if (! script || scriptLen == 0 || scriptLen > MAX_SCRIPT_LENGTH) return NULL; - const uint8_t *elems[BRScriptElements(NULL, 0, script, scriptLen)], *r = NULL; - size_t l, count = BRScriptElements(elems, sizeof(elems)/sizeof(*elems), script, scriptLen); + const uint8_t *r = NULL; + std::vector elems(BRScriptElements(NULL, 0, script, scriptLen)); + size_t l, count = BRScriptElements(elems.data(), elems.size(), script, scriptLen); if (count == 5 && *elems[0] == OP_DUP && *elems[1] == OP_HASH160 && *elems[2] == 20 && *elems[3] == OP_EQUALVERIFY && *elems[4] == OP_CHECKSIG) { @@ -259,8 +260,9 @@ const UInt160 BRHTLCScriptPKH(const uint8_t *script, size_t scriptLen, HTLCScrip assert(script != NULL || scriptLen == 0); if (! script || scriptLen == 0 || scriptLen > MAX_SCRIPT_LENGTH) return UINT160_ZERO; - const uint8_t *elems[BRScriptElements(NULL, 0, script, scriptLen)], *r = NULL; - size_t l, count = BRScriptElements(elems, sizeof(elems)/sizeof(*elems), script, scriptLen); + const uint8_t *r = NULL; + std::vector elems(BRScriptElements(NULL, 0, script, scriptLen)); + size_t l = 0, count = BRScriptElements(elems.data(), elems.size(), script, scriptLen); UInt160 hash160 = UINT160_ZERO; @@ -297,8 +299,9 @@ size_t BRAddressFromScriptPubKey(char *addr, size_t addrLen, const uint8_t *scri char a[91]; uint8_t data[21]; - const uint8_t *d, *elems[BRScriptElements(NULL, 0, script, scriptLen)]; - size_t r = 0, l = 0, count = BRScriptElements(elems, sizeof(elems)/sizeof(*elems), script, scriptLen); + const uint8_t *d; + std::vector elems(BRScriptElements(NULL, 0, script, scriptLen)); + size_t r = 0, l = 0, count = BRScriptElements(elems.data(), elems.size(), script, scriptLen); BRChainParams const * params = BRGetChainParams(); if (count == 5 && *elems[0] == OP_DUP && *elems[1] == OP_HASH160 && *elems[2] == 20 && @@ -340,8 +343,9 @@ size_t BRAddressFromScriptSig(char *addr, size_t addrLen, const uint8_t *script, if (! script || scriptLen == 0 || scriptLen > MAX_SCRIPT_LENGTH) return 0; uint8_t data[21]; - const uint8_t *d = NULL, *elems[BRScriptElements(NULL, 0, script, scriptLen)]; - size_t l = 0, count = BRScriptElements(elems, sizeof(elems)/sizeof(*elems), script, scriptLen); + const uint8_t *d = NULL; + std::vector elems(BRScriptElements(NULL, 0, script, scriptLen)); + size_t l = 0, count = BRScriptElements(elems.data(), elems.size(), script, scriptLen); data[0] = BRGetChainParams()->base58_p2pkh; diff --git a/src/spv/support/BRArray.h b/src/spv/support/BRArray.h index 7d6086978a..9a9573c548 100644 --- a/src/spv/support/BRArray.h +++ b/src/spv/support/BRArray.h @@ -61,7 +61,6 @@ extern "C" { #define array_new(array, capacity) do {\ size_t _array_cap = (capacity);\ - assert(_array_cap >= 0);\ (array) = static_cast::type>((void *)((size_t *)calloc(1, _array_cap*sizeof(*(array)) + sizeof(size_t)*2) + 2));\ assert((array) != NULL);\ array_capacity(array) = _array_cap;\ @@ -86,7 +85,6 @@ extern "C" { #define array_set_count(array, count) do {\ size_t _array_cnt = (count);\ assert((array) != NULL);\ - assert(_array_cnt >= 0);\ if (_array_cnt > array_capacity(array))\ array_set_capacity(array, _array_cnt);\ if (_array_cnt < array_count(array))\ @@ -105,7 +103,6 @@ extern "C" { assert((array) != NULL);\ size_t _array_cnt = (count), _array_i = array_count(array), _array_j = 0;\ assert((other_array) != NULL || _array_cnt == 0);\ - assert(_array_cnt >= 0);\ if (_array_i + _array_cnt > array_capacity(array))\ array_set_capacity(array, (_array_i + _array_cnt)*3/2);\ while (_array_j < _array_cnt)\ @@ -116,7 +113,7 @@ extern "C" { #define array_insert(array, index, item) do {\ assert((array) != NULL);\ size_t _array_idx = (index), _array_i = ++array_count(array);\ - assert(_array_idx >= 0 && _array_idx < array_count(array));\ + assert(_array_idx < array_count(array));\ if (_array_i > array_capacity(array))\ array_set_capacity(array, (array_capacity(array) + 1)*3/2);\ while (--_array_i > _array_idx)\ @@ -127,9 +124,8 @@ extern "C" { #define array_insert_array(array, index, other_array, count) do {\ assert((array) != NULL);\ size_t _array_idx = (index), _array_cnt = (count), _array_i = array_count(array) + _array_cnt, _array_j = 0;\ - assert(_array_idx >= 0 && _array_idx <= array_count(array));\ + assert(_array_idx <= array_count(array));\ assert((other_array) != NULL || _array_cnt == 0);\ - assert(_array_cnt >= 0);\ if (_array_i > array_capacity(array))\ array_set_capacity(array, _array_i*3/2);\ while (_array_i-- > _array_idx + _array_cnt)\ @@ -142,7 +138,7 @@ extern "C" { #define array_rm(array, index) do {\ size_t _array_i = (index);\ assert((array) != NULL);\ - assert(_array_i >= 0 && _array_i < array_count(array));\ + assert(_array_i < array_count(array));\ array_count(array)--;\ while (_array_i < array_count(array))\ (array)[_array_i] = (array)[_array_i + 1], _array_i++;\ @@ -158,8 +154,8 @@ extern "C" { #define array_rm_range(array, index, len) do {\ size_t _array_i = (index), _array_len = (len);\ assert((array) != NULL);\ - assert(_array_i >= 0 && _array_i < array_count(array));\ - assert(_array_len >= 0 && _array_i + _array_len <= array_count(array));\ + assert(_array_i < array_count(array));\ + assert(_array_i + _array_len <= array_count(array));\ array_count(array) -= _array_len;\ while (_array_i < array_count(array))\ (array)[_array_i] = (array)[_array_i + _array_len], _array_i++;\ diff --git a/src/spv/support/BRBIP32Sequence.cpp b/src/spv/support/BRBIP32Sequence.cpp index 8a1b32c441..88c05dcdd6 100644 --- a/src/spv/support/BRBIP32Sequence.cpp +++ b/src/spv/support/BRBIP32Sequence.cpp @@ -232,7 +232,7 @@ size_t _BRBIP32Serialize(char *str, size_t strLen, uint8_t depth, uint32_t finge const void *key, size_t keyLen) { size_t len, off = 0; - uint8_t data[4 + sizeof(depth) + sizeof(fingerprint) + sizeof(child) + sizeof(chain) + 1 + keyLen]; + std::vector data(4 + sizeof(depth) + sizeof(fingerprint) + sizeof(child) + sizeof(chain) + 1 + keyLen); memcpy(&data[off], (keyLen < 33 ? BRGetChainParams()->bip32_xprv : BRGetChainParams()->bip32_xpub), 4); off += 4; @@ -247,8 +247,8 @@ size_t _BRBIP32Serialize(char *str, size_t strLen, uint8_t depth, uint32_t finge if (keyLen < 33) data[off++] = 0; memcpy(&data[off], key, keyLen); off += keyLen; - len = BRBase58CheckEncode(str, strLen, data, off); - mem_clean(data, sizeof(data)); + len = BRBase58CheckEncode(str, strLen, data.data(), off); + mem_clean(data.data(), data.size()); return len; } @@ -284,7 +284,7 @@ BRMasterPubKey BRBIP32ParseMasterPubKey(const char *str) size_t dataLen = BRBase58CheckDecode(data, sizeof(data), str); if (dataLen == sizeof(data) && memcmp(data, BRGetChainParams()->bip32_xpub, 4) == 0) { union conv { uint8_t u8[4]; uint32_t u32; }; - mpk.fingerPrint = (conv{ data[5], data[6], data[7], data[8] }).u32; + mpk.fingerPrint = (conv{{data[5], data[6], data[7], data[8]}}).u32; mpk.chainCode = UInt256Get(&data[13]); memcpy(mpk.pubKey, &data[45], sizeof(mpk.pubKey)); } @@ -308,11 +308,11 @@ void BRBIP32BitIDKey(BRKey *key, const void *seed, size_t seedLen, uint32_t inde if (key && (seed || seedLen == 0) && uri) { UInt256 hash; size_t uriLen = strlen(uri); - uint8_t data[sizeof(index) + uriLen]; + std::vector data(sizeof(index) + uriLen); - UInt32SetLE(data, index); + UInt32SetLE(data.data(), index); memcpy(&data[sizeof(index)], uri, uriLen); - BRSHA256(&hash, data, sizeof(data)); + BRSHA256(&hash, data.data(), data.size()); BRBIP32PrivKeyPath(key, seed, seedLen, 5, 13 | BIP32_HARD, UInt32GetLE(&hash.u32[0]) | BIP32_HARD, UInt32GetLE(&hash.u32[1]) | BIP32_HARD, UInt32GetLE(&hash.u32[2]) | BIP32_HARD, UInt32GetLE(&hash.u32[3]) | BIP32_HARD); // path m/13H/aH/bH/cH/dH diff --git a/src/spv/support/BRBIP39Mnemonic.cpp b/src/spv/support/BRBIP39Mnemonic.cpp index 283cc96373..95f2f6fecc 100644 --- a/src/spv/support/BRBIP39Mnemonic.cpp +++ b/src/spv/support/BRBIP39Mnemonic.cpp @@ -32,7 +32,7 @@ size_t BRBIP39Encode(char *phrase, size_t phraseLen, const char *wordList[], const uint8_t *data, size_t dataLen) { uint32_t x; - uint8_t buf[dataLen + 32]; + std::vector buf(dataLen + 32); const char *word; size_t i, len = 0; @@ -41,7 +41,7 @@ size_t BRBIP39Encode(char *phrase, size_t phraseLen, const char *wordList[], con assert(dataLen > 0 && (dataLen % 4) == 0); if (! data || (dataLen % 4) != 0) return 0; // data length must be a multiple of 32 bits - memcpy(buf, data, dataLen); + memcpy(buf.data(), data, dataLen); BRSHA256(&buf[dataLen], data, dataLen); // append SHA256 checksum for (i = 0; i < dataLen*3/4; i++) { @@ -55,7 +55,7 @@ size_t BRBIP39Encode(char *phrase, size_t phraseLen, const char *wordList[], con var_clean(&word); var_clean(&x); - mem_clean(buf, sizeof(buf)); + mem_clean(buf.data(), buf.size()); return (! phrase || len + 1 <= phraseLen) ? len + 1 : 0; } @@ -85,7 +85,7 @@ size_t BRBIP39Decode(uint8_t *data, size_t dataLen, const char *wordList[], cons } if ((count % 3) == 0 && (! word || *word == '\0')) { // check that phrase has correct number of words - uint8_t buf[(count*11 + 7)/8]; + std::vector buf((count*11 + 7)/8); for (i = 0; i < (count*11 + 7)/8; i++) { x = idx[i*8/11]; @@ -94,14 +94,14 @@ size_t BRBIP39Decode(uint8_t *data, size_t dataLen, const char *wordList[], cons buf[i] = b; } - BRSHA256(hash, buf, count*4/3); + BRSHA256(hash, buf.data(), count*4/3); if (b >> (8 - count/3) == (hash[0] >> (8 - count/3))) { // verify checksum r = count*4/3; - if (data && r <= dataLen) memcpy(data, buf, r); + if (data && r <= dataLen) memcpy(data, buf.data(), r); } - mem_clean(buf, sizeof(buf)); + mem_clean(buf.data(), buf.size()); } var_clean(&b); @@ -123,15 +123,13 @@ int BRBIP39PhraseIsValid(const char *wordList[], const char *phrase) // BUG: does not currently support passphrases containing NULL characters void BRBIP39DeriveKey(void *key64, const char *phrase, const char *passphrase) { - char salt[strlen("mnemonic") + (passphrase ? strlen(passphrase) : 0) + 1]; - assert(key64 != NULL); assert(phrase != NULL); if (phrase) { - strcpy(salt, "mnemonic"); - if (passphrase) strcpy(salt + strlen("mnemonic"), passphrase); - BRPBKDF2(key64, 64, BRSHA512, 512/8, phrase, strlen(phrase), salt, strlen(salt), 2048); - mem_clean(salt, sizeof(salt)); + std::string salt("mnemonic"); + if (passphrase) salt += passphrase; + BRPBKDF2(key64, 64, BRSHA512, 512/8, phrase, strlen(phrase), salt.data(), salt.size(), 2048); + mem_clean(salt.data(), salt.size()); } } diff --git a/src/spv/support/BRBase58.cpp b/src/spv/support/BRBase58.cpp index 0c3cdfc925..20c64024a8 100644 --- a/src/spv/support/BRBase58.cpp +++ b/src/spv/support/BRBase58.cpp @@ -30,6 +30,8 @@ #include #include +#include + // base58 and base58check encoding: https://en.bitcoin.it/wiki/Base58Check_encoding // returns the number of characters written to str including NULL terminator, or total strLen needed if str is NULL @@ -41,14 +43,12 @@ size_t BRBase58Encode(char *str, size_t strLen, const uint8_t *data, size_t data assert(data != NULL); while (zcount < dataLen && data && data[zcount] == 0) zcount++; // count leading zeroes - uint8_t buf[(dataLen - zcount)*138/100 + 1]; // log(256)/log(58), rounded up - - memset(buf, 0, sizeof(buf)); + std::vector buf((dataLen - zcount)*138/100 + 1); // log(256)/log(58), rounded up for (i = zcount; data && i < dataLen; i++) { uint32_t carry = data[i]; - for (j = sizeof(buf); j > 0; j--) { + for (j = buf.size(); j > 0; j--) { carry += (uint32_t)buf[j - 1] << 8; buf[j - 1] = carry % 58; carry /= 58; @@ -58,16 +58,16 @@ size_t BRBase58Encode(char *str, size_t strLen, const uint8_t *data, size_t data } i = 0; - while (i < sizeof(buf) && buf[i] == 0) i++; // skip leading zeroes - len = (zcount + sizeof(buf) - i) + 1; + while (i < buf.size() && buf[i] == 0) i++; // skip leading zeroes + len = (zcount + buf.size() - i) + 1; if (str && len <= strLen) { for (; zcount > 0; --zcount) *(str++) = chars[0]; - while (i < sizeof(buf)) *(str++) = chars[buf[i++]]; + while (i < buf.size()) *(str++) = chars[buf[i++]]; *str = '\0'; } - mem_clean(buf, sizeof(buf)); + mem_clean(buf.data(), buf.size()); return (! str || len <= strLen) ? len : 0; } @@ -79,9 +79,7 @@ size_t BRBase58Decode(uint8_t *data, size_t dataLen, const char *str) assert(str != NULL); while (str && *str == '1') str++, zcount++; // count leading zeroes - uint8_t buf[(str) ? strlen(str)*733/1000 + 1 : 0]; // log(58)/log(256), rounded up - - memset(buf, 0, sizeof(buf)); + std::vector buf((str) ? strlen(str)*733/1000 + 1 : 0); // log(58)/log(256), rounded up while (str && *str) { uint32_t carry = *(const uint8_t *)(str++); @@ -124,7 +122,7 @@ size_t BRBase58Decode(uint8_t *data, size_t dataLen, const char *str) if (carry >= 58) break; // invalid base58 digit - for (j = sizeof(buf); j > 0; j--) { + for (j = buf.size(); j > 0; j--) { carry += (uint32_t)buf[j - 1]*58; buf[j - 1] = carry & 0xff; carry >>= 8; @@ -132,15 +130,15 @@ size_t BRBase58Decode(uint8_t *data, size_t dataLen, const char *str) carry = 0; } - while (i < sizeof(buf) && buf[i] == 0) i++; // skip leading zeroes - len = zcount + sizeof(buf) - i; + while (i < buf.size() && buf[i] == 0) i++; // skip leading zeroes + len = zcount + buf.size() - i; if (data && len <= dataLen) { if (zcount > 0) memset(data, 0, zcount); - memcpy(&data[zcount], &buf[i], sizeof(buf) - i); + memcpy(&data[zcount], &buf[i], buf.size() - i); } - mem_clean(buf, sizeof(buf)); + mem_clean(buf.data(), buf.size()); return (! data || len <= dataLen) ? len : 0; } diff --git a/src/spv/support/BRBech32.cpp b/src/spv/support/BRBech32.cpp index de17993101..3c04d708e1 100644 --- a/src/spv/support/BRBech32.cpp +++ b/src/spv/support/BRBech32.cpp @@ -34,8 +34,8 @@ // bech32 address format: https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki -//#define polymod(x) ((((x) & 0x1ffffff) << 5) ^ (-(((x) >> 25) & 1) & 0x3b6a57b2) ^\ -// (-(((x) >> 26) & 1) & 0x26508e6d) ^ (-(((x) >> 27) & 1) & 0x1ea119fa) ^\ +//#define polymod(x) ((((x) & 0x1ffffff) << 5) ^ (-(((x) >> 25) & 1) & 0x3b6a57b2) ^ +// (-(((x) >> 26) & 1) & 0x26508e6d) ^ (-(((x) >> 27) & 1) & 0x1ea119fa) ^ // (-(((x) >> 28) & 1) & 0x3d4233dd) ^ (-(((x) >> 29) & 1) & 0x2a1462b3)) #define polymod(x) ((((x) & 0x1ffffff) << 5) ^ ((((x) >> 25) & 1) ? 0x3b6a57b2 : 0) ^\ diff --git a/src/spv/support/BRCrypto.cpp b/src/spv/support/BRCrypto.cpp index 27345c9249..264b137aba 100644 --- a/src/spv/support/BRCrypto.cpp +++ b/src/spv/support/BRCrypto.cpp @@ -27,6 +27,8 @@ #include #include +#include + // endian swapping #if __BIG_ENDIAN__ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) inline static uint32_t be32(uint32_t x) { return x; } @@ -42,7 +44,7 @@ inline static uint32_t be32(uint32_t x) { return (((x) & 0xff) << 24) | (((x) & inline static uint64_t le64(uint64_t x) { return x; } inline static uint64_t be64(uint64_t x) { union conv { uint32_t u32[2]; uint64_t u64; }; - return conv{ be32((uint32_t)((x) >> 32)), be32((uint32_t)(x)) }.u64; + return conv{{be32((uint32_t)((x) >> 32)), be32((uint32_t)(x))}}.u64; } #else // unknown endianess inline static uint32_t be32(uint32_t x) { @@ -673,8 +675,8 @@ void BRHMAC(void *mac, void (*hash)(void *, const void *, size_t), size_t hashLe const void *data, size_t dataLen) { size_t i, blockLen = (hashLen > 32) ? 128 : 64; - uint8_t k[hashLen]; - uint64_t kipad[(blockLen + dataLen)/sizeof(uint64_t) + 1], kopad[(blockLen + hashLen)/sizeof(uint64_t) + 1]; + std::vector k(hashLen); + std::vector kipad((blockLen + dataLen)/sizeof(uint64_t) + 1), kopad((blockLen + hashLen)/sizeof(uint64_t) + 1); assert(mac != NULL); assert(hash != NULL); @@ -682,20 +684,18 @@ void BRHMAC(void *mac, void (*hash)(void *, const void *, size_t), size_t hashLe assert(key != NULL || keyLen == 0); assert(data != NULL || dataLen == 0); - if (keyLen > blockLen) hash(k, key, keyLen), key = k, keyLen = sizeof(k); - memset(kipad, 0, blockLen); - memcpy(kipad, key, keyLen); + if (keyLen > blockLen) hash(k.data(), key, keyLen), key = k.data(), keyLen = k.size(); + memcpy(kipad.data(), key, keyLen); for (i = 0; i < blockLen/sizeof(uint64_t); i++) kipad[i] ^= 0x3636363636363636; - memset(kopad, 0, blockLen); - memcpy(kopad, key, keyLen); + memcpy(kopad.data(), key, keyLen); for (i = 0; i < blockLen/sizeof(uint64_t); i++) kopad[i] ^= 0x5c5c5c5c5c5c5c5c; memcpy(&kipad[blockLen/sizeof(uint64_t)], data, dataLen); - hash(&kopad[blockLen/sizeof(uint64_t)], kipad, blockLen + dataLen); - hash(mac, kopad, blockLen + hashLen); + hash(&kopad[blockLen/sizeof(uint64_t)], kipad.data(), blockLen + dataLen); + hash(mac, kopad.data(), blockLen + hashLen); - mem_clean(k, sizeof(k)); - mem_clean(kipad, blockLen); - mem_clean(kopad, blockLen); + mem_clean(k.data(), k.size()); + mem_clean(kipad.data(), blockLen); + mem_clean(kopad.data(), blockLen); } // hmac-drbg with no prediction resistance or additional input @@ -705,7 +705,7 @@ void BRHMACDRBG(void *out, size_t outLen, void *K, void *V, void (*hash)(void *, const void *seed, size_t seedLen, const void *nonce, size_t nonceLen, const void *ps, size_t psLen) { size_t i, bufLen = hashLen + 1 + seedLen + nonceLen + psLen; - uint8_t buf[bufLen]; + std::vector buf(bufLen); assert(out != NULL || outLen == 0); assert(K != NULL); @@ -720,22 +720,22 @@ void BRHMACDRBG(void *out, size_t outLen, void *K, void *V, void (*hash)(void *, for (i = 0; i < hashLen; i++) ((uint8_t *)K)[i] = 0x00, ((uint8_t *)V)[i] = 0x01; } - memcpy(buf, V, hashLen); + memcpy(buf.data(), V, hashLen); buf[hashLen] = 0x00; memcpy(&buf[hashLen + 1], seed, seedLen); memcpy(&buf[hashLen + 1 + seedLen], nonce, nonceLen); memcpy(&buf[hashLen + 1 + seedLen + nonceLen], ps, psLen); - BRHMAC(K, hash, hashLen, K, hashLen, buf, bufLen); // K = HMAC(K, V || 0x00 || entropy || nonce || ps) + BRHMAC(K, hash, hashLen, K, hashLen, buf.data(), bufLen); // K = HMAC(K, V || 0x00 || entropy || nonce || ps) BRHMAC(V, hash, hashLen, K, hashLen, V, hashLen); // V = HMAC(K, V) if (seed || nonce || ps) { - memcpy(buf, V, hashLen); + memcpy(buf.data(), V, hashLen); buf[hashLen] = 0x01; - BRHMAC(K, hash, hashLen, K, hashLen, buf, bufLen); // K = HMAC(K, V || 0x01 || entropy || nonce || ps) + BRHMAC(K, hash, hashLen, K, hashLen, buf.data(), bufLen); // K = HMAC(K, V || 0x01 || entropy || nonce || ps) BRHMAC(V, hash, hashLen, K, hashLen, V, hashLen); // V = HMAC(K, V) } - mem_clean(buf, bufLen); + mem_clean(buf.data(), bufLen); for (i = 0; i*hashLen < outLen; i++) { BRHMAC(V, hash, hashLen, K, hashLen, V, hashLen); // V = HMAC(K, V) @@ -939,7 +939,7 @@ size_t BRChacha20Poly1305AEADDecrypt(void *out, size_t outLen, const void *key32 _BRPoly1305Compress(h, macKey, pad, 16, 1); mem_clean(macKey, sizeof(macKey)); memcpy(mac, (const uint8_t *)data + outLen, 16); - if ((mac[0] ^ h[0]) | (mac[1] ^ h[1]) | (mac[2] ^ h[2]) | (mac[3] ^ h[3]) != 0) outLen = 0; // constant time compare + if (((mac[0] ^ h[0]) | (mac[1] ^ h[1]) | (mac[2] ^ h[2]) | (mac[3] ^ h[3])) != 0) outLen = 0; // constant time compare BRChacha20(out, key32, iv, data, outLen, le64(counter) + 1); return outLen; } @@ -1145,8 +1145,9 @@ void BRAESCTR_OFFSET(void *out, size_t outLen, const void *key, size_t keyLen, v void BRPBKDF2(void *dk, size_t dkLen, void (*hash)(void *, const void *, size_t), size_t hashLen, const void *pw, size_t pwLen, const void *salt, size_t saltLen, unsigned rounds) { - uint8_t s[saltLen + sizeof(uint32_t)]; - uint32_t i, j, U[hashLen/sizeof(uint32_t)], T[hashLen/sizeof(uint32_t)]; + std::vector s(saltLen + sizeof(uint32_t)); + std::vector U(hashLen/sizeof(uint32_t)), T(hashLen/sizeof(uint32_t)); + uint32_t i, j; assert(dk != NULL || dkLen == 0); assert(hash != NULL); @@ -1155,26 +1156,26 @@ void BRPBKDF2(void *dk, size_t dkLen, void (*hash)(void *, const void *, size_t) assert(salt != NULL || saltLen == 0); assert(rounds > 0); - memcpy(s, salt, saltLen); + memcpy(s.data(), salt, saltLen); for (i = 0; i < (dkLen + hashLen - 1)/hashLen; i++) { j = be32(i + 1); - memcpy(s + saltLen, &j, sizeof(j)); - BRHMAC(U, hash, hashLen, pw, pwLen, s, sizeof(s)); // U1 = hmac_hash(pw, salt || be32(i)) - memcpy(T, U, sizeof(U)); + memcpy(s.data() + saltLen, &j, sizeof(j)); + BRHMAC(U.data(), hash, hashLen, pw, pwLen, s.data(), s.size()); // U1 = hmac_hash(pw, salt || be32(i)) + memcpy(T.data(), U.data(), U.size()); for (unsigned r = 1; r < rounds; r++) { - BRHMAC(U, hash, hashLen, pw, pwLen, U, sizeof(U)); // Urounds = hmac_hash(pw, Urounds-1) + BRHMAC(U.data(), hash, hashLen, pw, pwLen, U.data(), U.size()); // Urounds = hmac_hash(pw, Urounds-1) for (j = 0; j < hashLen/sizeof(uint32_t); j++) T[j] ^= U[j]; // Ti = U1 ^ U2 ^ ... ^ Urounds } // dk = T1 || T2 || ... || Tdklen/hlen - memcpy((uint8_t *)dk + i*hashLen, T, (i*hashLen + hashLen <= dkLen) ? hashLen : dkLen % hashLen); + memcpy((uint8_t *)dk + i*hashLen, T.data(), (i*hashLen + hashLen <= dkLen) ? hashLen : dkLen % hashLen); } - mem_clean(s, sizeof(s)); - mem_clean(U, sizeof(U)); - mem_clean(T, sizeof(T)); + mem_clean(s.data(), s.size()); + mem_clean(U.data(), U.size()); + mem_clean(T.data(), T.size()); } // salsa20/8 stream cipher: http://cr.yp.to/snuffle.html @@ -1219,10 +1220,11 @@ static void _blockmix_salsa8(uint64_t *dest, const uint64_t *src, uint64_t *b, u void BRScrypt(void *dk, size_t dkLen, const void *pw, size_t pwLen, const void *salt, size_t saltLen, unsigned n, unsigned r, unsigned p) { - uint64_t x[16*r], y[16*r], z[8], *v = (uint64_t *)malloc(128*r*n), m; - uint32_t b[32*r*p]; + uint64_t z[8], m; + std::vector x(16*r), y(16*r); + std::vector v(16*r*n); + std::vector b(32*r*p); - assert(v != NULL); assert(dk != NULL || dkLen == 0); assert(pw != NULL || pwLen == 0); assert(salt != NULL || saltLen == 0); @@ -1230,35 +1232,34 @@ void BRScrypt(void *dk, size_t dkLen, const void *pw, size_t pwLen, const void * assert(r > 0); assert(p > 0); - BRPBKDF2(b, sizeof(b), BRSHA256, 256/8, pw, pwLen, salt, saltLen, 1); + BRPBKDF2(b.data(), b.size() * sizeof(uint32_t), BRSHA256, 256/8, pw, pwLen, salt, saltLen, 1); - for (int i = 0; i < p; i++) { - for (unsigned j = 0; j < 32*r; j++) ((uint32_t *)x)[j] = le32(b[i*32*r + j]); + for (unsigned i = 0; i < p; i++) { + for (unsigned j = 0; j < 32*r; j++) ((uint32_t *)x.data())[j] = le32(b[i*32*r + j]); for (unsigned j = 0; j < n; j += 2) { - memcpy(&v[j*(16*r)], x, 128*r); - _blockmix_salsa8(y, x, z, r); - memcpy(&v[(j + 1)*(16*r)], y, 128*r); - _blockmix_salsa8(x, y, z, r); + memcpy(&v[j*(16*r)], x.data(), 128*r); + _blockmix_salsa8(y.data(), x.data(), z, r); + memcpy(&v[(j + 1)*(16*r)], y.data(), 128*r); + _blockmix_salsa8(x.data(), y.data(), z, r); } for (unsigned j = 0; j < n; j += 2) { m = le64(x[(2*r - 1)*8]) & (n - 1); for (unsigned k = 0; k < 16*r; k++) x[k] ^= v[m*(16*r) + k]; - _blockmix_salsa8(y, x, z, r); + _blockmix_salsa8(y.data(), x.data(), z, r); m = le64(y[(2*r - 1)*8]) & (n - 1); for (unsigned k = 0; k < 16*r; k++) y[k] ^= v[m*(16*r) + k]; - _blockmix_salsa8(x, y, z, r); + _blockmix_salsa8(x.data(), y.data(), z, r); } - for (unsigned j = 0; j < 32*r; j++) b[i*32*r + j] = le32(((uint32_t *)x)[j]); + for (unsigned j = 0; j < 32*r; j++) b[i*32*r + j] = le32(((uint32_t *)x.data())[j]); } - BRPBKDF2(dk, dkLen, BRSHA256, 256/8, pw, pwLen, b, sizeof(b), 1); - mem_clean(b, sizeof(b)); - mem_clean(x, sizeof(x)); - mem_clean(y, sizeof(y)); + BRPBKDF2(dk, dkLen, BRSHA256, 256/8, pw, pwLen, b.data(), b.size(), 1); + mem_clean(b.data(), b.size()); + mem_clean(x.data(), x.size()); + mem_clean(y.data(), y.size()); + mem_clean(v.data(), v.size()); mem_clean(z, sizeof(z)); - mem_clean(v, 128*r*n); - free(v); } diff --git a/src/spv/support/BRKey.cpp b/src/spv/support/BRKey.cpp index 3c5b7dae82..4088fbd66a 100644 --- a/src/spv/support/BRKey.cpp +++ b/src/spv/support/BRKey.cpp @@ -44,20 +44,21 @@ #define USE_BASIC_CONFIG 1 #define ENABLE_MODULE_RECOVERY 1 +#ifdef __clang__ #pragma clang diagnostic push -#pragma GCC diagnostic push #pragma clang diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wconversion" #pragma clang diagnostic ignored "-Wunused-function" -#pragma GCC diagnostic ignored "-Wunused-function" #pragma clang diagnostic ignored "-Wconditional-uninitialized" -#ifndef __clang__ +#pragma clang diagnostic pop +#elif defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#pragma GCC diagnostic pop #endif #include "../secp256k1/src/basic-config.h" -#include "../secp256k1/src/secp256k1.c" -#pragma clang diagnostic pop -#pragma GCC diagnostic pop +#include "../secp256k1/include/secp256k1_recovery.h" static std::once_flag _rand_once; @@ -178,12 +179,12 @@ int BRPrivKeyIsValid(const char *privKey) r = (data[0] == BRGetChainParams()->privkey); } else if ((strLen == 30 || strLen == 22) && privKey[0] == 'S') { // mini private key format - char s[strLen + 2]; + char s[32] = {}; - strncpy(s, privKey, sizeof(s)); - s[sizeof(s) - 2] = '?'; - BRSHA256(data, s, sizeof(s) - 1); - mem_clean(s, sizeof(s)); + strcpy(s, privKey); + s[strLen] = '?'; + BRSHA256(data, s, strLen + 1); + mem_clean(s, strLen + 2); r = (data[0] == 0); } else r = (strspn(privKey, "0123456789ABCDEFabcdef") == 64); // hex encoded key @@ -497,18 +498,17 @@ size_t BRKeyCompactSignEthereum(const BRKey *key, void *compactSig, size_t sigLe // assigns pubKey recovered from compactSig to key and returns true on success int BRKeyRecoverPubKeyEthereum(BRKey *key, UInt256 md, const void *compactSig, size_t sigLen) { - int r = 0, compressed = 0, recid = 0; + int r = 0, recid = 0; uint8_t pubKey[65]; size_t len = sizeof(pubKey); secp256k1_ecdsa_recoverable_signature s; secp256k1_pubkey pk; - + assert(key != NULL); assert(compactSig != NULL); assert(sigLen == 65); - + if (sigLen == 65) { - compressed = 0; recid = ((uint8_t *)compactSig)[64]; if (secp256k1_ecdsa_recoverable_signature_parse_compact(_ctx, &s, (const uint8_t *)compactSig, recid) && secp256k1_ecdsa_recover(_ctx, &pk, &s, md.u8) && diff --git a/src/spv/support/BRSet.cpp b/src/spv/support/BRSet.cpp index f06dadd8c5..1cce4382c2 100644 --- a/src/spv/support/BRSet.cpp +++ b/src/spv/support/BRSet.cpp @@ -51,7 +51,6 @@ static void _BRSetInit(BRSet *set, size_t (*hash)(const void *), int (*eq)(const assert(set != NULL); assert(hash != NULL); assert(eq != NULL); - assert(capacity >= 0); size_t i = 0; @@ -237,8 +236,7 @@ size_t BRSetAll(const BRSet *set, void *allItems[], size_t count) { assert(set != NULL); assert(allItems != NULL || count == 0); - assert(count >= 0); - + size_t i = 0, j = 0, size = set->size; void *t; From a63e8430d5b9658c96b44875ca61c5cf9f8f11d6 Mon Sep 17 00:00:00 2001 From: Peter Bushnell Date: Wed, 9 Mar 2022 07:15:26 +0000 Subject: [PATCH 2/2] Cast to void* and use std::decay. --- src/spv/support/BRArray.h | 4 ++-- src/spv/support/BRBIP39Mnemonic.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/spv/support/BRArray.h b/src/spv/support/BRArray.h index 9a9573c548..9456bf81ff 100644 --- a/src/spv/support/BRArray.h +++ b/src/spv/support/BRArray.h @@ -61,7 +61,7 @@ extern "C" { #define array_new(array, capacity) do {\ size_t _array_cap = (capacity);\ - (array) = static_cast::type>((void *)((size_t *)calloc(1, _array_cap*sizeof(*(array)) + sizeof(size_t)*2) + 2));\ + (array) = static_cast::type>((void *)((size_t *)calloc(1, _array_cap*sizeof(*(array)) + sizeof(size_t)*2) + 2));\ assert((array) != NULL);\ array_capacity(array) = _array_cap;\ array_count(array) = 0;\ @@ -73,7 +73,7 @@ extern "C" { size_t _array_cap = (capacity);\ assert((array) != NULL);\ assert(_array_cap >= array_count(array));\ - (array) = static_cast::type>((void *)((size_t *)realloc((size_t *)(array) - 2, _array_cap*sizeof(*(array)) + sizeof(size_t)*2) + 2));\ + (array) = static_cast::type>((void *)((size_t *)realloc((size_t *)(array) - 2, _array_cap*sizeof(*(array)) + sizeof(size_t)*2) + 2));\ assert((array) != NULL);\ if (_array_cap > array_capacity(array))\ memset((array) + array_capacity(array), 0, (_array_cap - array_capacity(array))*sizeof(*(array)));\ diff --git a/src/spv/support/BRBIP39Mnemonic.cpp b/src/spv/support/BRBIP39Mnemonic.cpp index 95f2f6fecc..cf1a3d932f 100644 --- a/src/spv/support/BRBIP39Mnemonic.cpp +++ b/src/spv/support/BRBIP39Mnemonic.cpp @@ -130,6 +130,6 @@ void BRBIP39DeriveKey(void *key64, const char *phrase, const char *passphrase) std::string salt("mnemonic"); if (passphrase) salt += passphrase; BRPBKDF2(key64, 64, BRSHA512, 512/8, phrase, strlen(phrase), salt.data(), salt.size(), 2048); - mem_clean(salt.data(), salt.size()); + mem_clean((void *) salt.data(), salt.size()); } }