def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock): sequence_value = 1 if not use_height_lock: sequence_value |= SEQUENCE_LOCKTIME_TYPE_FLAG tx = CTransaction() tx.nVersion = 2 tx.vin = [ CTxIn(COutPoint(orig_tx.sha256, 0), nSequence=sequence_value) ] tx.vout = [ CTxOut(int(orig_tx.vout[0].nValue - relayfee * COIN), CScript([b'a'])) ] bloat_tx(tx) tx.calc_sha256() try: node.sendrawtransaction(ToHex(tx)) except JSONRPCException as exp: assert_equal(exp.error["message"], NOT_FINAL_ERROR) assert (orig_tx.hash in node.getrawmempool()) else: # orig_tx must not be in mempool assert (orig_tx.hash not in node.getrawmempool()) return tx
def create_transaction(prevtx, n, sig, value, scriptPubKey=CScript()): tx = CTransaction() assert (n < len(prevtx.vout)) tx.vin.append(CTxIn(COutPoint(prevtx.sha256, n), sig, 0xffffffff)) tx.vout.append(CTxOut(value, scriptPubKey)) tx.calc_sha256() # make sure tx is at least MIN_TX_SIZE bloat_tx(tx) return tx
def test_bip68_not_consensus(self): txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2) tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid)) tx1.rehash() # Make an anyone-can-spend transaction tx2 = CTransaction() tx2.nVersion = 1 tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)] tx2.vout = [ CTxOut(int(tx1.vout[0].nValue - self.relayfee * COIN), CScript([b'a'])) ] # sign tx2 tx2_raw = self.nodes[0].signrawtransaction(ToHex(tx2))["hex"] tx2 = FromHex(tx2, tx2_raw) tx2.rehash() self.nodes[0].sendrawtransaction(ToHex(tx2)) # Now make an invalid spend of tx2 according to BIP68 sequence_value = 100 # 100 block relative locktime tx3 = CTransaction() tx3.nVersion = 2 tx3.vin = [CTxIn(COutPoint(tx2.sha256, 0), nSequence=sequence_value)] tx3.vout = [ CTxOut(int(tx2.vout[0].nValue - self.relayfee * COIN), CScript([b'a'])) ] bloat_tx(tx3) tx3.calc_sha256() try: self.nodes[0].sendrawtransaction(ToHex(tx3)) except JSONRPCException as exp: assert_equal(exp.error["message"], NOT_FINAL_ERROR) else: assert (False) # make a block that violates bip68; ensure that the tip updates tip = int(self.nodes[0].getbestblockhash(), 16) block = create_block( tip, create_coinbase(absoluteHeight=self.nodes[0].getblockcount() + 1)) block.nVersion = 4 block.vtx.extend([tx1, tx2, tx3]) ltor_sort_block(block) block.hashMerkleRoot = block.calc_merkle_root() block.rehash() block.solve() self.nodes[0].submitblock(ToHex(block)) assert_equal(self.nodes[0].getbestblockhash(), block.hash)
def get_base_transaction(): # Create the new transaction tx = CTransaction() # Spend from one of the spendable outputs spend = spendable_outputs.popleft() tx.vin.append(CTxIn(COutPoint(spend.tx.sha256, spend.n))) # Add spendable outputs for i in range(4): tx.vout.append(CTxOut(0, CScript([OP_TRUE]))) spendable_outputs.append(PreviousSpendableOutput(tx, i)) bloat_tx(tx) return tx
def test_disable_flag(self): # Create some unconfirmed inputs new_addr = self.nodes[0].getnewaddress() self.nodes[0].sendtoaddress(new_addr, 2) # send 2 BTC utxos = self.nodes[0].listunspent(0, 0) assert (len(utxos) > 0) utxo = utxos[0] tx1 = CTransaction() value = int(satoshi_round(utxo["amount"] - self.relayfee) * COIN) # Check that the disable flag disables relative locktime. # If sequence locks were used, this would require 1 block for the # input to mature. sequence_value = SEQUENCE_LOCKTIME_DISABLE_FLAG | 1 tx1.vin = [ CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), nSequence=sequence_value) ] tx1.vout = [CTxOut(value, CScript([b'a']))] tx1_signed = self.nodes[0].signrawtransaction(ToHex(tx1))["hex"] tx1_id = self.nodes[0].sendrawtransaction(tx1_signed) tx1_id = int(tx1_id, 16) # This transaction will enable sequence-locks, so this transaction should # fail tx2 = CTransaction() tx2.nVersion = 2 sequence_value = sequence_value & 0x7fffffff tx2.vin = [CTxIn(COutPoint(tx1_id, 0), nSequence=sequence_value)] tx2.vout = [CTxOut(int(value - self.relayfee * COIN), CScript([b'a']))] bloat_tx(tx2) tx2.rehash() try: self.nodes[0].sendrawtransaction(ToHex(tx2)) except JSONRPCException as exp: assert_equal(exp.error["message"], NOT_FINAL_ERROR) else: assert (False) # Setting the version back down to 1 should disable the sequence lock, # so this should be accepted. tx2.nVersion = 1 self.nodes[0].sendrawtransaction(ToHex(tx2))
def build_block_with_transactions(self, node, utxo, num_transactions): block = self.build_block_on_tip(node) for i in range(num_transactions): tx = CTransaction() tx.vin.append(CTxIn(COutPoint(utxo[0], utxo[1]), b'')) tx.vout.append(CTxOut(utxo[2] - 1000, CScript([OP_TRUE]))) bloat_tx(tx) tx.calc_sha256() utxo = [tx.sha256, 0, tx.vout[0].nValue] block.vtx.append(tx) ltor_sort_block(block) block.hashMerkleRoot = block.calc_merkle_root() block.solve() return block
def create_coinbase(heightAdjust=0, absoluteHeight=None, pubkey=None): global counter height = absoluteHeight if absoluteHeight is not None else counter + heightAdjust coinbase = CTransaction() coinbase.vin.append( CTxIn(COutPoint(0, 0xffffffff), ser_string(serialize_script_num(height)), 0xffffffff)) counter += 1 coinbaseoutput = CTxOut() coinbaseoutput.nValue = 50 * COIN halvings = int(height / 150) # regtest coinbaseoutput.nValue >>= halvings if (pubkey != None): coinbaseoutput.scriptPubKey = CScript([pubkey, OP_CHECKSIG]) else: coinbaseoutput.scriptPubKey = CScript([OP_TRUE]) coinbase.vout = [coinbaseoutput] # make sure tx is at least MIN_TX_SIZE bloat_tx(coinbase) coinbase.calc_sha256() return coinbase