Disallow extended encoding for non-witness transactions (take 3)
This commit is contained in:
parent
e79bbb73e0
commit
fa2b52af32
2 changed files with 33 additions and 14 deletions
|
@ -3288,23 +3288,22 @@ bool PeerLogicValidation::ProcessMessages(CNode* pfrom, std::atomic<bool>& inter
|
||||||
if (m_enable_bip61) {
|
if (m_enable_bip61) {
|
||||||
connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, std::string("error parsing message")));
|
connman->PushMessage(pfrom, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, std::string("error parsing message")));
|
||||||
}
|
}
|
||||||
if (strstr(e.what(), "end of data"))
|
if (strstr(e.what(), "end of data")) {
|
||||||
{
|
|
||||||
// Allow exceptions from under-length message on vRecv
|
// Allow exceptions from under-length message on vRecv
|
||||||
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());
|
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());
|
||||||
}
|
} else if (strstr(e.what(), "size too large")) {
|
||||||
else if (strstr(e.what(), "size too large"))
|
|
||||||
{
|
|
||||||
// Allow exceptions from over-long size
|
// Allow exceptions from over-long size
|
||||||
LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what());
|
LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what());
|
||||||
}
|
} else if (strstr(e.what(), "non-canonical ReadCompactSize()")) {
|
||||||
else if (strstr(e.what(), "non-canonical ReadCompactSize()"))
|
|
||||||
{
|
|
||||||
// Allow exceptions from non-canonical encoding
|
// Allow exceptions from non-canonical encoding
|
||||||
LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what());
|
LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what());
|
||||||
}
|
} else if (strstr(e.what(), "Superfluous witness record")) {
|
||||||
else
|
// Allow exceptions from illegal witness encoding
|
||||||
{
|
LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what());
|
||||||
|
} else if (strstr(e.what(), "Unknown transaction optional data")) {
|
||||||
|
// Allow exceptions from unknown witness encoding
|
||||||
|
LogPrint(BCLog::NET, "%s(%s, %u bytes): Exception '%s' caught\n", __func__, SanitizeString(strCommand), nMessageSize, e.what());
|
||||||
|
} else {
|
||||||
PrintExceptionContinue(&e, "ProcessMessages()");
|
PrintExceptionContinue(&e, "ProcessMessages()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2038,9 +2038,9 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
# TODO: test p2sh sigop counting
|
# TODO: test p2sh sigop counting
|
||||||
|
|
||||||
def test_superfluous_witness(self):
|
def test_superfluous_witness(self):
|
||||||
# Serialization of tx that puts witness flag to 1 always
|
# Serialization of tx that puts witness flag to 3 always
|
||||||
def serialize_with_bogus_witness(tx):
|
def serialize_with_bogus_witness(tx):
|
||||||
flags = 1
|
flags = 3
|
||||||
r = b""
|
r = b""
|
||||||
r += struct.pack("<i", tx.nVersion)
|
r += struct.pack("<i", tx.nVersion)
|
||||||
if flags:
|
if flags:
|
||||||
|
@ -2059,9 +2059,29 @@ class SegWitTest(BitcoinTestFramework):
|
||||||
r += struct.pack("<I", tx.nLockTime)
|
r += struct.pack("<I", tx.nLockTime)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
raw = self.nodes[0].createrawtransaction([{"txid":"00"*32, "vout":0}], {self.nodes[0].getnewaddress():1})
|
class msg_bogus_tx(msg_tx):
|
||||||
|
def serialize(self):
|
||||||
|
return serialize_with_bogus_witness(self.tx)
|
||||||
|
|
||||||
|
self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(address_type='bech32'), 5)
|
||||||
|
self.nodes[0].generate(1)
|
||||||
|
unspent = next(u for u in self.nodes[0].listunspent() if u['spendable'] and u['address'].startswith('bcrt'))
|
||||||
|
|
||||||
|
raw = self.nodes[0].createrawtransaction([{"txid": unspent['txid'], "vout": unspent['vout']}], {self.nodes[0].getnewaddress(): 1})
|
||||||
tx = FromHex(CTransaction(), raw)
|
tx = FromHex(CTransaction(), raw)
|
||||||
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, serialize_with_bogus_witness(tx).hex())
|
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, serialize_with_bogus_witness(tx).hex())
|
||||||
|
with self.nodes[0].assert_debug_log(['Superfluous witness record']):
|
||||||
|
self.nodes[0].p2p.send_message(msg_bogus_tx(tx))
|
||||||
|
self.nodes[0].p2p.sync_with_ping()
|
||||||
|
raw = self.nodes[0].signrawtransactionwithwallet(raw)
|
||||||
|
assert raw['complete']
|
||||||
|
raw = raw['hex']
|
||||||
|
tx = FromHex(CTransaction(), raw)
|
||||||
|
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].decoderawtransaction, serialize_with_bogus_witness(tx).hex())
|
||||||
|
with self.nodes[0].assert_debug_log(['Unknown transaction optional data']):
|
||||||
|
self.nodes[0].p2p.send_message(msg_bogus_tx(tx))
|
||||||
|
self.nodes[0].p2p.sync_with_ping()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
SegWitTest().main()
|
SegWitTest().main()
|
||||||
|
|
Loading…
Add table
Reference in a new issue