Skip to content

Commit fa2b52a

Browse files
author
MarcoFalke
committed
Disallow extended encoding for non-witness transactions (take 3)
1 parent e79bbb7 commit fa2b52a

File tree

2 files changed

+33
-14
lines changed

2 files changed

+33
-14
lines changed

src/net_processing.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3288,23 +3288,22 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
32883288
if (m_enable_bip61) {
32893289
connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, std::string("error parsing message")));
32903290
}
3291-
if (strstr(e.what(), "end of data"))
3292-
{
3291+
if (strstr(e.what(), "end of data")) {
32933292
// Allow exceptions from under-length message on vRecv
32943293
LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught, normally caused by a message being shorter than its stated length\n", __func__, SanitizeString(strCommand), nMessageSize, e.what());
3295-
}
3296-
else if (strstr(e.what(), "size too large"))
3297-
{
3294+
} else if (strstr(e.what(), "size too large")) {
32983295
// Allow exceptions from over-long size
32993296
LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what());
3300-
}
3301-
else if (strstr(e.what(), "non-canonical ReadCompactSize()"))
3302-
{
3297+
} else if (strstr(e.what(), "non-canonical ReadCompactSize()")) {
33033298
// Allow exceptions from non-canonical encoding
33043299
LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what());
3305-
}
3306-
else
3307-
{
3300+
} else if (strstr(e.what(), "Superfluous witness record")) {
3301+
// Allow exceptions from illegal witness encoding
3302+
LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what());
3303+
} else if (strstr(e.what(), "Unknown transaction optional data")) {
3304+
// Allow exceptions from unknown witness encoding
3305+
LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what());
3306+
} else {
33083307
PrintExceptionContinue(&e, "ProcessMessages()");
33093308
}
33103309
}

test/functional/p2p_segwit.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2038,9 +2038,9 @@ def test_witness_sigops(self):
20382038
# TODO: test p2sh sigop counting
20392039

20402040
def test_superfluous_witness(self):
2041-
# Serialization of tx that puts witness flag to 1 always
2041+
# Serialization of tx that puts witness flag to 3 always
20422042
def serialize_with_bogus_witness(tx):
2043-
flags = 1
2043+
flags = 3
20442044
r = b""
20452045
r += struct.pack("<i", tx.nVersion)
20462046
if flags:
@@ -2059,9 +2059,29 @@ def serialize_with_bogus_witness(tx):
20592059
r += struct.pack("<I", tx.nLockTime)
20602060
return r
20612061

2062-
raw = self.nodes[0].createrawtransaction([{"txid":"00"*32, "vout":0}], {self.nodes[0].getnewaddress():1})
2062+
class msg_bogus_tx(msg_tx):
2063+
def serialize(self):
2064+
return serialize_with_bogus_witness(self.tx)
2065+
2066+
self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(address_type='bech32'), 5)
2067+
self.nodes[0].generate(1)
2068+
unspent = next(u for u in self.nodes[0].listunspent() if u['spendable'] and u['address'].startswith('bcrt'))
2069+
2070+
raw = self.nodes[0].createrawtransaction([{"txid": unspent['txid'], "vout": unspent['vout']}], {self.nodes[0].getnewaddress(): 1})
20632071
tx = FromHex(CTransaction(), raw)
20642072
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, serialize_with_bogus_witness(tx).hex())
2073+
with self.nodes[0].assert_debug_log(['Superfluous witness record']):
2074+
self.nodes[0].p2p.send_message(msg_bogus_tx(tx))
2075+
self.nodes[0].p2p.sync_with_ping()
2076+
raw = self.nodes[0].signrawtransactionwithwallet(raw)
2077+
assert raw['complete']
2078+
raw = raw['hex']
2079+
tx = FromHex(CTransaction(), raw)
2080+
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, serialize_with_bogus_witness(tx).hex())
2081+
with self.nodes[0].assert_debug_log(['Unknown transaction optional data']):
2082+
self.nodes[0].p2p.send_message(msg_bogus_tx(tx))
2083+
self.nodes[0].p2p.sync_with_ping()
2084+
20652085

20662086
if __name__ == '__main__':
20672087
SegWitTest().main()

0 commit comments

Comments
 (0)