Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
252def createrawtransaction_tests(self):253self.log.info("Test createrawtransaction")254# Test `createrawtransaction` required parameters255assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction)256assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction, [])258# Test `createrawtransaction` invalid extra parameters259assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction, [], {}, 0, False, 2, 3, 'foo')261# Test `createrawtransaction` invalid version parameters262assert_raises_rpc_error(-8, f"Invalid parameter, version out of range({TX_MIN_STANDARD_VERSION}~{TX_MAX_STANDARD_VERSION})", self.nodes[0].createrawtransaction, [], {}, 0, False, TX_MIN_STANDARD_VERSION - 1)263assert_raises_rpc_error(-8, f"Invalid parameter, version out of range({TX_MIN_STANDARD_VERSION}~{TX_MAX_STANDARD_VERSION})", self.nodes[0].createrawtransaction, [], {}, 0, False, TX_MAX_STANDARD_VERSION + 1)265# Test `createrawtransaction` invalid `inputs`266assert_raises_rpc_error(-3, "JSON value of type string is not of expected type array", self.nodes[0].createrawtransaction, 'foo', {})267assert_raises_rpc_error(-3, "JSON value of type string is not of expected type object", self.nodes[0].createrawtransaction, ['foo'], {})268assert_raises_rpc_error(-3, "JSON value of type null is not of expected type string", self.nodes[0].createrawtransaction, [{}], {})269assert_raises_rpc_error(-8, "txid must be of length 64 (not 3, for 'foo')", self.nodes[0].createrawtransaction, [{'txid': 'foo'}], {})270txid = "ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844"271assert_raises_rpc_error(-8, f"txid must be hexadecimal string (not '{txid}')", self.nodes[0].createrawtransaction, [{'txid': txid}], {})272assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, [{'txid': TXID}], {})273assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, [{'txid': TXID, 'vout': 'foo'}], {})274assert_raises_rpc_error(-8, "Invalid parameter, vout cannot be negative", self.nodes[0].createrawtransaction, [{'txid': TXID, 'vout': -1}], {})275# sequence number out of range276for invalid_seq in [-1, 4294967296]:277inputs = [{'txid': TXID, 'vout': 1, 'sequence': invalid_seq}]278address = getnewdestination()[2]279outputs = {address: 1}280assert_raises_rpc_error(-8, 'Invalid parameter, sequence number is out of range',281self.nodes[0].createrawtransaction, inputs, outputs)282# with valid sequence number283for valid_seq in [1000, 4294967294]:284inputs = [{'txid': TXID, 'vout': 1, 'sequence': valid_seq}]285address = getnewdestination()[2]286outputs = {address: 1}287rawtx = self.nodes[0].createrawtransaction(inputs, outputs)288decrawtx = self.nodes[0].decoderawtransaction(rawtx)289assert_equal(decrawtx['vin'][0]['sequence'], valid_seq)291# Test `createrawtransaction` invalid `outputs`292address = getnewdestination()[2]293assert_raises_rpc_error(-3, "JSON value of type string is not of expected type array", self.nodes[0].createrawtransaction, [], 'foo')294self.nodes[0].createrawtransaction(inputs=[], outputs={}) # Should not throw for backwards compatibility295self.nodes[0].createrawtransaction(inputs=[], outputs=[])296assert_raises_rpc_error(-8, "Data must be hexadecimal string", self.nodes[0].createrawtransaction, [], {'data': 'foo'})297assert_raises_rpc_error(-5, "Invalid Bitcoin address", self.nodes[0].createrawtransaction, [], {'foo': 0})298assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].createrawtransaction, [], {address: 'foo'})299assert_raises_rpc_error(-3, "Amount out of range", self.nodes[0].createrawtransaction, [], {address: -1})300assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % address, self.nodes[0].createrawtransaction, [], multidict([(address, 1), (address, 1)]))301assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % address, self.nodes[0].createrawtransaction, [], [{address: 1}, {address: 1}])302assert_raises_rpc_error(-8, "Invalid parameter, duplicate key: data", self.nodes[0].createrawtransaction, [], [{"data": 'aa'}, {"data": "bb"}])303assert_raises_rpc_error(-8, "Invalid parameter, duplicate key: data", self.nodes[0].createrawtransaction, [], multidict([("data", 'aa'), ("data", "bb")]))304assert_raises_rpc_error(-8, "Invalid parameter, key-value pair must contain exactly one key", self.nodes[0].createrawtransaction, [], [{'a': 1, 'b': 2}])305assert_raises_rpc_error(-8, "Invalid parameter, key-value pair not an object as expected", self.nodes[0].createrawtransaction, [], [['key-value pair1'], ['2']])307# Test `createrawtransaction` mismatch between sequence number(s) and `replaceable` option308assert_raises_rpc_error(-8, "Invalid parameter combination: Sequence number(s) contradict replaceable option",309self.nodes[0].createrawtransaction, [{'txid': TXID, 'vout': 0, 'sequence': MAX_BIP125_RBF_SEQUENCE+1}], {}, 0, True)311# Test `createrawtransaction` invalid `locktime`312assert_raises_rpc_error(-3, "JSON value of type string is not of expected type number", self.nodes[0].createrawtransaction, [], {}, 'foo')313assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range", self.nodes[0].createrawtransaction, [], {}, -1)314assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range", self.nodes[0].createrawtransaction, [], {}, 4294967296)316# Test `createrawtransaction` invalid `replaceable`317assert_raises_rpc_error(-3, "JSON value of type string is not of expected type bool", self.nodes[0].createrawtransaction, [], {}, 0, 'foo')319# Test that createrawtransaction accepts an array and object as outputs320# One output321tx = tx_from_hex(self.nodes[2].createrawtransaction(inputs=[{'txid': TXID, 'vout': 9}], outputs={address: 99}))322assert_equal(len(tx.vout), 1)323assert_equal(324tx.serialize().hex(),325self.nodes[2].createrawtransaction(inputs=[{'txid': TXID, 'vout': 9}], outputs=[{address: 99}]),326)327# Two outputs328address2 = getnewdestination()[2]329tx = tx_from_hex(self.nodes[2].createrawtransaction(inputs=[{'txid': TXID, 'vout': 9}], outputs=OrderedDict([(address, 99), (address2, 99)])))330assert_equal(len(tx.vout), 2)331assert_equal(332tx.serialize().hex(),333self.nodes[2].createrawtransaction(inputs=[{'txid': TXID, 'vout': 9}], outputs=[{address: 99}, {address2: 99}]),334)335# Multiple mixed outputs336tx = tx_from_hex(self.nodes[2].createrawtransaction(inputs=[{'txid': TXID, 'vout': 9}], outputs=multidict([(address, 99), (address2, 99), ('data', '99')])))337assert_equal(len(tx.vout), 3)338assert_equal(339tx.serialize().hex(),340self.nodes[2].createrawtransaction(inputs=[{'txid': TXID, 'vout': 9}], outputs=[{address: 99}, {address2: 99}, {'data': '99'}]),341)343for version in range(TX_MIN_STANDARD_VERSION, TX_MAX_STANDARD_VERSION + 1):344rawtx = self.nodes[2].createrawtransaction(inputs=[{'txid': TXID, 'vout': 9}], outputs=OrderedDict([(address, 99), (address2, 99)]), version=version)345tx = tx_from_hex(rawtx)346assert_equal(tx.version, version)348def sendrawtransaction_tests(self):349self.log.info("Test sendrawtransaction with missing input")350inputs = [{'txid': TXID, 'vout': 1}] # won't exist351address = getnewdestination()[2]352outputs = {address: 4.998}353rawtx = self.nodes[2].createrawtransaction(inputs, outputs)354assert_raises_rpc_error(-25, "bad-txns-inputs-missingorspent", self.nodes[2].sendrawtransaction, rawtx)356self.log.info("Test sendrawtransaction exceeding, falling short of, and equaling maxburnamount")357max_burn_exceeded = "Unspendable output exceeds maximum configured by user (maxburnamount)"360# Test that spendable transaction with default maxburnamount (0) gets sent361tx = self.wallet.create_self_transfer()['tx']362tx_hex = tx.serialize().hex()363self.nodes[2].sendrawtransaction(hexstring=tx_hex)365# Test that datacarrier transaction with default maxburnamount (0) does not get sent366tx = self.wallet.create_self_transfer()['tx']367tx_val = 0.001368tx.vout = [CTxOut(int(Decimal(tx_val) * COIN), CScript([OP_RETURN] + [OP_FALSE] * 30))]369tx_hex = tx.serialize().hex()370assert_raises_rpc_error(-25, max_burn_exceeded, self.nodes[2].sendrawtransaction, tx_hex)372# Test that oversized script gets rejected by sendrawtransaction373tx = self.wallet.create_self_transfer()['tx']374tx_val = 0.001375tx.vout = [CTxOut(int(Decimal(tx_val) * COIN), CScript([OP_FALSE] * 10001))]376tx_hex = tx.serialize().hex()377assert_raises_rpc_error(-25, max_burn_exceeded, self.nodes[2].sendrawtransaction, tx_hex)379# Test that script containing invalid opcode gets rejected by sendrawtransaction380tx = self.wallet.create_self_transfer()['tx']381tx_val = 0.01382tx.vout = [CTxOut(int(Decimal(tx_val) * COIN), CScript([OP_INVALIDOPCODE]))]383tx_hex = tx.serialize().hex()384assert_raises_rpc_error(-25, max_burn_exceeded, self.nodes[2].sendrawtransaction, tx_hex)386# Test a transaction where our burn exceeds maxburnamount387tx = self.wallet.create_self_transfer()['tx']388tx_val = 0.001389tx.vout = [CTxOut(int(Decimal(tx_val) * COIN), CScript([OP_RETURN] + [OP_FALSE] * 30))]390tx_hex = tx.serialize().hex()391assert_raises_rpc_error(-25, max_burn_exceeded, self.nodes[2].sendrawtransaction, tx_hex, 0, 0.0009)393# Test a transaction where our burn falls short of maxburnamount394tx = self.wallet.create_self_transfer()['tx']395tx_val = 0.001396tx.vout = [CTxOut(int(Decimal(tx_val) * COIN), CScript([OP_RETURN] + [OP_FALSE] * 30))]397tx_hex = tx.serialize().hex()398self.nodes[2].sendrawtransaction(hexstring=tx_hex, maxfeerate='0', maxburnamount='0.0011')400# Test a transaction where our burn equals maxburnamount401tx = self.wallet.create_self_transfer()['tx']402tx_val = 0.001403tx.vout = [CTxOut(int(Decimal(tx_val) * COIN), CScript([OP_RETURN] + [OP_FALSE] * 30))]404tx_hex = tx.serialize().hex()405self.nodes[2].sendrawtransaction(hexstring=tx_hex, maxfeerate='0', maxburnamount='0.001')407def sendrawtransaction_testmempoolaccept_tests(self):408self.log.info("Test sendrawtransaction/testmempoolaccept with maxfeerate")409fee_exceeds_max = "Fee exceeds maximum configured by user (e.g. -maxtxfee, maxfeerate)"411# Test a transaction with a small fee.412# Fee rate is 0.00100000 BTC/kvB413tx = self.wallet.create_self_transfer(fee_rate=Decimal('0.00100000'))414# Thus, testmempoolaccept should reject415testres = self.nodes[2].testmempoolaccept([tx['hex']], 0.00001000)[0]416assert_equal(testres['allowed'], False)417assert_equal(testres['reject-reason'], 'max-fee-exceeded')418# and sendrawtransaction should throw419assert_raises_rpc_error(-25, fee_exceeds_max, self.nodes[2].sendrawtransaction, tx['hex'], 0.00001000)420# and the following calls should both succeed421testres = self.nodes[2].testmempoolaccept(rawtxs=[tx['hex']])[0]422assert_equal(testres['allowed'], True)423self.nodes[2].sendrawtransaction(hexstring=tx['hex'])425# Test a transaction with a large fee.426# Fee rate is 0.20000000 BTC/kvB427tx = self.wallet.create_self_transfer(fee_rate=Decimal("0.20000000"))428# Thus, testmempoolaccept should reject429testres = self.nodes[2].testmempoolaccept([tx['hex']])[0]430assert_equal(testres['allowed'], False)431assert_equal(testres['reject-reason'], 'max-fee-exceeded')432# and sendrawtransaction should throw433assert_raises_rpc_error(-25, fee_exceeds_max, self.nodes[2].sendrawtransaction, tx['hex'])434# and the following calls should both succeed435testres = self.nodes[2].testmempoolaccept(rawtxs=[tx['hex']], maxfeerate='0.20000000')[0]436assert_equal(testres['allowed'], True)437self.nodes[2].sendrawtransaction(hexstring=tx['hex'], maxfeerate='0.20000000')439self.log.info("Test sendrawtransaction/testmempoolaccept with tx outputs already in the utxo set")440self.generate(self.nodes[2], 1)441for node in self.nodes:442testres = node.testmempoolaccept([tx['hex']])[0]443assert_equal(testres['allowed'], False)444assert_equal(testres['reject-reason'], 'txn-already-known')445assert_raises_rpc_error(-27, 'Transaction outputs already in utxo set', node.sendrawtransaction, tx['hex'])447def decoderawtransaction_tests(self):448self.log.info("Test decoderawtransaction")449# witness transaction450encrawtx = "010000000001010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f50500000000000102616100000000"451decrawtx = self.nodes[0].decoderawtransaction(encrawtx, True) # decode as witness transaction452assert_equal(decrawtx['vout'][0]['value'], Decimal('1.00000000'))453assert_raises_rpc_error(-22, 'TX decode failed', self.nodes[0].decoderawtransaction, encrawtx, False) # force decode as non-witness transaction454# non-witness transaction455encrawtx = "01000000010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f505000000000000000000"456decrawtx = self.nodes[0].decoderawtransaction(encrawtx, False) # decode as non-witness transaction457assert_equal(decrawtx['vout'][0]['value'], Decimal('1.00000000'))458# known ambiguous transaction in the chain (see https://github.com/bitcoin/bitcoin/issues/20579)459coinbase = "03c68708046ff8415c622f4254432e434f4d2ffabe6d6de1965d02c68f928e5b244ab1965115a36f56eb997633c7f690124bbf43644e23080000000ca3d3af6d005a65ff0200fd00000000"460encrawtx = f"020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff4b{coinbase}" \461"ffffffff03f4c1fb4b0000000016001497cfc76442fe717f2a3f0cc9c175f7561b6619970000000000000000266a24aa21a9ed957d1036a80343e0d1b659497e1b48a38ebe876a056d45965fac4a85cda84e1900000000000000002952534b424c4f434b3a8e092581ab01986cbadc84f4b43f4fa4bb9e7a2e2a0caf9b7cf64d939028e22c0120000000000000000000000000000000000000000000000000000000000000000000000000"462decrawtx = self.nodes[0].decoderawtransaction(encrawtx)463decrawtx_wit = self.nodes[0].decoderawtransaction(encrawtx, True)464assert_raises_rpc_error(-22, 'TX decode failed', self.nodes[0].decoderawtransaction, encrawtx, False) # fails to decode as non-witness transaction465assert_equal(decrawtx, decrawtx_wit) # the witness interpretation should be chosen466assert_equal(decrawtx['vin'][0]['coinbase'], coinbase)468def transaction_version_number_tests(self):469self.log.info("Test transaction version numbers")471# Test the minimum transaction version number that fits in a signed 32-bit integer.472# As transaction version is serialized unsigned, this should convert to its unsigned equivalent.473tx = CTransaction()474tx.version = 0x80000000475rawtx = tx.serialize().hex()476decrawtx = self.nodes[0].decoderawtransaction(rawtx)477assert_equal(decrawtx['version'], 0x80000000)479# Test the maximum transaction version number that fits in a signed 32-bit integer.480tx = CTransaction()481tx.version = 0x7fffffff482rawtx = tx.serialize().hex()483decrawtx = self.nodes[0].decoderawtransaction(rawtx)484assert_equal(decrawtx['version'], 0x7fffffff)486# Test the minimum transaction version number that fits in an unsigned 32-bit integer.487tx = CTransaction()488tx.version = 0489rawtx = tx.serialize().hex()490decrawtx = self.nodes[0].decoderawtransaction(rawtx)491assert_equal(decrawtx['version'], 0)493# Test the maximum transaction version number that fits in an unsigned 32-bit integer.494tx = CTransaction()495tx.version = 0xffffffff496rawtx = tx.serialize().hex()497decrawtx = self.nodes[0].decoderawtransaction(rawtx)498assert_equal(decrawtx['version'], 0xffffffff)500if __name__ == '__main__':
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.