diff options
Diffstat (limited to 'qa')
-rwxr-xr-x | qa/rpc-tests/p2p-segwit.py | 102 | ||||
-rwxr-xr-x | qa/rpc-tests/sendheaders.py | 105 | ||||
-rw-r--r-- | qa/rpc-tests/test_framework/blocktools.py | 2 | ||||
-rwxr-xr-x | qa/rpc-tests/test_framework/mininode.py | 6 |
4 files changed, 184 insertions, 31 deletions
diff --git a/qa/rpc-tests/p2p-segwit.py b/qa/rpc-tests/p2p-segwit.py index cf78954f28..b30d41af92 100755 --- a/qa/rpc-tests/p2p-segwit.py +++ b/qa/rpc-tests/p2p-segwit.py @@ -43,6 +43,7 @@ class TestNode(NodeConnCB): self.last_pong = msg_pong(0) self.sleep_time = 0.05 self.getdataset = set() + self.last_reject = None def add_connection(self, conn): self.connection = conn @@ -68,7 +69,7 @@ class TestNode(NodeConnCB): def on_reject(self, conn, message): self.last_reject = message - #print message + #print (message) # Syncing helpers def sync(self, test_function, timeout=60): @@ -136,13 +137,17 @@ class TestNode(NodeConnCB): self.wait_for_block(blockhash, timeout) return self.last_block - def test_transaction_acceptance(self, tx, with_witness, accepted): + def test_transaction_acceptance(self, tx, with_witness, accepted, reason=None): tx_message = msg_tx(tx) if with_witness: tx_message = msg_witness_tx(tx) self.send_message(tx_message) self.sync_with_ping() assert_equal(tx.hash in self.connection.rpc.getrawmempool(), accepted) + if (reason != None and not accepted): + # Check the rejection reason as well. + with mininode_lock: + assert_equal(self.last_reject.reason, reason) # Test whether a witness block had the correct effect on the tip def test_witness_block(self, block, accepted, with_witness=True): @@ -252,7 +257,7 @@ class SegWitTest(BitcoinTestFramework): tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) tx.vout.append(CTxOut(self.utxo[0].nValue-1000, CScript([OP_TRUE]))) - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)])] # Verify the hash with witness differs from the txid @@ -277,9 +282,52 @@ class SegWitTest(BitcoinTestFramework): self.test_node.sync_with_ping() assert_equal(self.nodes[0].getbestblockhash(), block.hash) + sync_blocks(self.nodes) + + # Create a p2sh output -- this is so we can pass the standardness + # rules (an anyone-can-spend OP_TRUE would be rejected, if not wrapped + # in P2SH). + p2sh_program = CScript([OP_TRUE]) + p2sh_pubkey = hash160(p2sh_program) + scriptPubKey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL]) + + # Now check that unnecessary witnesses can't be used to blind a node + # to a transaction, eg by violating standardness checks. + tx2 = CTransaction() + tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) + tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, scriptPubKey)) + tx2.rehash() + self.test_node.test_transaction_acceptance(tx2, False, True) + self.nodes[0].generate(1) + sync_blocks(self.nodes) + + # We'll add an unnecessary witness to this transaction that would cause + # it to be too large according to IsStandard. + tx3 = CTransaction() + tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), CScript([p2sh_program]))) + tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, scriptPubKey)) + tx3.wit.vtxinwit.append(CTxInWitness()) + tx3.wit.vtxinwit[0].scriptWitness.stack = [b'a'*400000] + tx3.rehash() + self.std_node.test_transaction_acceptance(tx3, True, False, b'no-witness-yet') + + # If we send without witness, it should be accepted. + self.std_node.test_transaction_acceptance(tx3, False, True) + + # Now create a new anyone-can-spend utxo for the next test. + tx4 = CTransaction() + tx4.vin.append(CTxIn(COutPoint(tx3.sha256, 0), CScript([p2sh_program]))) + tx4.vout.append(CTxOut(tx3.vout[0].nValue-1000, CScript([OP_TRUE]))) + tx4.rehash() + self.test_node.test_transaction_acceptance(tx3, False, True) + self.test_node.test_transaction_acceptance(tx4, False, True) + + self.nodes[0].generate(1) + sync_blocks(self.nodes) + # Update our utxo list; we spent the first entry. self.utxo.pop(0) - self.utxo.append(UTXO(tx.sha256, 0, tx.vout[0].nValue)) + self.utxo.append(UTXO(tx4.sha256, 0, tx4.vout[0].nValue)) # Mine enough blocks for segwit's vb state to be 'started'. @@ -362,7 +410,7 @@ class SegWitTest(BitcoinTestFramework): tx2 = CTransaction() tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, witness_program)) - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[0].scriptWitness.stack = [witness_program] tx2.rehash() @@ -489,7 +537,7 @@ class SegWitTest(BitcoinTestFramework): child_tx.vin.append(CTxIn(COutPoint(parent_tx.sha256, i), b"")) child_tx.vout = [CTxOut(value - 100000, CScript([OP_TRUE]))] for i in range(NUM_OUTPUTS): - child_tx.wit.vtxinwit.append(CTxinWitness()) + child_tx.wit.vtxinwit.append(CTxInWitness()) child_tx.wit.vtxinwit[-1].scriptWitness.stack = [b'a'*195]*(2*NUM_DROPS) + [witness_program] child_tx.rehash() self.update_witness_block_with_transactions(block, [parent_tx, child_tx]) @@ -584,7 +632,7 @@ class SegWitTest(BitcoinTestFramework): tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) tx.vout.append(CTxOut(self.utxo[0].nValue-2000, scriptPubKey)) tx.vout.append(CTxOut(1000, CScript([OP_TRUE]))) # non-witness output - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([])] tx.rehash() self.update_witness_block_with_transactions(block, [tx]) @@ -607,7 +655,7 @@ class SegWitTest(BitcoinTestFramework): tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) # witness output tx2.vin.append(CTxIn(COutPoint(tx.sha256, 1), b"")) # non-witness tx2.vout.append(CTxOut(tx.vout[0].nValue, CScript([OP_TRUE]))) - tx2.wit.vtxinwit.extend([CTxinWitness(), CTxinWitness()]) + tx2.wit.vtxinwit.extend([CTxInWitness(), CTxInWitness()]) tx2.wit.vtxinwit[0].scriptWitness.stack = [ CScript([CScriptNum(1)]), CScript([CScriptNum(1)]), witness_program ] tx2.wit.vtxinwit[1].scriptWitness.stack = [ CScript([OP_TRUE]) ] @@ -663,7 +711,7 @@ class SegWitTest(BitcoinTestFramework): tx2 = CTransaction() tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE]))) - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) # First try a 521-byte stack element tx2.wit.vtxinwit[0].scriptWitness.stack = [ b'a'*(MAX_SCRIPT_ELEMENT_SIZE+1), witness_program ] tx2.rehash() @@ -705,7 +753,7 @@ class SegWitTest(BitcoinTestFramework): tx2 = CTransaction() tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE]))) - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a']*44 + [long_witness_program] tx2.rehash() @@ -782,7 +830,7 @@ class SegWitTest(BitcoinTestFramework): # First try using a too long vtxinwit for i in range(11): - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[i].scriptWitness.stack = [b'a', witness_program] block = self.build_next_block() @@ -798,7 +846,7 @@ class SegWitTest(BitcoinTestFramework): self.test_node.test_witness_block(block, accepted=False) # Now make one of the intermediate witnesses be incorrect - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[-1].scriptWitness.stack = [b'a', witness_program] tx2.wit.vtxinwit[5].scriptWitness.stack = [ witness_program ] @@ -825,7 +873,7 @@ class SegWitTest(BitcoinTestFramework): tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) tx.vout.append(CTxOut(self.utxo[0].nValue-1000, CScript([OP_TRUE]))) - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a' ] tx.rehash() @@ -885,7 +933,7 @@ class SegWitTest(BitcoinTestFramework): tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b"")) tx.vout.append(CTxOut(self.utxo[0].nValue-1000, CScript([OP_TRUE]))) - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a' ] tx.rehash() @@ -914,7 +962,7 @@ class SegWitTest(BitcoinTestFramework): tx3 = CTransaction() tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), b"")) tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, CScript([OP_TRUE]))) - tx3.wit.vtxinwit.append(CTxinWitness()) + tx3.wit.vtxinwit.append(CTxInWitness()) tx3.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)]), witness_program ] tx3.rehash() @@ -1087,7 +1135,7 @@ class SegWitTest(BitcoinTestFramework): tx2 = CTransaction() tx2.vin = [CTxIn(COutPoint(tx.sha256, 0), b"")] tx2.vout = [CTxOut(tx.vout[0].nValue-1000, scriptPubKey)] - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ] tx2.rehash() # Gets accepted to test_node, because standardness of outputs isn't @@ -1102,7 +1150,7 @@ class SegWitTest(BitcoinTestFramework): total_value = 0 for i in temp_utxo: tx3.vin.append(CTxIn(COutPoint(i.sha256, i.n), b"")) - tx3.wit.vtxinwit.append(CTxinWitness()) + tx3.wit.vtxinwit.append(CTxInWitness()) total_value += i.nValue tx3.wit.vtxinwit[-1].scriptWitness.stack = [witness_program] tx3.vout.append(CTxOut(total_value - 1000, CScript([OP_TRUE]))) @@ -1140,7 +1188,7 @@ class SegWitTest(BitcoinTestFramework): spend_tx = CTransaction() spend_tx.vin = [CTxIn(COutPoint(block.vtx[0].sha256, 0), b"")] spend_tx.vout = [CTxOut(block.vtx[0].vout[0].nValue, witness_program)] - spend_tx.wit.vtxinwit.append(CTxinWitness()) + spend_tx.wit.vtxinwit.append(CTxInWitness()) spend_tx.wit.vtxinwit[0].scriptWitness.stack = [ witness_program ] spend_tx.rehash() @@ -1200,7 +1248,7 @@ class SegWitTest(BitcoinTestFramework): tx = CTransaction() tx.vin.append(CTxIn(COutPoint(prev_utxo.sha256, prev_utxo.n), b"")) tx.vout.append(CTxOut(prev_utxo.nValue - 1000, scriptPubKey)) - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) # Too-large input value sign_P2PK_witness_input(witness_program, tx, 0, hashtype, prev_utxo.nValue+1, key) self.update_witness_block_with_transactions(block, [tx]) @@ -1233,7 +1281,7 @@ class SegWitTest(BitcoinTestFramework): split_value = prev_utxo.nValue // NUM_TESTS for i in range(NUM_TESTS): tx.vout.append(CTxOut(split_value, scriptPubKey)) - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) sign_P2PK_witness_input(witness_program, tx, 0, SIGHASH_ALL, prev_utxo.nValue, key) for i in range(NUM_TESTS): temp_utxos.append(UTXO(tx.sha256, i, split_value)) @@ -1255,7 +1303,7 @@ class SegWitTest(BitcoinTestFramework): total_value = 0 for i in range(num_inputs): tx.vin.append(CTxIn(COutPoint(temp_utxos[i].sha256, temp_utxos[i].n), b"")) - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) total_value += temp_utxos[i].nValue split_value = total_value // num_outputs for i in range(num_outputs): @@ -1295,7 +1343,7 @@ class SegWitTest(BitcoinTestFramework): tx = CTransaction() tx.vin.append(CTxIn(COutPoint(temp_utxos[0].sha256, temp_utxos[0].n), b"")) tx.vout.append(CTxOut(temp_utxos[0].nValue, scriptPKH)) - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) sign_P2PK_witness_input(witness_program, tx, 0, SIGHASH_ALL, temp_utxos[0].nValue, key) tx2 = CTransaction() tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b"")) @@ -1313,7 +1361,7 @@ class SegWitTest(BitcoinTestFramework): # Move the signature to the witness. block.vtx.pop() - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[0].scriptWitness.stack = [signature, pubkey] tx2.vin[0].scriptSig = b"" tx2.rehash() @@ -1333,7 +1381,7 @@ class SegWitTest(BitcoinTestFramework): # the signatures as we go. tx.vin.append(CTxIn(COutPoint(i.sha256, i.n), b"")) tx.vout.append(CTxOut(i.nValue, CScript([OP_TRUE]))) - tx.wit.vtxinwit.append(CTxinWitness()) + tx.wit.vtxinwit.append(CTxInWitness()) sign_P2PK_witness_input(witness_program, tx, index, SIGHASH_SINGLE|SIGHASH_ANYONECANPAY, i.nValue, key) index += 1 block = self.build_next_block() @@ -1393,7 +1441,7 @@ class SegWitTest(BitcoinTestFramework): # segwit activates. spend_tx.vin[0].scriptSig = scriptSig spend_tx.rehash() - spend_tx.wit.vtxinwit.append(CTxinWitness()) + spend_tx.wit.vtxinwit.append(CTxInWitness()) spend_tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a', witness_program ] # Verify mempool acceptance @@ -1499,7 +1547,7 @@ class SegWitTest(BitcoinTestFramework): total_value = 0 for i in range(outputs-1): tx2.vin.append(CTxIn(COutPoint(tx.sha256, i), b"")) - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program ] total_value += tx.vout[i].nValue tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program_toomany ] @@ -1540,7 +1588,7 @@ class SegWitTest(BitcoinTestFramework): block_5 = self.build_next_block() tx2.vout.pop() tx2.vin.append(CTxIn(COutPoint(tx.sha256, outputs-1), b"")) - tx2.wit.vtxinwit.append(CTxinWitness()) + tx2.wit.vtxinwit.append(CTxInWitness()) tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program_justright ] tx2.rehash() self.update_witness_block_with_transactions(block_5, [tx2]) diff --git a/qa/rpc-tests/sendheaders.py b/qa/rpc-tests/sendheaders.py index 6ab17d59b3..c3f3180b6b 100755 --- a/qa/rpc-tests/sendheaders.py +++ b/qa/rpc-tests/sendheaders.py @@ -63,6 +63,21 @@ e. Announce 16 more headers that build on that fork. Expect: getdata request for 14 more blocks. f. Announce 1 more header that builds on that fork. Expect: no response. + +Part 5: Test handling of headers that don't connect. +a. Repeat 10 times: + 1. Announce a header that doesn't connect. + Expect: getheaders message + 2. Send headers chain. + Expect: getdata for the missing blocks, tip update. +b. Then send 9 more headers that don't connect. + Expect: getheaders message each time. +c. Announce a header that does connect. + Expect: no response. +d. Announce 49 headers that don't connect. + Expect: getheaders message each time. +e. Announce one more that doesn't connect. + Expect: disconnect. ''' class BaseNode(NodeConnCB): @@ -77,6 +92,8 @@ class BaseNode(NodeConnCB): self.last_getdata = None self.sleep_time = 0.05 self.block_announced = False + self.last_getheaders = None + self.disconnected = False def clear_last_announcement(self): with mininode_lock: @@ -127,6 +144,12 @@ class BaseNode(NodeConnCB): def on_pong(self, conn, message): self.last_pong = message + def on_getheaders(self, conn, message): + self.last_getheaders = message + + def on_close(self, conn): + self.disconnected = True + # Test whether the last announcement we received had the # right header or the right inv # inv and headers should be lists of block hashes @@ -178,6 +201,11 @@ class BaseNode(NodeConnCB): self.sync(test_function, timeout) return + def wait_for_getheaders(self, timeout=60): + test_function = lambda: self.last_getheaders != None + self.sync(test_function, timeout) + return + def wait_for_getdata(self, hash_list, timeout=60): if hash_list == []: return @@ -186,6 +214,11 @@ class BaseNode(NodeConnCB): self.sync(test_function, timeout) return + def wait_for_disconnect(self, timeout=60): + test_function = lambda: self.disconnected + self.sync(test_function, timeout) + return + def send_header_for_blocks(self, new_blocks): headers_message = msg_headers() headers_message.headers = [ CBlockHeader(b) for b in new_blocks ] @@ -510,6 +543,78 @@ class SendHeadersTest(BitcoinTestFramework): print("Part 4: success!") + # Now deliver all those blocks we announced. + [ test_node.send_message(msg_block(x)) for x in blocks ] + + print("Part 5: Testing handling of unconnecting headers") + # First we test that receipt of an unconnecting header doesn't prevent + # chain sync. + for i in range(10): + test_node.last_getdata = None + blocks = [] + # Create two more blocks. + for j in range(2): + blocks.append(create_block(tip, create_coinbase(height), block_time)) + blocks[-1].solve() + tip = blocks[-1].sha256 + block_time += 1 + height += 1 + # Send the header of the second block -> this won't connect. + with mininode_lock: + test_node.last_getheaders = None + test_node.send_header_for_blocks([blocks[1]]) + test_node.wait_for_getheaders(timeout=1) + test_node.send_header_for_blocks(blocks) + test_node.wait_for_getdata([x.sha256 for x in blocks]) + [ test_node.send_message(msg_block(x)) for x in blocks ] + test_node.sync_with_ping() + assert_equal(int(self.nodes[0].getbestblockhash(), 16), blocks[1].sha256) + + blocks = [] + # Now we test that if we repeatedly don't send connecting headers, we + # don't go into an infinite loop trying to get them to connect. + MAX_UNCONNECTING_HEADERS = 10 + for j in range(MAX_UNCONNECTING_HEADERS+1): + blocks.append(create_block(tip, create_coinbase(height), block_time)) + blocks[-1].solve() + tip = blocks[-1].sha256 + block_time += 1 + height += 1 + + for i in range(1, MAX_UNCONNECTING_HEADERS): + # Send a header that doesn't connect, check that we get a getheaders. + with mininode_lock: + test_node.last_getheaders = None + test_node.send_header_for_blocks([blocks[i]]) + test_node.wait_for_getheaders(timeout=1) + + # Next header will connect, should re-set our count: + test_node.send_header_for_blocks([blocks[0]]) + + # Remove the first two entries (blocks[1] would connect): + blocks = blocks[2:] + + # Now try to see how many unconnecting headers we can send + # before we get disconnected. Should be 5*MAX_UNCONNECTING_HEADERS + for i in range(5*MAX_UNCONNECTING_HEADERS - 1): + # Send a header that doesn't connect, check that we get a getheaders. + with mininode_lock: + test_node.last_getheaders = None + test_node.send_header_for_blocks([blocks[i%len(blocks)]]) + test_node.wait_for_getheaders(timeout=1) + + # Eventually this stops working. + with mininode_lock: + self.last_getheaders = None + test_node.send_header_for_blocks([blocks[-1]]) + + # Should get disconnected + test_node.wait_for_disconnect() + with mininode_lock: + self.last_getheaders = True + + print("Part 5: success!") + # Finally, check that the inv node never received a getdata request, # throughout the test assert_equal(inv_node.last_getdata, None) diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py index df4fe13e5c..f69958823c 100644 --- a/qa/rpc-tests/test_framework/blocktools.py +++ b/qa/rpc-tests/test_framework/blocktools.py @@ -34,7 +34,7 @@ def add_witness_commitment(block, nonce=0): witness_root = block.calc_witness_merkle_root() witness_commitment = uint256_from_str(hash256(ser_uint256(witness_root)+ser_uint256(witness_nonce))) # witness_nonce should go to coinbase witness. - block.vtx[0].wit.vtxinwit = [CTxinWitness()] + block.vtx[0].wit.vtxinwit = [CTxInWitness()] block.vtx[0].wit.vtxinwit[0].scriptWitness.stack = [ser_uint256(witness_nonce)] # witness commitment is the last OP_RETURN output in coinbase diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py index 4548e2e7c0..cdd5292cd6 100755 --- a/qa/rpc-tests/test_framework/mininode.py +++ b/qa/rpc-tests/test_framework/mininode.py @@ -419,7 +419,7 @@ class CScriptWitness(object): return True -class CTxinWitness(object): +class CTxInWitness(object): def __init__(self): self.scriptWitness = CScriptWitness() @@ -497,7 +497,7 @@ class CTransaction(object): else: self.vout = deser_vector(f, CTxOut) if flags != 0: - self.wit.vtxinwit = [CTxinWitness()]*len(self.vin) + self.wit.vtxinwit = [CTxInWitness()]*len(self.vin) self.wit.deserialize(f) self.nLockTime = struct.unpack("<I", f.read(4))[0] self.sha256 = None @@ -529,7 +529,7 @@ class CTransaction(object): # vtxinwit must have the same length as vin self.wit.vtxinwit = self.wit.vtxinwit[:len(self.vin)] for i in range(len(self.wit.vtxinwit), len(self.vin)): - self.wit.vtxinwit.append(CTxinWitness()) + self.wit.vtxinwit.append(CTxInWitness()) r += self.wit.serialize() r += struct.pack("<I", self.nLockTime) return r |