def set_test_params(self): self.pubkeys = [ "025700236c2890233592fcef262f4520d22af9160e3d9705855140eb2aa06c35d3", "03831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc" ] privkeystr = [ "67ae3f5bfb3464b9704d7bd3a134401cc80c3a172240ebfca9f1e40f51bb6d37", "dbb9d19637018267268dfc2cc7aec07e7217c1a2d6733e1184a0909273bf078b" ] self.privkeys = [] for key in privkeystr: ckey = CECKey() ckey.set_secretbytes(bytes.fromhex(key)) self.privkeys.append(ckey) self.coinbase_key = CECKey() self.coinbase_key.set_secretbytes( bytes.fromhex( "12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747" )) self.coinbase_pubkey = self.coinbase_key.get_pubkey() self.schnorr_key = Schnorr() self.schnorr_key.set_secretbytes( bytes.fromhex( "12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747" )) self.num_nodes = 1 self.setup_clean_chain = True
def solve(self, signblockprivkey): # create signed blocks. sighash = self.getsighash() self.proof = "" #proof is based on Schnorr aggregate private key signKey = Schnorr() signKey.set_secretbytes(hex_str_to_bytes(signblockprivkey)) self.proof = bytearray(signKey.sign(sighash)) self.rehash()
def set_test_params(self): self.aggpubkeys = [ "025700236c2890233592fcef262f4520d22af9160e3d9705855140eb2aa06c35d3", "03831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc", "02bf2027c8455800c7626542219e6208b5fe787483689f1391d6d443ec85673ecf", "03b44f1cfcf46aba8bc98e2fd39f137cc43d98ab7792e4848b09c06198b042ca8b", "02b9a609d6bec0fdc9ba690986013cf7bbd13c54ffc25e6cf30916b4732c4a952a", "02e78cafe033b22bda5d7d1c8e82ee932930bf12e08489bc19769cbec765568be9", "02473757a955a23f75379820f3071abf5b3343b78eb54e52373d06259ffa6c550b" ] self.aggprivkey = [ "67ae3f5bfb3464b9704d7bd3a134401cc80c3a172240ebfca9f1e40f51bb6d37", "dbb9d19637018267268dfc2cc7aec07e7217c1a2d6733e1184a0909273bf078b", "aa2c70c4b85a09be514292d04b27bbb0cc3f86d306d58fe87743d10a095ada07", "3087d8decc5f951f19a442397cf1eba1e2b064e68650c346502780b56454c6e2", "6125c8d4330941944cc6cc3e775e8620c479a5901ad627e6e734c6a6f7377428", "1c3e5453c0f9aa74a8eb0216310b2b013f017813a648fce364bf41dbc0b37647", "ea9fe9fd2f1761fc6f1f0f23eb4d4141d7b05f2b95a1b7a9912cd97bddd9036c" ] self.aggprivkey_wif = [ "cR4F4fGuKjDWxiYDtGtyM77WkrVhTgokVyM2ERxoxp7R4RQP9dgE", "cUwpWhH9CbYwjUWzfz1UVaSjSQm9ALXWRqeFFiZKnn8cV6wqNXQA", "cTHVmjaAwKtU75t89fg42SLx43nRxhsri6YY1Eynvs1V1tPRCfae", "cPD3D5AvmXhw7NGxQeaRhTVNW2UoYeibQAMhye7jzyM4ETG9d1ez", "cQqYVqYhK47EWvDViNwcyhc6sLS6tkuhED7T3rvumeGRtVJcEQHh", "cNXbwddRQrPR4k7Us7eSrRUHFBerNBKwxrExTSs4gdH1rjHdoNuL", "cVSnGe9DzWfEgahMjSXs5nuVqnwvyanG9aaEQF6m7M5mSY2wfZzW" ] self.blocks = [] self.coinbase_key = CECKey() self.coinbase_key.set_secretbytes( bytes.fromhex( "12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747" )) self.schnorr_key = Schnorr() self.schnorr_key.set_secretbytes( bytes.fromhex( "12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747" )) self.num_nodes = 1 self.sig_scheme = 0 self.setup_clean_chain = True self.genesisBlock = createTestGenesisBlock(self.aggpubkeys[0], self.aggprivkey[0], int(time.time() - 100))
def set_test_params(self): self.aggpubkeys = [ "025700236c2890233592fcef262f4520d22af9160e3d9705855140eb2aa06c35d3", "03831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc", "02bf2027c8455800c7626542219e6208b5fe787483689f1391d6d443ec85673ecf", "03b44f1cfcf46aba8bc98e2fd39f137cc43d98ab7792e4848b09c06198b042ca8b", "02b9a609d6bec0fdc9ba690986013cf7bbd13c54ffc25e6cf30916b4732c4a952a", "02e78cafe033b22bda5d7d1c8e82ee932930bf12e08489bc19769cbec765568be9", "02473757a955a23f75379820f3071abf5b3343b78eb54e52373d06259ffa6c550b" ] self.aggprivkey = [ "67ae3f5bfb3464b9704d7bd3a134401cc80c3a172240ebfca9f1e40f51bb6d37", "dbb9d19637018267268dfc2cc7aec07e7217c1a2d6733e1184a0909273bf078b", "aa2c70c4b85a09be514292d04b27bbb0cc3f86d306d58fe87743d10a095ada07", "3087d8decc5f951f19a442397cf1eba1e2b064e68650c346502780b56454c6e2", "6125c8d4330941944cc6cc3e775e8620c479a5901ad627e6e734c6a6f7377428", "1c3e5453c0f9aa74a8eb0216310b2b013f017813a648fce364bf41dbc0b37647", "ea9fe9fd2f1761fc6f1f0f23eb4d4141d7b05f2b95a1b7a9912cd97bddd9036c" ] self.blocks = [] self.coinbase_key = CECKey() self.coinbase_key.set_secretbytes( bytes.fromhex( "12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747" )) self.schnorr_key = Schnorr() self.schnorr_key.set_secretbytes( bytes.fromhex( "12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747" )) self.num_nodes = 1 self.sig_scheme = 0 self.setup_clean_chain = True self.genesisBlock = createTestGenesisBlock(self.aggpubkeys[0], self.aggprivkey[0], int(time.time() - 100))
class FederationManagementTest(BitcoinTestFramework): def set_test_params(self): self.aggpubkeys = [ "025700236c2890233592fcef262f4520d22af9160e3d9705855140eb2aa06c35d3", "03831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc", "02bf2027c8455800c7626542219e6208b5fe787483689f1391d6d443ec85673ecf", "03b44f1cfcf46aba8bc98e2fd39f137cc43d98ab7792e4848b09c06198b042ca8b", "02b9a609d6bec0fdc9ba690986013cf7bbd13c54ffc25e6cf30916b4732c4a952a", "02e78cafe033b22bda5d7d1c8e82ee932930bf12e08489bc19769cbec765568be9", "02473757a955a23f75379820f3071abf5b3343b78eb54e52373d06259ffa6c550b" ] self.aggprivkey = [ "67ae3f5bfb3464b9704d7bd3a134401cc80c3a172240ebfca9f1e40f51bb6d37", "dbb9d19637018267268dfc2cc7aec07e7217c1a2d6733e1184a0909273bf078b", "aa2c70c4b85a09be514292d04b27bbb0cc3f86d306d58fe87743d10a095ada07", "3087d8decc5f951f19a442397cf1eba1e2b064e68650c346502780b56454c6e2", "6125c8d4330941944cc6cc3e775e8620c479a5901ad627e6e734c6a6f7377428", "1c3e5453c0f9aa74a8eb0216310b2b013f017813a648fce364bf41dbc0b37647", "ea9fe9fd2f1761fc6f1f0f23eb4d4141d7b05f2b95a1b7a9912cd97bddd9036c" ] self.aggprivkey_wif = [ "cR4F4fGuKjDWxiYDtGtyM77WkrVhTgokVyM2ERxoxp7R4RQP9dgE", "cUwpWhH9CbYwjUWzfz1UVaSjSQm9ALXWRqeFFiZKnn8cV6wqNXQA", "cTHVmjaAwKtU75t89fg42SLx43nRxhsri6YY1Eynvs1V1tPRCfae", "cPD3D5AvmXhw7NGxQeaRhTVNW2UoYeibQAMhye7jzyM4ETG9d1ez", "cQqYVqYhK47EWvDViNwcyhc6sLS6tkuhED7T3rvumeGRtVJcEQHh", "cNXbwddRQrPR4k7Us7eSrRUHFBerNBKwxrExTSs4gdH1rjHdoNuL", "cVSnGe9DzWfEgahMjSXs5nuVqnwvyanG9aaEQF6m7M5mSY2wfZzW" ] self.blocks = [] self.coinbase_key = CECKey() self.coinbase_key.set_secretbytes( bytes.fromhex( "12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747" )) self.schnorr_key = Schnorr() self.schnorr_key.set_secretbytes( bytes.fromhex( "12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747" )) self.num_nodes = 1 self.sig_scheme = 0 self.setup_clean_chain = True self.genesisBlock = createTestGenesisBlock(self.aggpubkeys[0], self.aggprivkey[0], int(time.time() - 100)) def run_test(self): node = self.nodes[0] # convenience reference to the node self.address = node.getnewaddress() node.add_p2p_connection(P2PDataStore()) node.p2p.wait_for_getheaders(timeout=5) self.log.info("Test starting...") #genesis block (B0) self.blocks = [self.genesisBlock.hash] block_time = self.genesisBlock.nTime # Create a new blocks B1 - B10 self.blocks += node.generate(1, self.aggprivkey_wif[0]) create_colored_transaction(2, 100, node) self.blocks += node.generate(9, self.aggprivkey_wif[0]) best_block = node.getblock(node.getbestblockhash()) self.tip = node.getbestblockhash() self.log.info("First federation block") # B11 - Create block - aggpubkey2 - sign with aggpubkey1 block_time = best_block["time"] + 1 blocknew = create_block(int(self.tip, 16), create_coinbase(11), block_time, self.aggpubkeys[1]) blocknew.solve(self.aggprivkey[0]) self.blocks += [blocknew.hash] node.submitblock(bytes_to_hex_str(blocknew.serialize())) self.tip = self.blocks[-1] assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) #B -- Create block with invalid aggpubkey2 - sign with aggpubkey1 -- failure - invalid aggpubkey aggpubkeyInv = self.aggpubkeys[-1][:-2] block_time += 1 blocknew = create_block(int(self.tip, 16), create_coinbase(12), block_time, aggpubkeyInv) blocknew.solve(self.aggprivkey[0]) assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())), "invalid") assert_equal(self.tip, node.getbestblockhash()) # B - Create block - sign with aggpubkey1 - failure - Proof verification failed block_time += 1 blocknew = create_block(int(self.tip, 16), create_coinbase(12), block_time) blocknew.solve(self.aggprivkey[0]) assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())), "invalid") assert_equal(self.tip, node.getbestblockhash()) # B12 - Create block - sign with aggpubkey2 blocknew.solve(self.aggprivkey[1]) self.blocks += [blocknew.hash] node.submitblock(bytes_to_hex_str(blocknew.serialize())) self.tip = self.blocks[-1] assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) # Create a new blocks B13 - B22 self.blocks += node.generate(10, self.aggprivkey_wif[1]) best_block = node.getblock(node.getbestblockhash()) self.tip = node.getbestblockhash() #B23 -- Create block with 1 valid transaction - sign with aggpubkey2 -- success block_time = best_block["time"] + 1 blocknew = create_block(int(self.tip, 16), create_coinbase(23), block_time) spendHash = node.getblock(self.blocks[2])['tx'][1] vout = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction( spendHash, 1)["vout"]) if vout["value"] != 100) rawtx = node.createrawtransaction(inputs=[{ "txid": spendHash, "vout": vout }], outputs={self.address: 1.0}) signresult = node.signrawtransactionwithwallet(rawtx, [], "ALL", self.options.scheme) assert_equal(signresult["complete"], True) tx = CTransaction() tx.deserialize(BytesIO(hex_str_to_bytes(signresult['hex']))) blocknew.vtx += [tx] blocknew.hashMerkleRoot = blocknew.calc_merkle_root() blocknew.hashImMerkleRoot = blocknew.calc_immutable_merkle_root() blocknew.solve(self.aggprivkey[1]) self.blocks.append(blocknew.hash) self.tip = blocknew.hash node.submitblock(bytes_to_hex_str(blocknew.serialize())) assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) #call invalidate block rpc on B23 -- success - B23 is removed from the blockchain. tip is B22 node.invalidateblock(self.tip) self.tip = self.blocks[22] assert_equal(self.tip, node.getbestblockhash()) #B23 -- Re Create a new block B23 -- success block_time += 1 blocknew = create_block(int(self.tip, 16), create_coinbase(23), block_time) spendHash = node.getblock(self.blocks[2])['tx'][0] blocknew.vtx += [ create_transaction(node, spendHash, self.address, amount=49.0) ] blocknew.hashMerkleRoot = blocknew.calc_merkle_root() blocknew.hashImMerkleRoot = blocknew.calc_immutable_merkle_root() blocknew.solve(self.aggprivkey[1]) self.blocks[22] = blocknew.hash self.tip = blocknew.hash node.submitblock(bytes_to_hex_str(blocknew.serialize())) assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) #B -- - Create block with 1 invalid transaction - sign with aggpubkey2 -- failure block_time += 1 blocknew = create_block(int(self.tip, 16), create_coinbase(23), block_time) spendHash = node.getblock(self.blocks[3])['tx'][0] blocknew.vtx += [ create_transaction(node, spendHash, self.address, amount=100.0) ] #invalid blocknew.hashMerkleRoot = blocknew.calc_merkle_root() blocknew.hashImMerkleRoot = blocknew.calc_immutable_merkle_root() blocknew.solve(self.aggprivkey[1]) assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())), "invalid") assert_equal(self.tip, node.getbestblockhash()) #B -- - Create block with 1 invalid transaction and aggpubkey3 - sign with aggpubkey2 -- failure and aggpubkey3 is not added to the list blocknew = create_block(int(self.tip, 16), create_coinbase(23), block_time, self.aggpubkeys[2]) spendHash = node.getblock(self.blocks[4])['tx'][0] blocknew.vtx += [ create_transaction(node, spendHash, self.address, amount=100.0) ] #invalid blocknew.hashMerkleRoot = blocknew.calc_merkle_root() blocknew.hashImMerkleRoot = blocknew.calc_immutable_merkle_root() blocknew.solve(self.aggprivkey[1]) assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())), "invalid") assert_equal(self.tip, node.getbestblockhash()) # verify aggpubkey3 is not added to the list : verify that block signed using aggprivkey3 is rejected blocknew = create_block(int(self.tip, 16), create_coinbase(24), block_time, self.aggpubkeys[2]) blocknew.solve(self.aggprivkey[2]) assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())), "invalid") assert_equal(self.tip, node.getbestblockhash()) self.log.info("Second federation block") #B24 -- Create block with 1 valid transaction and aggpubkey3- sign with aggpubkey2 -- success and aggpubkey3 is added to the list block_time += 1 blocknew = create_block(int(self.tip, 16), create_coinbase(24), block_time, self.aggpubkeys[2]) spendHash = node.getblock(self.blocks[4])['tx'][0] blocknew.vtx += [ create_transaction(node, spendHash, self.address, amount=10.0) ] blocknew.hashMerkleRoot = blocknew.calc_merkle_root() blocknew.hashImMerkleRoot = blocknew.calc_immutable_merkle_root() blocknew.solve(self.aggprivkey[1]) self.blocks.append(blocknew.hash) self.tip = blocknew.hash node.submitblock(bytes_to_hex_str(blocknew.serialize())) assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) #B25 -- Create block with 1 valid transaction - sign with aggpubkey3 -- success block_time += 1 blocknew = create_block(int(self.tip, 16), create_coinbase(25), block_time) spendHash = node.getblock(self.blocks[5])['tx'][0] blocknew.vtx += [ create_transaction(node, spendHash, self.address, amount=10.0) ] blocknew.hashMerkleRoot = blocknew.calc_merkle_root() blocknew.hashImMerkleRoot = blocknew.calc_immutable_merkle_root() blocknew.solve(self.aggprivkey[2]) self.blocks.append(blocknew.hash) self.tip = blocknew.hash b25 = blocknew.hash node.submitblock(bytes_to_hex_str(blocknew.serialize())) assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) # Create a new blocks B26 - B30 self.blocks += node.generate(5, self.aggprivkey_wif[2]) best_block = node.getblock(node.getbestblockhash()) self.tip = node.getbestblockhash() self.log.info("Verifying getblockchaininfo") #getblockchaininfo expectedAggPubKeys = [{ self.aggpubkeys[0]: 0 }, { self.aggpubkeys[1]: 12 }, { self.aggpubkeys[2]: 25 }] blockchaininfo = node.getblockchaininfo() assert_equal(blockchaininfo["aggregatePubkeys"], expectedAggPubKeys) self.log.info( "Simulate Blockchain Reorg - After the last federation block") #B27 -- Create block with previous block hash = B26 - sign with aggpubkey3 -- success - block is accepted but there is no re-org block_time += 1 self.forkblocks = self.blocks blocknew = create_block(int(self.blocks[26], 16), create_coinbase(27), block_time) blocknew.solve(self.aggprivkey[2]) node.submitblock(bytes_to_hex_str(blocknew.serialize())) self.forkblocks[27] = blocknew.hash assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) #B28 -- Create block with previous block hash = B27 - sign with aggpubkey3 -- success - block is accepted but there is no re-org block_time += 1 blocknew = create_block(int(self.forkblocks[27], 16), create_coinbase(28), block_time) blocknew.solve(self.aggprivkey[2]) node.submitblock(bytes_to_hex_str(blocknew.serialize())) self.forkblocks[28] = blocknew.hash assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) #B29 -- Create block with previous block hash = B28 - sign with aggpubkey3 -- success - block is accepted but there is no re-org block_time += 1 blocknew = create_block(int(self.forkblocks[28], 16), create_coinbase(29), block_time) blocknew.solve(self.aggprivkey[2]) node.submitblock(bytes_to_hex_str(blocknew.serialize())) self.forkblocks[29] = blocknew.hash assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) #B30 -- Create block with previous block hash = B29 - sign with aggpubkey3 -- success - block is accepted but there is no re-org block_time += 1 blocknew = create_block(int(self.forkblocks[29], 16), create_coinbase(30), block_time) blocknew.solve(self.aggprivkey[2]) node.submitblock(bytes_to_hex_str(blocknew.serialize())) self.forkblocks[30] = blocknew.hash assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) #B31 -- Create block with previous block hash = B30 - sign with aggpubkey3 -- success - block is accepted and re-org happens block_time += 1 blocknew = create_block(int(self.forkblocks[30], 16), create_coinbase(31), block_time) blocknew.solve(self.aggprivkey[2]) node.submitblock(bytes_to_hex_str(blocknew.serialize())) self.forkblocks.append(blocknew.hash) self.tip = blocknew.hash assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) assert_equal(blockchaininfo["aggregatePubkeys"], expectedAggPubKeys) self.log.info( "Simulate Blockchain Reorg - Before the last federation block") #B24 -- Create block with previous block hash = B23 - sign with aggpubkey2 -- failure - block is in invalid chain block_time += 1 blocknew = create_block(int(self.blocks[23], 16), create_coinbase(24), block_time) blocknew.solve(self.aggprivkey[1]) assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())), "invalid") assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) #B25 -- Create block with previous block hash = B24 - sign with aggpubkey2 -- success - block is in invalid chain block_time += 1 blocknew = create_block(int(self.blocks[24], 16), create_coinbase(25), block_time) blocknew.solve(self.aggprivkey[1]) assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())), "invalid") assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) #there are 3 tips in the current blockchain chaintips = node.getchaintips() assert_equal(len(chaintips), 3) assert (node.getblock(self.blocks[12])) assert (node.getblock(self.blocks[25])) assert_raises_rpc_error(-5, "Block not found", node.getblock, blocknew.hash) self.log.info("Third Federation Block - active chain") #B32 -- Create block with aggpubkey4 - sign with aggpubkey3 -- success - aggpubkey4 is added to the list block_time += 1 blocknew = create_block(int(self.tip, 16), create_coinbase(32), block_time, self.aggpubkeys[3]) blocknew.solve(self.aggprivkey[2]) node.submitblock(bytes_to_hex_str(blocknew.serialize())) self.forkblocks.append(blocknew.hash) self.tip = blocknew.hash assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) #B -- Create block - sign with aggpubkey2 -- failure - proof verification failed block_time += 1 blocknew = create_block(int(self.tip, 16), create_coinbase(33), block_time) blocknew.solve(self.aggprivkey[1]) assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())), "invalid") assert_equal(self.tip, node.getbestblockhash()) #B -- Create block - sign with aggpubkey3 -- failure - proof verification failed blocknew.solve(self.aggprivkey[2]) assert_equal(node.submitblock(bytes_to_hex_str(blocknew.serialize())), "invalid") assert_equal(self.tip, node.getbestblockhash()) #B33 -- Create block - sign with aggpubkey4 -- success blocknew.solve(self.aggprivkey[3]) node.submitblock(bytes_to_hex_str(blocknew.serialize())) self.forkblocks.append(blocknew.hash) self.tip = blocknew.hash assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) #B34 - B35 -- Generate 2 blocks - no aggpubkey -- chain becomes longer self.forkblocks += node.generate(2, self.aggprivkey_wif[3]) self.tip = self.forkblocks[35] assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) self.log.info("Fourth Federation Block") #B36 -- Create block with aggpubkey5 - sign using aggpubkey4 -- success - aggpubkey5 is added to the list block_time += 1 blocknew = create_block(int(self.tip, 16), create_coinbase(36), block_time, self.aggpubkeys[4]) blocknew.solve(self.aggprivkey[3]) node.submitblock(bytes_to_hex_str(blocknew.serialize())) self.tip = blocknew.hash self.forkblocks.append(blocknew.hash) assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) #call invalidate block rpc on B36 -- failure - B36 is a federation block assert_raises_rpc_error(-8, "Federation block found", node.invalidateblock, self.tip) assert_raises_rpc_error(-8, "Federation block found", node.invalidateblock, self.forkblocks[33]) assert_raises_rpc_error(-8, "Federation block found", node.invalidateblock, self.blocks[29]) assert_equal(self.tip, node.getbestblockhash()) #B37 - Create block - sign using aggpubkey5 -- success block_time += 1 blocknew = create_block(int(self.tip, 16), create_coinbase(37), block_time) blocknew.solve(self.aggprivkey[4]) node.submitblock(bytes_to_hex_str(blocknew.serialize())) self.tip = blocknew.hash self.forkblocks.append(blocknew.hash) assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) self.log.info("Verifying getblockchaininfo") #getblockchaininfo expectedAggPubKeys = [ { self.aggpubkeys[0]: 0 }, { self.aggpubkeys[1]: 12 }, { self.aggpubkeys[2]: 25 }, { self.aggpubkeys[3]: 33 }, { self.aggpubkeys[4]: 37 }, ] blockchaininfo = node.getblockchaininfo() assert_equal(blockchaininfo["aggregatePubkeys"], expectedAggPubKeys) #B38 - B40 -- Generate 2 blocks - no aggpubkey -- chain becomes longer self.forkblocks += node.generate(3, self.aggprivkey_wif[4]) self.tip = node.getbestblockhash() best_block = node.getblock(self.tip) self.log.info("Test Repeated aggpubkeys in Federation Block") #B41 -- Create block with aggpubkey0 - sign using aggpubkey5 -- success - aggpubkey0 is added to the list block_time = best_block["time"] + 1 blocknew = create_block(int(self.tip, 16), create_coinbase(41), block_time, self.aggpubkeys[0]) blocknew.solve(self.aggprivkey[4]) node.submitblock(bytes_to_hex_str(blocknew.serialize())) self.tip = blocknew.hash assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) #B42 -- Create block with aggpubkey1 - sign using aggpubkey0 -- success - aggpubkey1 is added to the list block_time += 1 blocknew = create_block(int(self.tip, 16), create_coinbase(42), block_time, self.aggpubkeys[1]) blocknew.solve(self.aggprivkey[0]) node.submitblock(bytes_to_hex_str(blocknew.serialize())) self.tip = blocknew.hash assert_equal(self.tip, node.getbestblockhash()) assert (node.getblock(self.tip)) self.log.info("Verifying getblockchaininfo") #getblockchaininfo expectedAggPubKeys = [ { self.aggpubkeys[0]: 0 }, { self.aggpubkeys[1]: 12 }, { self.aggpubkeys[2]: 25 }, { self.aggpubkeys[3]: 33 }, { self.aggpubkeys[4]: 37 }, { self.aggpubkeys[0]: 42 }, { self.aggpubkeys[1]: 43 }, ] blockchaininfo = node.getblockchaininfo() assert_equal(blockchaininfo["aggregatePubkeys"], expectedAggPubKeys) self.stop_node(0) self.log.info("Restarting node with '-reindex-chainstate'") self.start_node(0, extra_args=["-reindex-chainstate"]) self.sync_all() self.stop_node(0) self.log.info("Restarting node with '-loadblock'") shutil.copyfile( os.path.join(self.nodes[0].datadir, NetworkDirName(), 'blocks', 'blk00000.dat'), os.path.join(self.nodes[0].datadir, 'blk00000.dat')) os.remove( os.path.join(self.nodes[0].datadir, NetworkDirName(), 'blocks', 'blk00000.dat')) extra_args = [ "-loadblock=%s" % os.path.join(self.nodes[0].datadir, 'blk00000.dat'), "-reindex" ] self.start_node(0, extra_args)
def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 1 self.extra_args = [["-whitelist=127.0.0.1"]] self.signKey = Schnorr() self.signKey.set_secretbytes(hex_str_to_bytes(self.signblockprivkey))
class BlockHeaderXFieldTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 1 self.extra_args = [["-whitelist=127.0.0.1"]] self.signKey = Schnorr() self.signKey.set_secretbytes(hex_str_to_bytes(self.signblockprivkey)) def createblockproof(self, block, signblockprivkey): # create block proof with xField for all xfieldTypes r = b"" r += struct.pack("<i", block.nVersion) r += ser_uint256(block.hashPrevBlock) r += ser_uint256(block.hashMerkleRoot) r += ser_uint256(block.hashImMerkleRoot) r += struct.pack("<I", block.nTime) r += struct.pack("B", block.xfieldType) r += ser_string(block.xfield) sighash = hash256(r) block.proof = bytearray(self.signKey.sign(sighash)) block.rehash() def serializeblock_err(self, block): r = b"" r += struct.pack("<i", block.nVersion) r += ser_uint256(block.hashPrevBlock) r += ser_uint256(block.hashMerkleRoot) r += ser_uint256(block.hashImMerkleRoot) r += struct.pack("<I", block.nTime) r += struct.pack("B", block.xfieldType) r += block.xfield r += ser_string(block.proof) r += ser_vector(block.vtx) return r def reconnect_p2p(self): """Tear down and bootstrap the P2P connection to the node. The node gets disconnected several times in this test. This helper method reconnects the p2p and restarts the network thread.""" self.nodes[0].disconnect_p2ps() self.nodes[0].add_p2p_connection(P2PDataStore()) self.nodes[0].p2p.wait_for_getheaders(timeout=5) def run_test(self): node = self.nodes[0] node.add_p2p_connection(P2PDataStore()) node.p2p.wait_for_getheaders(timeout=5) self.tip = node.getbestblockhash() best_block = node.getblock(self.tip) block_time = best_block["time"] + 1 self.log.info("Incorrect xfield with xfieldType = 0") block = create_block(int(self.tip, 16), create_coinbase(1), block_time) block.xfieldType = 0 block.xfield = b'1' self.createblockproof(block, self.signblockprivkey) node.p2p.send_blocks_and_test([block], node, success=False, request_block=False) self.log.info("Incorrect xfield with xfieldType = 1") block = create_block(int(self.tip, 16), create_coinbase(1), block_time) block.xfieldType = 1 block.xfield = b'1' self.createblockproof(block, self.signblockprivkey) node.p2p.send_blocks_and_test([block], node, success=False, request_block=False, reject_code=16, reject_reason="bad-xfieldType-xfield") blockchaininfo = node.getblockchaininfo() assert_equal( blockchaininfo['warnings'], "This is a pre-release test build - use at your own risk - do not use for mining or merchant applications" ) self.log.info("Incorrect xfield with xfieldType = 2") block = create_block(int(self.tip, 16), create_coinbase(1), block_time) block.xfieldType = 2 block.xfield = b'1' self.createblockproof(block, self.signblockprivkey) assert_raises_rpc_error( -22, "", node.submitblock, bytes_to_hex_str(self.serializeblock_err(block))) blockchaininfo = node.getblockchaininfo() assert_equal( blockchaininfo['warnings'], "This is a pre-release test build - use at your own risk - do not use for mining or merchant applications" ) self.log.info("Valid xfield with xfieldType = 2") node.p2p.send_blocks_and_test([block], node, True, True) assert_equal(block.hash, node.getbestblockhash()) blockchaininfo = node.getblockchaininfo() assert_equal( blockchaininfo['warnings'], "Warning: Unknown xfieldType [%2x] was accepted in block [%s]" % (block.xfieldType, block.hash)) self.log.info("Valid xfield with xfieldType = 0xFF") self.tip = node.getbestblockhash() block_time += 1 block = create_block(int(self.tip, 16), create_coinbase(2), block_time) block.xfieldType = 0xFF block.xfield = b'1' self.createblockproof(block, self.signblockprivkey) node.p2p.send_blocks_and_test([block], node, True, True) assert_equal(block.hash, node.getbestblockhash()) self.log.info( "xfieldType = 3 in invalid block - insufficient tx input") self.tip = node.getbestblockhash() block_time += 1 block = create_block(int(self.tip, 16), create_coinbase(3), block_time) block.xfieldType = 3 block.xfield = b'' spendHash = node.getblock(self.tip)['tx'][0] block.vtx += [ create_transaction(node, spendHash, node.getnewaddress(), amount=100.0) ] block.hashMerkleRoot = block.calc_merkle_root() block.hashImMerkleRoot = block.calc_immutable_merkle_root() self.createblockproof(block, self.signblockprivkey) oldblockhash = block.hash node.p2p.send_blocks_and_test([block], node, success=False, request_block=True, reject_code=16, reject_reason="bad-txns-in-belowout") assert_equal(self.tip, node.getbestblockhash()) blockchaininfo = node.getblockchaininfo() assert_equal( blockchaininfo['warnings'], "Warning: Unknown xfieldType [%2x] was accepted in block [%s]" % (block.xfieldType, block.hash)) self.log.info("xfieldType = 4 in invalid block - height in coinbase") block_time += 1 block = create_block(int(self.tip, 16), create_coinbase(1), block_time) block.xfieldType = 4 block.xfield = b'' self.createblockproof(block, self.signblockprivkey) node.p2p.send_blocks_and_test([block], node, success=False, request_block=True, reject_code=16, reject_reason="bad-cb-invalid") assert_equal(self.tip, node.getbestblockhash()) blockchaininfo = node.getblockchaininfo() assert_equal( blockchaininfo['warnings'], "Warning: Unknown xfieldType [%2x] was accepted in block [%s]" % (3, oldblockhash)) self.log.info("xfieldType = 5 in invalid block - no coinbase") block_time += 1 block = create_block(int(self.tip, 16), create_coinbase(4), block_time) block.xfieldType = 5 block.xfield = b'' block.vtx = [] self.createblockproof(block, self.signblockprivkey) node.p2p.send_blocks_and_test([block], node, success=False, request_block=True, reject_code=16, reject_reason="bad-cb-missing") assert_equal(self.tip, node.getbestblockhash()) blockchaininfo = node.getblockchaininfo() assert_equal( blockchaininfo['warnings'], "Warning: Unknown xfieldType [%2x] was accepted in block [%s]" % (3, oldblockhash))
class ColoredCoinTest(BitcoinTestFramework): def set_test_params(self): self.pubkeys = [ "025700236c2890233592fcef262f4520d22af9160e3d9705855140eb2aa06c35d3", "03831a69b8009833ab5b0326012eaf489bfea35a7321b1ca15b11d88131423fafc" ] privkeystr = [ "67ae3f5bfb3464b9704d7bd3a134401cc80c3a172240ebfca9f1e40f51bb6d37", "dbb9d19637018267268dfc2cc7aec07e7217c1a2d6733e1184a0909273bf078b" ] self.privkeys = [] for key in privkeystr: ckey = CECKey() ckey.set_secretbytes(bytes.fromhex(key)) self.privkeys.append(ckey) self.coinbase_key = CECKey() self.coinbase_key.set_secretbytes( bytes.fromhex( "12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747" )) self.coinbase_pubkey = self.coinbase_key.get_pubkey() self.schnorr_key = Schnorr() self.schnorr_key.set_secretbytes( bytes.fromhex( "12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747" )) self.num_nodes = 1 self.setup_clean_chain = True def run_test(self): node = self.nodes[0] # convenience reference to the node self.address = node.getnewaddress() node.add_p2p_connection(P2PDataStore()) node.p2p.wait_for_getheaders(timeout=5) self.address = self.nodes[0].getnewaddress() self.log.info("Test starting...") #generate 10 blocks for coinbase outputs coinbase_txs = [] for i in range(1, 10): height = node.getblockcount() + 1 coinbase_tx = create_coinbase(height, self.coinbase_pubkey) coinbase_txs.append(coinbase_tx) tip = node.getbestblockhash() block_time = node.getblockheader(tip)["mediantime"] + 1 block = create_block(int(tip, 16), coinbase_tx, block_time) block.solve(self.signblockprivkey) tip = block.hash node.p2p.send_and_ping(msg_block(block)) assert_equal(node.getbestblockhash(), tip) change_script = CScript([self.coinbase_pubkey, OP_CHECKSIG]) burn_script = CScript([hex_str_to_bytes(self.pubkeys[1]), OP_CHECKSIG]) #TxSuccess1 - coinbaseTx1 - issue 100 REISSUABLE + 30 (UTXO-1,2) colorId_reissuable = colorIdReissuable( coinbase_txs[0].vout[0].scriptPubKey) script_reissuable = CP2PHK_script(colorId=colorId_reissuable, pubkey=self.pubkeys[0]) script_transfer_reissuable = CP2PHK_script(colorId=colorId_reissuable, pubkey=self.pubkeys[1]) txSuccess1 = CTransaction() txSuccess1.vin.append( CTxIn(COutPoint(coinbase_txs[0].malfixsha256, 0), b"")) txSuccess1.vout.append(CTxOut(100, script_reissuable)) txSuccess1.vout.append( CTxOut(30 * COIN, CScript([self.coinbase_pubkey, OP_CHECKSIG]))) sig_hash, err = SignatureHash(coinbase_txs[0].vout[0].scriptPubKey, txSuccess1, 0, SIGHASH_ALL) signature = self.coinbase_key.sign( sig_hash) + b'\x01' # 0x1 is SIGHASH_ALL txSuccess1.vin[0].scriptSig = CScript([signature]) txSuccess1.rehash() test_transaction_acceptance(node, txSuccess1, accepted=True) #TxSuccess2 - (UTXO-2) - issue 100 NON-REISSUABLE (UTXO-3) colorId_nonreissuable = colorIdNonReissuable( COutPoint(txSuccess1.malfixsha256, 1).serialize()) script_nonreissuable = CP2PHK_script(colorId=colorId_nonreissuable, pubkey=self.pubkeys[0]) script_transfer_nonreissuable = CP2PHK_script( colorId=colorId_nonreissuable, pubkey=self.pubkeys[1]) txSuccess2 = CTransaction() txSuccess2.vin.append(CTxIn(COutPoint(txSuccess1.malfixsha256, 1), b"")) txSuccess2.vout.append(CTxOut(100, script_nonreissuable)) sig_hash, err = SignatureHash(txSuccess1.vout[1].scriptPubKey, txSuccess2, 0, SIGHASH_ALL) signature = self.coinbase_key.sign(sig_hash) + b'\x01' txSuccess2.vin[0].scriptSig = CScript([signature]) txSuccess2.rehash() test_transaction_acceptance(node, txSuccess2, accepted=True) #TxSuccess3 - coinbaseTx2 - issue 1 NFT (UTXO-4) colorId_nft = colorIdNFT( COutPoint(coinbase_txs[1].malfixsha256, 0).serialize()) script_nft = CP2PHK_script(colorId=colorId_nft, pubkey=self.pubkeys[0]) script_transfer_nft = CP2PHK_script(colorId=colorId_nft, pubkey=self.pubkeys[0]) txSuccess3 = CTransaction() txSuccess3.vin.append( CTxIn(COutPoint(coinbase_txs[1].malfixsha256, 0), b"")) txSuccess3.vout.append(CTxOut(1, script_nft)) sig_hash, err = SignatureHash(coinbase_txs[1].vout[0].scriptPubKey, txSuccess3, 0, SIGHASH_ALL) signature = self.coinbase_key.sign(sig_hash) + b'\x01' txSuccess3.vin[0].scriptSig = CScript([signature]) txSuccess3.rehash() test_transaction_acceptance(node, txSuccess3, accepted=True) #TxFailure4 - (UTXO-1) - split REISSUABLE - 25 + 75 (UTXO-5,6) # - (UTXO-3) - split NON-REISSUABLE - 40 + 60 (UTXO-7,8) # - coinbaseTx3 - issue 100 REISSUABLE (UTXO-9) TxFailure4 = CTransaction() TxFailure4.vin.append(CTxIn(COutPoint(txSuccess1.malfixsha256, 0), b"")) TxFailure4.vin.append(CTxIn(COutPoint(txSuccess2.malfixsha256, 0), b"")) TxFailure4.vin.append( CTxIn(COutPoint(coinbase_txs[2].malfixsha256, 0), b"")) TxFailure4.vout.append(CTxOut(25, script_reissuable)) TxFailure4.vout.append(CTxOut(75, script_reissuable)) TxFailure4.vout.append(CTxOut(40, script_nonreissuable)) TxFailure4.vout.append(CTxOut(60, script_nonreissuable)) TxFailure4.vout.append(CTxOut(100, script_reissuable)) sig_hash, err = SignatureHash(txSuccess1.vout[0].scriptPubKey, TxFailure4, 0, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' TxFailure4.vin[0].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(txSuccess2.vout[0].scriptPubKey, TxFailure4, 1, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' TxFailure4.vin[1].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(coinbase_txs[2].vout[0].scriptPubKey, TxFailure4, 2, SIGHASH_ALL) signature = self.coinbase_key.sign(sig_hash) + b'\x01' TxFailure4.vin[2].scriptSig = CScript([signature]) TxFailure4.rehash() test_transaction_acceptance(node, TxFailure4, accepted=False, reason=b"bad-txns-token-balance") #TxSuccess4 - (UTXO-1) - split REISSUABLE - 25 + 75 (UTXO-5,6) # - (UTXO-3) - split NON-REISSUABLE - 40 + 60 (UTXO-7,8) txSuccess4 = CTransaction() txSuccess4.vin.append(CTxIn(COutPoint(txSuccess1.malfixsha256, 0), b"")) txSuccess4.vin.append(CTxIn(COutPoint(txSuccess2.malfixsha256, 0), b"")) txSuccess4.vin.append( CTxIn(COutPoint(coinbase_txs[2].malfixsha256, 0), b"")) txSuccess4.vout.append(CTxOut(25, script_reissuable)) txSuccess4.vout.append(CTxOut(75, script_reissuable)) txSuccess4.vout.append(CTxOut(40, script_nonreissuable)) txSuccess4.vout.append(CTxOut(60, script_nonreissuable)) sig_hash, err = SignatureHash(txSuccess1.vout[0].scriptPubKey, txSuccess4, 0, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' txSuccess4.vin[0].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(txSuccess2.vout[0].scriptPubKey, txSuccess4, 1, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' txSuccess4.vin[1].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(coinbase_txs[2].vout[0].scriptPubKey, txSuccess4, 2, SIGHASH_ALL) signature = self.coinbase_key.sign(sig_hash) + b'\x01' txSuccess4.vin[2].scriptSig = CScript([signature]) txSuccess4.rehash() test_transaction_acceptance(node, txSuccess4, accepted=True) #TxFailure5 - (UTXO-6) - split REISSUABLE(75) (UTXO-10,11) # - (UTXO-7) - split NON-REISSUABLE(40) (UTXO-12) # - (UTXO-4) - split NFT (UTXO-13) # - coinbaseTx4 TxFailure5 = CTransaction() TxFailure5.vin.append(CTxIn(COutPoint(txSuccess4.malfixsha256, 1), b"")) TxFailure5.vin.append(CTxIn(COutPoint(txSuccess4.malfixsha256, 2), b"")) TxFailure5.vin.append(CTxIn(COutPoint(txSuccess3.malfixsha256, 0), b"")) TxFailure5.vin.append( CTxIn(COutPoint(coinbase_txs[3].malfixsha256, 0), b"")) TxFailure5.vout.append(CTxOut(35, script_reissuable)) TxFailure5.vout.append(CTxOut(40, script_reissuable)) TxFailure5.vout.append(CTxOut(20, script_nonreissuable)) TxFailure5.vout.append(CTxOut(20, script_nonreissuable)) TxFailure5.vout.append(CTxOut(1, script_nft)) TxFailure5.vout.append(CTxOut(1, script_nft)) sig_hash, err = SignatureHash(txSuccess4.vout[1].scriptPubKey, TxFailure5, 0, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' TxFailure5.vin[0].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(txSuccess4.vout[2].scriptPubKey, TxFailure5, 1, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' TxFailure5.vin[1].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(txSuccess3.vout[0].scriptPubKey, TxFailure5, 2, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' TxFailure5.vin[2].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(coinbase_txs[3].vout[0].scriptPubKey, TxFailure5, 3, SIGHASH_ALL) signature = self.coinbase_key.sign(sig_hash) + b'\x01' TxFailure5.vin[3].scriptSig = CScript([signature]) TxFailure5.rehash() test_transaction_acceptance(node, TxFailure5, accepted=False, reason=b"bad-txns-token-balance") #txSuccess5 - (UTXO-6) - split REISSUABLE(75) (UTXO-10,11) # - (UTXO-7) - split NON-REISSUABLE(40) (UTXO-12) # - (UTXO-4) - transfer NFT (UTXO-13) # - coinbaseTx4 txSuccess5 = CTransaction() txSuccess5.vin.append(CTxIn(COutPoint(txSuccess4.malfixsha256, 1), b"")) txSuccess5.vin.append(CTxIn(COutPoint(txSuccess4.malfixsha256, 2), b"")) txSuccess5.vin.append(CTxIn(COutPoint(txSuccess3.malfixsha256, 0), b"")) txSuccess5.vin.append( CTxIn(COutPoint(coinbase_txs[3].malfixsha256, 0), b"")) txSuccess5.vout.append(CTxOut(35, script_reissuable)) txSuccess5.vout.append(CTxOut(40, script_reissuable)) txSuccess5.vout.append(CTxOut(20, script_nonreissuable)) txSuccess5.vout.append(CTxOut(20, script_nonreissuable)) txSuccess5.vout.append(CTxOut(1, script_nft)) sig_hash, err = SignatureHash(txSuccess4.vout[1].scriptPubKey, txSuccess5, 0, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' txSuccess5.vin[0].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(txSuccess4.vout[2].scriptPubKey, txSuccess5, 1, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' txSuccess5.vin[1].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(txSuccess3.vout[0].scriptPubKey, txSuccess5, 2, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' txSuccess5.vin[2].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(coinbase_txs[3].vout[0].scriptPubKey, txSuccess5, 3, SIGHASH_ALL) signature = self.coinbase_key.sign(sig_hash) + b'\x01' txSuccess5.vin[3].scriptSig = CScript([signature]) txSuccess5.rehash() test_transaction_acceptance(node, txSuccess5, accepted=True) #TxFailure6 - (UTXO-11) - transfer REISSUABLE(40) (UTXO-14) # - (UTXO-8) - burn NON-REISSUABLE(60) (UTXO-15)* # - (UTXO-13) - transfer NFT (UTXO-16) # - coinbaseTx5 - issue 1000 REISSUABLE1, change (UTXO-17) colorId_reissuable1 = colorIdReissuable( coinbase_txs[6].vout[0].scriptPubKey) script_reissuable1 = CP2PHK_script(colorId=colorId_reissuable, pubkey=self.pubkeys[0]) TxFailure6 = CTransaction() TxFailure6.vin.append(CTxIn(COutPoint(txSuccess5.malfixsha256, 1), b"")) TxFailure6.vin.append(CTxIn(COutPoint(txSuccess4.malfixsha256, 3), b"")) TxFailure6.vin.append(CTxIn(COutPoint(txSuccess5.malfixsha256, 4), b"")) TxFailure6.vin.append( CTxIn(COutPoint(coinbase_txs[4].malfixsha256, 0), b"")) TxFailure6.vout.append(CTxOut(40, script_transfer_reissuable)) TxFailure6.vout.append(CTxOut(30, script_transfer_nonreissuable)) TxFailure6.vout.append(CTxOut(1, script_transfer_nft)) TxFailure6.vout.append(CTxOut(1000, script_reissuable1)) TxFailure6.vout.append(CTxOut(1 * COIN, change_script)) sig_hash, err = SignatureHash(txSuccess5.vout[1].scriptPubKey, TxFailure6, 0, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' TxFailure6.vin[0].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(txSuccess4.vout[3].scriptPubKey, TxFailure6, 1, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' TxFailure6.vin[1].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(txSuccess5.vout[4].scriptPubKey, TxFailure6, 2, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' TxFailure6.vin[2].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(coinbase_txs[4].vout[0].scriptPubKey, TxFailure6, 3, SIGHASH_ALL) signature = self.coinbase_key.sign(sig_hash) + b'\x01' TxFailure6.vin[3].scriptSig = CScript([signature]) TxFailure6.rehash() test_transaction_acceptance(node, TxFailure6, accepted=False, reason=b"bad-txns-token-balance") #TxSuccess6 - (UTXO-11) - transfer REISSUABLE(40) (UTXO-14) # - (UTXO-8) - burn NON-REISSUABLE(60) (UTXO-15)* # - (UTXO-13) - transfer NFT (UTXO-16) # - coinbaseTx5 - change txSuccess6 = CTransaction() txSuccess6.vin.append(CTxIn(COutPoint(txSuccess5.malfixsha256, 1), b"")) txSuccess6.vin.append(CTxIn(COutPoint(txSuccess4.malfixsha256, 3), b"")) txSuccess6.vin.append(CTxIn(COutPoint(txSuccess5.malfixsha256, 4), b"")) txSuccess6.vin.append( CTxIn(COutPoint(coinbase_txs[4].malfixsha256, 0), b"")) txSuccess6.vout.append(CTxOut(40, script_transfer_reissuable)) txSuccess6.vout.append(CTxOut(30, script_transfer_nonreissuable)) txSuccess6.vout.append(CTxOut(1, script_transfer_nft)) txSuccess6.vout.append(CTxOut(1 * COIN, change_script)) sig_hash, err = SignatureHash(txSuccess5.vout[1].scriptPubKey, txSuccess6, 0, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' txSuccess6.vin[0].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(txSuccess4.vout[3].scriptPubKey, txSuccess6, 1, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' txSuccess6.vin[1].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(txSuccess5.vout[4].scriptPubKey, txSuccess6, 2, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' txSuccess6.vin[2].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(coinbase_txs[4].vout[0].scriptPubKey, txSuccess6, 3, SIGHASH_ALL) signature = self.coinbase_key.sign(sig_hash) + b'\x01' txSuccess6.vin[3].scriptSig = CScript([signature]) txSuccess6.rehash() test_transaction_acceptance(node, txSuccess6, accepted=True) #TxSuccess7 - coinbaseTx5 - issue 1000 REISSUABLE1, change (UTXO-17) txSuccess7 = CTransaction() txSuccess7.vin.append( CTxIn(COutPoint(coinbase_txs[5].malfixsha256, 0), b"")) txSuccess7.vout.append(CTxOut(1000, script_reissuable1)) sig_hash, err = SignatureHash(coinbase_txs[5].vout[0].scriptPubKey, txSuccess7, 0, SIGHASH_ALL) signature = self.coinbase_key.sign(sig_hash) + b'\x01' txSuccess7.vin[0].scriptSig = CScript([signature]) txSuccess7.rehash() test_transaction_acceptance(node, txSuccess7, accepted=True) #TxFailure7 - (UTXO-9,14) - aggregate REISSUABLE(25 + 40) x # - (UTXO-12) - burn NON-REISSUABLE(20) * TxFailure7 = CTransaction() TxFailure7.vin.append(CTxIn(COutPoint(txSuccess4.malfixsha256, 0), b"")) TxFailure7.vin.append(CTxIn(COutPoint(txSuccess6.malfixsha256, 0), b"")) TxFailure7.vin.append(CTxIn(COutPoint(txSuccess5.malfixsha256, 2), b"")) TxFailure7.vout.append(CTxOut(65, script_transfer_reissuable)) sig_hash, err = SignatureHash(txSuccess4.vout[0].scriptPubKey, TxFailure7, 0, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' TxFailure7.vin[0].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(txSuccess6.vout[0].scriptPubKey, TxFailure7, 1, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' TxFailure7.vin[1].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(txSuccess5.vout[2].scriptPubKey, TxFailure7, 2, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' TxFailure7.vin[2].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) TxFailure7.rehash() test_transaction_acceptance(node, TxFailure7, accepted=False, reason=b'min relay fee not met') #txSuccess8 - (UTXO-9,14) - aggregate REISSUABLE(25 + 40) x # - (UTXO-12) - burn NON-REISSUABLE(20) * # - coinbase[6] txSuccess8 = CTransaction() txSuccess8.vin.append(CTxIn(COutPoint(txSuccess4.malfixsha256, 0), b"")) txSuccess8.vin.append(CTxIn(COutPoint(txSuccess6.malfixsha256, 0), b"")) txSuccess8.vin.append(CTxIn(COutPoint(txSuccess5.malfixsha256, 2), b"")) txSuccess8.vin.append( CTxIn(COutPoint(coinbase_txs[6].malfixsha256, 0), b"")) txSuccess8.vout.append(CTxOut(65, script_transfer_reissuable)) sig_hash, err = SignatureHash(txSuccess4.vout[0].scriptPubKey, txSuccess8, 0, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' txSuccess8.vin[0].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(txSuccess6.vout[0].scriptPubKey, txSuccess8, 1, SIGHASH_ALL) signature = self.privkeys[1].sign(sig_hash) + b'\x01' txSuccess8.vin[1].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[1])]) sig_hash, err = SignatureHash(txSuccess5.vout[2].scriptPubKey, txSuccess8, 2, SIGHASH_ALL) signature = self.privkeys[0].sign(sig_hash) + b'\x01' txSuccess8.vin[2].scriptSig = CScript( [signature, hex_str_to_bytes(self.pubkeys[0])]) sig_hash, err = SignatureHash(coinbase_txs[6].vout[0].scriptPubKey, txSuccess8, 3, SIGHASH_ALL) signature = self.coinbase_key.sign(sig_hash) + b'\x01' txSuccess8.vin[3].scriptSig = CScript([signature]) txSuccess8.rehash() test_transaction_acceptance(node, txSuccess8, accepted=True) #TxFailure8 - (UTXO-17) - convert REISSUABLE to NON-REISSUABLE TxFailure8 = CTransaction() TxFailure8.vin.append(CTxIn(COutPoint(txSuccess7.malfixsha256, 0), b"")) TxFailure8.vout.append(CTxOut(60, script_transfer_nonreissuable)) sig_hash, err = SignatureHash(txSuccess7.vout[0].scriptPubKey, TxFailure8, 0, SIGHASH_ALL) signature = self.coinbase_key.sign(sig_hash) + b'\x01' TxFailure8.vin[0].scriptSig = CScript([signature]) TxFailure8.rehash() test_transaction_acceptance(node, TxFailure8, accepted=False, reason=b'invalid-colorid')