def sc_setup_network(self, split=False): self.sc_nodes = self.sc_setup_nodes() print("Connecting sidechain nodes node0, node1 and node2...") connect_sc_nodes(self.sc_nodes[0], 1) connect_sc_nodes(self.sc_nodes[0], 2) connect_sc_nodes(self.sc_nodes[1], 2) self.sc_sync_all()
def sc_setup_network(self, split=False): self.sc_nodes = self.sc_setup_nodes() #Connect nodes toghether print("Connecting node0, node1 and node2...") connect_sc_nodes( self.sc_nodes[0], 1) #In Scorex, it is just needed to call connect on one of the two connect_sc_nodes(self.sc_nodes[1], 2) connect_sc_nodes(self.sc_nodes[0], 2) self.sc_sync_all()
def run_test(self): mc_node1 = self.nodes[0] mc_node2 = self.nodes[1] sc_node1 = self.sc_nodes[0] sc_node2 = self.sc_nodes[1] # Synchronize mc_node1 and mc_node2 self.sync_all() genesis_sc_block_id = sc_node1.block_best()["result"] # Generate 1 SC block without any MC block info scblock_id0 = generate_next_blocks(sc_node1, "first node", 1)[0] # Verify that SC block has no MC headers, ref data, ommers check_mcheaders_amount(0, scblock_id0, sc_node1) check_mcreferencedata_amount(0, scblock_id0, sc_node1) check_ommers_amount(0, scblock_id0, sc_node1) # Generate 1 MC block on the first MC node mcblock_hash1 = mc_node1.generate(1)[0] # Synchronize mc_node1 and mc_node2, then disconnect them. self.sync_all() disconnect_nodes_bi(self.nodes, 0, 1) # Generate 1 more MC block on the first MC node mcblock_hash2 = mc_node1.generate(1)[0] # Generate 1 SC block, that should put 2 MC blocks inside # SC block contains MC `mcblock_hash1` that is common for MC Nodes 1,2 and `mcblock_hash2` that is known only by MC Node 1. scblock_id1 = generate_next_blocks(sc_node1, "first node", 1)[0] check_scparent(scblock_id0, scblock_id1, sc_node1) # Verify that SC block contains MC block as a MainchainReference check_mcheaders_amount(2, scblock_id1, sc_node1) check_mcreferencedata_amount(2, scblock_id1, sc_node1) check_mcreference_presence(mcblock_hash1, scblock_id1, sc_node1) check_mcreference_presence(mcblock_hash2, scblock_id1, sc_node1) check_ommers_amount(0, scblock_id1, sc_node1) # Generate another 2 MC blocks on the second MC node fork_mcblock_hash1 = mc_node2.generate(1)[0] fork_mcblock_hash2 = mc_node2.generate(1)[0] # Connect and synchronize MC node 1 to MC node 2 connect_nodes_bi(self.nodes, 0, 1) self.sync_all() # MC Node 1 should replace mcblock_hash2 Tip with [fork_mcblock_hash1, fork_mcblock_hash2] assert_equal(fork_mcblock_hash2, mc_node1.getbestblockhash()) # Generate 1 SC block # SC block must contains `mcblock_hash1` again and add fork_mcblock_hash1,2 # Ommered block also contains common `mcblock_hash1`, but moreover an orphaned `mcblock_hash2` scblock_id2 = generate_next_blocks(sc_node1, "first node", 1)[0] check_scparent(scblock_id0, scblock_id2, sc_node1) # Verify that SC block contains newly created MC blocks as a MainchainHeaders and no MainchainRefData check_mcheaders_amount(3, scblock_id2, sc_node1) check_mcreferencedata_amount(0, scblock_id2, sc_node1) check_mcheader_presence(mcblock_hash1, scblock_id2, sc_node1) check_mcheader_presence(fork_mcblock_hash1, scblock_id2, sc_node1) check_mcheader_presence(fork_mcblock_hash2, scblock_id2, sc_node1) # Verify that SC block contains 1 Ommer with 1 MainchainHeader check_ommers_amount(1, scblock_id2, sc_node1) check_ommers_cumulative_score(1, scblock_id2, sc_node1) check_ommer(scblock_id1, [mcblock_hash1, mcblock_hash2], scblock_id2, sc_node1) assert_equal(genesis_sc_block_id, sc_node2.block_best()["result"]) connect_sc_nodes(self.sc_nodes[0], 1) self.sc_sync_all() assert_equal(sc_node1.block_best()["result"], sc_node2.block_best()["result"])
def run_test(self): mc_nodes = self.nodes sc_nodes = self.sc_nodes print "Number of started mc nodes: {0}".format( len(mc_nodes), "The number of MC nodes is not {0}.".format( self.number_of_mc_nodes)) print "Number of started sc nodes: {0}".format( len(sc_nodes), "The number of SC nodes is not {0}.".format( self.number_of_sidechain_nodes)) first_mainchain_node = mc_nodes[0] second_mainchain_node = mc_nodes[1] first_sidechain_node = sc_nodes[0] second_sidechain_node = sc_nodes[1] wallet_balance = self.sc_nodes_bootstrap_info.genesis_account_balance genesis_account = self.sc_nodes_bootstrap_info.genesis_account mainchain_block_height = self.sc_nodes_bootstrap_info.mainchain_block_height first_mainchain_node_block = first_mainchain_node.getblock( str(mainchain_block_height)) # verify genesis information for SC node 1 and 2 # verify the mc block is included inside SC nodes 1 and 2 first_sc_node_best_block = first_sidechain_node.block_best()["result"] second_sc_node_best_block = second_sidechain_node.block_best( )["result"] assert_equal(first_sc_node_best_block["height"], 1, "The best block has not the specified height.") assert_equal(second_sc_node_best_block["height"], 1, "The best block has not the specified height.") sc_1_mc_block_inclusion = is_mainchain_block_included_in_sc_block( first_sc_node_best_block["block"], first_mainchain_node_block) sc_2_mc_block_inclusion = is_mainchain_block_included_in_sc_block( second_sc_node_best_block["block"], first_mainchain_node_block) assert_true(sc_1_mc_block_inclusion, "The mainchain block is not included for SC node 1.") assert_true(sc_2_mc_block_inclusion, "The mainchain block is not included for SC node 2.") first_sc_mc_best_block_ref_info = first_sidechain_node.mainchain_bestBlockReferenceInfo( )["result"] second_sc_mc_best_block_ref_info = second_sidechain_node.mainchain_bestBlockReferenceInfo( )["result"] assert_true( check_mainchain_block_reference_info( first_sc_mc_best_block_ref_info, first_mainchain_node_block), "The mainchain block is not included inside SC block reference info." ) assert_true( check_mainchain_block_reference_info( second_sc_mc_best_block_ref_info, first_mainchain_node_block), "The mainchain block is not included inside SC block reference info." ) check_box_balance(first_sidechain_node, genesis_account, 3, 1, wallet_balance) check_wallet_balance(first_sidechain_node, wallet_balance) # MC 1 mine a new block block_hash = first_mainchain_node.generate(1)[0] first_mainchain_node_new_block = first_mainchain_node.getblock( block_hash) # SC node 1 forges 1 SC block generate_next_blocks(first_sidechain_node, "first node", 1) # verify the block is included inside SC node 1 first_sc_node_best_block = first_sidechain_node.block_best()["result"] second_sc_node_best_block = second_sidechain_node.block_best( )["result"] assert_equal(first_sc_node_best_block["height"], 2, "The best block has not the specified height.") sc_1_mc_block_inclusion = is_mainchain_block_included_in_sc_block( first_sc_node_best_block["block"], first_mainchain_node_new_block) assert_true(sc_1_mc_block_inclusion, "The mainchain block is not included for SC node 1.") # verify the mc block is NOT included inside SC node 2 sc_2_mc_block_inclusion = is_mainchain_block_included_in_sc_block( second_sc_node_best_block["block"], first_mainchain_node_new_block) assert_false(sc_2_mc_block_inclusion, "The mainchain block is included for SC node 2.") first_sc_mc_best_block_ref_info = first_sidechain_node.mainchain_bestBlockReferenceInfo( )["result"] second_sc_mc_best_block_ref_info = second_sidechain_node.mainchain_bestBlockReferenceInfo( )["result"] assert_true( check_mainchain_block_reference_info( first_sc_mc_best_block_ref_info, first_mainchain_node_new_block), "The mainchain block is not included inside SC block reference info." ) assert_false( check_mainchain_block_reference_info( second_sc_mc_best_block_ref_info, first_mainchain_node_new_block), "The mainchain block is not included inside SC block reference info." ) # connect MC 1 to MC 2 connect_nodes_bi(self.nodes, 0, 1) self.sync_all() # connect SC 1 to SC 2 connect_sc_nodes(self.sc_nodes[0], 1) self.sc_sync_all() # verify the block is included inside SC node 2 second_sc_node_best_block = second_sidechain_node.block_best( )["result"] sc_2_mc_block_inclusion = is_mainchain_block_included_in_sc_block( second_sc_node_best_block["block"], first_mainchain_node_new_block) assert_true(sc_2_mc_block_inclusion, "The mainchain block is not included for SC node 2.")
def run_test(self): mc_node = self.nodes[0] sc_node1 = self.sc_nodes[0] sc_node2 = self.sc_nodes[1] # Do FT of 500 Zen to SC Node 1 sc_node1_address = sc_node1.wallet_createPrivateKey25519( )["result"]["proposition"]["publicKey"] sc_node1_account = Account("", sc_node1_address) ft_amount = 500 # Zen mc_node.sc_send(sc_node1_address, ft_amount, self.sc_nodes_bootstrap_info.sidechain_id) assert_equal(1, mc_node.getmempoolinfo()["size"], "Forward Transfer expected to be added to mempool.") # Generate MC block and SC block and check that FT appears in SC node wallet mcblock_hash1 = mc_node.generate(1)[0] scblock_id1 = generate_next_block(sc_node1, "first node") check_mcreference_presence(mcblock_hash1, scblock_id1, sc_node1) # check all keys/boxes/balances are coherent with the default initialization check_wallet_balance( sc_node1, self.sc_nodes_bootstrap_info.genesis_account_balance + ft_amount) check_box_balance(sc_node1, sc_node1_account, 1, 1, ft_amount) # Delegate 300 Zen and 200 Zen to SC node 2 - expected stake is 500 Zen sc_node2_address = sc_node2.wallet_createPrivateKey25519( )["result"]["proposition"]["publicKey"] sc_node2_vrf_address = sc_node2.wallet_createVrfSecret( )["result"]["proposition"]["publicKey"] forgerStake1_amount = 300 # Zen forgerStake2_amount = ft_amount - forgerStake1_amount # Zen forgerStakes = { "outputs": [ { "publicKey": sc_node1_address, # SC node 1 is an owner "blockSignPublicKey": sc_node2_address, # SC node 2 is a block signer "vrfPubKey": sc_node2_vrf_address, "value": forgerStake1_amount * 100000000 # in Satoshi }, { "publicKey": sc_node1_address, # SC node 1 is an owner "blockSignPublicKey": sc_node2_address, # SC node 2 is a block signer "vrfPubKey": sc_node2_vrf_address, "value": forgerStake2_amount * 100000000 # in Satoshi } ] } makeForgerStakeJsonRes = sc_node1.transaction_makeForgerStake( json.dumps(forgerStakes)) if "result" not in makeForgerStakeJsonRes: fail("make forger stake failed: " + json.dumps(makeForgerStakeJsonRes)) else: print("Forget stake created: " + json.dumps(makeForgerStakeJsonRes)) # Generate SC block generate_next_block(sc_node1, "first node") # Sync SC nodes connect_sc_nodes(self.sc_nodes[0], 1) self.sc_sync_all() # Check SC nodes balances # SC node 1 owns ForgerBoxes check_wallet_balance( sc_node1, self.sc_nodes_bootstrap_info.genesis_account_balance + ft_amount) check_box_balance(sc_node1, sc_node1_account, 3, 2, ft_amount) # ForgerBox type = 3 # SC node 2 doesn't own ForgerBoxes check_wallet_balance(sc_node2, 0) # Generate SC block on SC node 1 for the next consensus epoch generate_next_block(sc_node1, "first node", force_switch_to_next_epoch=True) # Generate SC block on SC node 2 for the next consensus epoch scnode2_block_id = generate_next_block(sc_node2, "second node", force_switch_to_next_epoch=True) # Check ForgingStake for SC block res = sc_node2.block_findById(blockId=scnode2_block_id) stakeInfo = res["result"]["block"]["header"]["forgingStakeInfo"] print("SC Node 2 forged block with forging info:\n" + json.dumps(stakeInfo, indent=4)) assert_equal(stakeInfo["stakeAmount"], ft_amount * 100000000, "Forging stake is wrong.") assert_equal(stakeInfo["blockSignPublicKey"]["publicKey"], sc_node2_address, "Forging stake block sign key is wrong.") assert_equal(stakeInfo["vrfPublicKey"]["publicKey"], sc_node2_vrf_address, "Forging stake vrf key is wrong.") # spend forger box of 100 Zen for SC node 1 all_forger_boxes_req = {"boxTypeClass": "ForgerBox"} forger_box_id = sc_node1.wallet_allBoxes( json.dumps(all_forger_boxes_req))["result"]["boxes"][0]["id"] spend_forger_stakes_req = { "transactionInputs": [{ "boxId": forger_box_id }], "regularOutputs": [{ "publicKey": sc_node1_address, "value": self.sc_nodes_bootstrap_info.genesis_account_balance * 100000000 # in Satoshi }], "forgerOutputs": [] } tx_hex = sc_node1.transaction_spendForgingStake( json.dumps(spend_forger_stakes_req)) if "result" not in tx_hex: fail("spend forger stake failed: " + json.dumps(tx_hex)) else: print("Forget stake was spend: " + json.dumps(tx_hex)) # Generate one more SC block on SC node 1 to include transaction generate_next_block(sc_node1, "first node") # Generate SC block on SC node 1 for the next consensus epoch - must be successful generate_next_block(sc_node1, "first node", force_switch_to_next_epoch=True) # Generate SC block on SC node 1 for the next consensus epoch. # Must fail, because of all forger stakes were spent 2 consensus epochs before. exception_occurs = False try: generate_next_block(sc_node1, "first node", force_switch_to_next_epoch=True) except: exception_occurs = True finally: assert_true(exception_occurs, "No forging stakes expected for SC node 1.")