def run_test(self): taddr = self.nodes[1].getnewaddress() zaddr1 = self.nodes[1].z_getnewaddress() zaddr2 = self.nodes[1].z_getnewaddress() self.nodes[0].sendtoaddress(taddr, Decimal('1.0')) self.generate_and_sync() # Send 1 ZEC to a zaddr wait_and_assert_operationid_status(self.nodes[1], self.nodes[1].z_sendmany(taddr, [{'address': zaddr1, 'amount': 1.0, 'memo': 'c0ffee01'}], 1, 0)) self.generate_and_sync() # Check that we have received 1 note which is not change receivedbyaddress = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0) listunspent = self.nodes[1].z_listunspent() assert_equal(1, len(receivedbyaddress), "Should have received 1 note") assert_false(receivedbyaddress[0]['change'], "Note should not be change") assert_equal(1, len(listunspent), "Should have 1 unspent note") assert_false(listunspent[0]['change'], "Unspent note should not be change") # Generate some change wait_and_assert_operationid_status(self.nodes[1], self.nodes[1].z_sendmany(zaddr1, [{'address': zaddr2, 'amount': 0.6, 'memo': 'c0ffee02'}], 1, 0)) self.generate_and_sync() # Check zaddr1 received sortedreceived1 = sorted(self.nodes[1].z_listreceivedbyaddress(zaddr1, 0), key = lambda received: received['amount']) assert_equal(2, len(sortedreceived1), "zaddr1 Should have received 2 notes") assert_equal(Decimal('0.4'), sortedreceived1[0]['amount']) assert_true(sortedreceived1[0]['change'], "Note valued at 0.4 should be change") assert_equal(Decimal('1.0'), sortedreceived1[1]['amount']) assert_false(sortedreceived1[1]['change'], "Note valued at 1.0 should not be change") # Check zaddr2 received sortedreceived2 = sorted(self.nodes[1].z_listreceivedbyaddress(zaddr2, 0), key = lambda received: received['amount']) assert_equal(1, len(sortedreceived2), "zaddr2 Should have received 1 notes") assert_equal(Decimal('0.6'), sortedreceived2[0]['amount']) assert_false(sortedreceived2[0]['change'], "Note valued at 0.6 should not be change") # Check unspent sortedunspent = sorted(self.nodes[1].z_listunspent(), key = lambda received: received['amount']) assert_equal(2, len(sortedunspent), "Should have 2 unspent notes") assert_equal(Decimal('0.4'), sortedunspent[0]['amount']) assert_true(sortedunspent[0]['change'], "Unspent note valued at 0.4 should be change") assert_equal(Decimal('0.6'), sortedunspent[1]['amount']) assert_false(sortedunspent[1]['change'], "Unspent note valued at 0.6 should not be change") # Give node 0 a viewing key viewing_key = self.nodes[1].z_exportviewingkey(zaddr1) self.nodes[0].z_importviewingkey(viewing_key) received_node0 = self.nodes[0].z_listreceivedbyaddress(zaddr1, 0) assert_equal(2, len(received_node0)) unspent_node0 = self.nodes[0].z_listunspent(1, 9999999, True) assert_equal(2, len(unspent_node0)) # node 0 only has a viewing key so does not see the change field assert_false('change' in received_node0[0]) assert_false('change' in received_node0[1]) assert_false('change' in unspent_node0[0]) assert_false('change' in unspent_node0[1])
def run_test(self): # Generate shared state up to the network split logging.info("Generating initial blocks.") self.nodes[0].generate(13) block14 = self.nodes[0].generate(1)[0] logging.info("Syncing network after initial generation...") self.sync_all() # Everyone is still on overwinter logging.info("Checking overwinter block propagation.") assert_equal(self.nodes[0].getbestblockhash(), block14) assert_equal(self.nodes[1].getbestblockhash(), block14) assert_equal(self.nodes[2].getbestblockhash(), block14) logging.info("All nodes are on overwinter.") logging.info("Generating network split...") self.is_network_split = True # generate past the boundary into sapling; this will become the "canonical" branch self.nodes[0].generate(50) expected = self.nodes[0].getbestblockhash() # generate blocks into sapling beyond the maximum rewind length (99 blocks) self.nodes[2].generate(120) self.sync_all() assert_true(expected != self.nodes[2].getbestblockhash(), "Split chains have not diverged!") # Stop the overwinter node to ensure state is flushed to disk. logging.info("Shutting down lagging node...") self.nodes[2].stop() bitcoind_processes[2].wait() # Restart the nodes, reconnect, and sync the network. This succeeds if "-reindex" is passed. logging.info("Reconnecting the network...") # expect an exception; the node will refuse to fully start because its last point of # agreement with the rest of the network was prior to the network upgrade activation assert_start_raises_init_error(2, self.options.tmpdir, HAS_SAPLING, "roll back 120") # restart the node with -reindex to allow the test to complete gracefully, # otherwise the node shutdown call in test cleanup will throw an error since # it can't connect self.nodes[2] = start_node(2, self.options.tmpdir, extra_args=NO_SAPLING + ["-reindex"])
def register_nft_reg_ticket(self, key1, key2): print("== Create the NFT registration ticket ==") self.create_nft_ticket_and_signatures(self.non_mn3, "HIJKLMNOP", "ABCDEFG", self.total_copies) nft_ticket_txid = \ self.nodes[self.top_mns_index0].tickets("register", "nft", self.ticket, json.dumps(self.signatures_dict), self.top_mn_pastelid0, self.passphrase, key1, key2, str(self.storage_fee))["txid"] print(nft_ticket_txid) assert_true(nft_ticket_txid, "No ticket was created") self.__wait_for_ticket_tnx() print(self.nodes[self.top_mns_index0].getblockcount()) return nft_ticket_txid
def run_test(self): ''' This test try to create a SC using the command create_sidechain using invalid parameters and valid parameters. ''' #{"withdrawalEpochLength", "fromaddress", "toaddress", "amount", "minconf", "fee", "customData"}; # network topology: (0)--(1) mark_logs("Node 1 generates 2 block", self.nodes, DEBUG_MODE) self.nodes[1].generate(2) self.sync_all() mark_logs("Node 0 generates 220 block", self.nodes, DEBUG_MODE) self.nodes[0].generate(220) self.sync_all() tx = [] errorString = "" toaddress = "abcdef" #generate wCertVk and constant mcTest = MCTestUtils(self.options.tmpdir, self.options.srcdir) vk = mcTest.generate_params('sc1') constant = generate_random_field_element_hex() # create with wrong key in input #------------------------------------ amount = 12.0 fee = 0.000025 cmdInput = { 'wrong_key': 123, 'toaddress': toaddress, 'amount': amount, 'fee': fee, 'wCertVk': vk } mark_logs("\nNode 1 create SC with wrong key in input", self.nodes, DEBUG_MODE) try: tx = self.nodes[1].create_sidechain(cmdInput) except JSONRPCException, e: errorString = e.error['message'] mark_logs(errorString, self.nodes, DEBUG_MODE) assert_true("wrong_key" in errorString)
def check_migration_status(node, destination_address, migration_state): status = node.z_getmigrationstatus() assert_equal(destination_address, status['destination_address'], "Migration destination address; status=%r" % status) assert_true(migration_state in ALL_MIGRATION_STATES, "Unexpected migration state %r" % migration_state) expected_enabled = migration_state not in [ DISABLED_NO_FUNDS, DISABLED_BEFORE_MIGRATION ] expected_sprout_funds = migration_state in [ DISABLED_BEFORE_MIGRATION, ENABLED_BEFORE_MIGRATION ] positive_unfinalized_amount = migration_state == DURING_MIGRATION positive_finalized_amount = migration_state == AFTER_MIGRATION num_migration_txids = 1 if migration_state in [ DURING_MIGRATION, AFTER_MIGRATION ] else 0 num_finalized_migration_transactions = 1 if migration_state == AFTER_MIGRATION else 0 assert_equal(expected_enabled, status['enabled'], "Expected enabled: %s" % expected_enabled) # During and after the migration there may be no remaining sprout funds if # we have randomly picked to migrate them all at once, so we only check # this field in the one case. if expected_sprout_funds: assert_true( Decimal(status['unmigrated_amount']) > Decimal('0.00'), "Expected sprout funds; status=%r" % (status, )) # For the other two amount fields we know whether or not they will be positive unfinalized_msg = "Positive unfinalized amount: %s; status=%r " % ( positive_unfinalized_amount, status) assert_equal(positive_unfinalized_amount, Decimal(status['unfinalized_migrated_amount']) > Decimal('0'), unfinalized_msg) finalized_msg = "Positive finalized amount: %s; status=%r " % ( positive_finalized_amount, status) assert_equal(positive_finalized_amount, Decimal(status['finalized_migrated_amount']) > Decimal('0'), finalized_msg) assert_equal(num_finalized_migration_transactions, status['finalized_migration_transactions'], "Num finalized transactions; status=%r" % (status, )) assert_equal(num_migration_txids, len(status['migration_txids']), "Num migration txids; status=%r" % (status, ))
def check_peers_info(self, peers_info, quorum_members, is_iqr_conn, inbound=False): for quorum_node in quorum_members: found = False for peer in peers_info: if "verif_mn_proreg_tx_hash" in peer and peer[ "verif_mn_proreg_tx_hash"] == quorum_node.proTx: self.check_peer_info(peer, quorum_node, is_iqr_conn, inbound) found = True break if not found: print(peers_info) assert_true( found, "MN connection not found for ip: " + str(quorum_node.ipport))
def run_test(self): ''' Create a few SCs having the same parameters, advance 2 epochs and then let half of them cease. For the SCs alive send a certificate, for the ceased ones send a csw, then mine a block, which should contain all of cert and csw with related proofs. Restart the network and check DB integrity. ''' #================================================================================ # Modify these params for customizing the test: # ------------------------------------------------------------------------------- # the number of sidechain to be used in the test (min 2) #TOT_NUM_OF_SIDECHAINS = 100 TOT_NUM_OF_SIDECHAINS = 2 # parameters for tuning the complexity (and the size) of the created proofs # These have impacts both in execution times and also on disk space # TO TEST: # SEGMENT_SIZE = 1 << 17 # 1) CERT_NUM_CONSTRAINTS = 1 << 19, CSW_NUM_CONSTRAINTS = 1 << 18; # 2) CERT_NUM_CONSTRAINTS = 1 << 20, CSW_NUM_CONSTRAINTS = 1 << 19; CERT_NUM_CONSTRAINTS = 1 << 13 CSW_NUM_CONSTRAINTS = 1 << 13 # CERT_PROVING_SYSTEM = "darlin" # CSW_PROVING_SYSTEM = "darlin" CERT_PROVING_SYSTEM = "cob_marlin" CSW_PROVING_SYSTEM = "cob_marlin" # Segment size should be at most 2 powers less than number of constraints, otherwise out-of-size vk could be produced SEGMENT_SIZE = 1 << 11 #================================================================================ assert_true(TOT_NUM_OF_SIDECHAINS >= 2) def create_sc(cmdInput, node): try: res = node.sc_create(cmdInput) tx = res['txid'] scid = res['scid'] except JSONRPCException, e: errorString = e.error['message'] mark_logs(errorString, self.nodes, DEBUG_MODE) assert_true(False) return tx, scid
def doTestJustBeforeScFork(self): node = self.nodes[0] tmpl = node.getblocktemplate() if 'coinbasetxn' not in tmpl: rawcoinbase = encodeUNum(tmpl['height']) rawcoinbase += b'\x01-' hexcoinbase = b2x(rawcoinbase) hexoutval = b2x(pack('<Q', tmpl['coinbasevalue'])) tmpl['coinbasetxn'] = { 'data': '01000000' + '01' + '0000000000000000000000000000000000000000000000000000000000000000ffffffff' + ('%02x' % (len(rawcoinbase), )) + hexcoinbase + 'fffffffe' + '01' + hexoutval + '00' + '00000000' } txlist = list( bytearray(a2b_hex(a['data'])) for a in (tmpl['coinbasetxn'], ) + tuple(tmpl['transactions'])) certlist = [] # Test: set a non-zero 'hashReserved' field (32 bytes after mkl tree field); this is used from the sc fork on, renamed as 'scTxsCommitment' rawtmpl = template_to_bytes(tmpl, txlist, certlist) # a 32 null byte array string nb1 = b2x(bytearray(32)) nb2 = b2x(rawtmpl[4 + 32 + 32:4 + 32 + 32 + 32]) # check hashReserved field is currently null assert_true(nb1 == nb2) for j in range(0, 32): rawtmpl[4 + 32 + 32 + j] = j # hashReserved is not null now nb3 = b2x(rawtmpl[4 + 32 + 32:4 + 32 + 32 + 32]) assert_false(nb3 == nb2) rsp = node.getblocktemplate({'data': b2x(rawtmpl), 'mode': 'proposal'}) # assert block validity assert_equal(rsp, None)
def fake_nftsell_tnx_tests1(self): print( "== NFT Sell ticket transaction validation test (for activation ticket) ==" ) self.nodes[self.mining_node_num].sendtoaddress(self.nonmn3_address1, 200, "", "", False) time.sleep(2) self.sync_all(10, 30) self.nodes[self.mining_node_num].generate(1) self.sync_all(10, 30) self.nft_ticket1_act_ticket_txid = self.nodes[self.non_mn3].tickets( "register", "act", self.nft_ticket1_txid, str(self.creator_ticket_height), str(self.storage_fee), self.creator_pastelid1, "passphrase")["txid"] assert_true(self.nft_ticket1_act_ticket_txid, "No ticket was created") tickets = { # 1. check PastelID in this ticket matches PastelID in the referred Activation ticket "sell-bad-nfts-sign": self.nodes[self.non_mn3].tickets( "makefaketicket", "sell", self.nft_ticket1_act_ticket_txid, "100000", self.creator_pastelid1, "passphrase", "0", "0", "10", "1" ), # Verb = 1 - will modify Act ticket signature to make it invalid (non matchig creator's PastelID) } # sync mempools self.sync_all() for n, t in tickets.items(): try: self.nodes[0].sendrawtransaction(t) except JSONRPCException as e: self.errorString = e.error['message'] print(n + ": " + self.errorString) assert_equal("bad-tx-invalid-ticket" in self.errorString, True) print( "== NFT Sell ticket transaction validation tested (for activation ticket) ==" )
def advance_sidechains_epoch(num_of_scs): for i in range(0, num_of_scs): if i == 0: self.nodes[0].generate(EPOCH_LENGTH) self.sync_all() # these parameters are valid for all scs since they share the same epoch length epoch_number, epoch_cum_tree_hash = get_epoch_data( scids[i], self.nodes[0], EPOCH_LENGTH) print "Generating cert proof..." t0 = time.time() scid_swapped = str(swap_bytes(scids[i])) proof = certMcTest.create_test_proof( "scs", scid_swapped, epoch_number, q, MBTR_SC_FEE, FT_SC_FEE, epoch_cum_tree_hash, constant, [], [], proofCfeArray, CERT_NUM_CONSTRAINTS, SEGMENT_SIZE) assert_true(proof != None) t1 = time.time() print "...proof generated: {} secs".format(t1 - t0) try: cert = self.nodes[0].sc_send_certificate( scids[i], epoch_number, q, epoch_cum_tree_hash, proof, [], FT_SC_FEE, MBTR_SC_FEE, CERT_FEE, "", vCfe, vCmt) except JSONRPCException, e: errorString = e.error['message'] print "Send certificate failed with reason {}".format( errorString) assert (False) self.sync_all() mark_logs( "==> certificate for SC{} epoch {} {} (chain height={})". format(i, epoch_number, cert, self.nodes[0].getblockcount()), self.nodes, DEBUG_MODE)
def check_genesis_balances(self, node, nodename, expected_keys_count, expected_boxes_count): print("Genesis checks for {0}...".format(nodename)) print( "-->Checking that each public key has a box assigned with a non-zero value... " ) responce = node.wallet_allPublicKeys() public_keys = responce["result"]["propositions"] responce = node.wallet_allBoxes() boxes = responce["result"]["boxes"] responce = node.wallet_balance() balance = responce["result"] assert_equal(expected_keys_count, len(public_keys), "Unexpected number of public keys") assert_equal(expected_boxes_count, len(boxes), "Unexpected number of boxes") for key in public_keys: target = None for box in boxes: if box["proposition"]["publicKey"] == key["publicKey"]: target = box assert_true( box["value"] > 0, "Non positive value for box: {0} with public key: {1}". format(box["id"], key)) break assert_true(target is not None, "Box related to public key: {0} not found".format(key)) print("-->Checking genesis balance...") assert_equal(10000000000, int(balance["balance"]), "Unexpected balance") print("-->Total balance: {0}".format(json.dumps(balance["balance"]))) print("OK\n")
def run_test(self): ''' Test verifying the fix of some corner cases in the implementation of cbh ''' TARGET_H = 3 FEE = Decimal('0.00005') self.mark_logs("Node1 generates %d blocks" % (CBH_DELTA_HEIGHT + TARGET_H)) self.nodes[1].generate(CBH_DELTA_HEIGHT + TARGET_H) self.sync_all() # create a Tx having a '-1' as height and genesys blockhash in its scriptPubKey CHECKBLOCKATHEIGHT part payment_1 = Decimal('10.0') raw_tx_1 = create_tampered_rawtx_cbh(self.nodes[1], self.nodes[2], payment_1, FEE, MODE_HEIGHT) try: self.mark_logs( "Node1 sending tx1 with tampered cbh script to Node2") tx_1 = self.nodes[1].sendrawtransaction(raw_tx_1['hex']) self.sync_all() except JSONRPCException, e: print " ==> Tx has been rejected! {}".format(e.error['message']) # before rp fix fork this is expected to succeed assert_true(False)
def check_change_taddr_reuse(target, isTargetShielded): recipients = [{"address": target, "amount": Decimal('1')}] # Send funds to recipient address twice txid1 = self.nodes[0].shieldsendmany(taddrSource, recipients, 1) self.nodes[1].generate(1) self.sync_all() txid2 = self.nodes[0].shieldsendmany(taddrSource, recipients, 1) self.nodes[1].generate(1) self.sync_all() # Verify that the two transactions used different change addresses tx1 = self.nodes[0].getrawtransaction(txid1, 1) tx2 = self.nodes[0].getrawtransaction(txid2, 1) assert_true(len(tx1['vout']) >= 1) # at least one output assert_true(len(tx2['vout']) >= 1) for i in range(len(tx1['vout'])): tx1OutAddrs = tx1['vout'][i]['scriptPubKey']['addresses'] tx2OutAddrs = tx2['vout'][i]['scriptPubKey']['addresses'] if tx1OutAddrs != [target]: print('Source address: %s' % taddrSource) print('TX1 change address: %s' % tx1OutAddrs[0]) print('TX2 change address: %s' % tx2OutAddrs[0]) assert (tx1OutAddrs != tx2OutAddrs)
def run_test(self): print "Mining blocks..." self.nodes[0].generate(101) offline_node = start_node(1, self.options.tmpdir, ["-maxconnections=0", "-nuparams=5ba81b19:10"]) self.nodes.append(offline_node) assert_equal(0, len(offline_node.getpeerinfo())) # make sure node 1 has no peers privkeys = [self.nodes[0].dumpprivkey(self.nodes[0].getnewaddress())] taddr = self.nodes[0].getnewaddress() tx = self.nodes[0].listunspent()[0] txid = tx['txid'] scriptpubkey = tx['scriptPubKey'] create_inputs = [{'txid': txid, 'vout': 0}] sign_inputs = [{'txid': txid, 'vout': 0, 'scriptPubKey': scriptpubkey, 'amount': 10}] create_hex = self.nodes[0].createrawtransaction(create_inputs, {taddr: 9.9999}) # An offline regtest node does not rely on the approx release height of the software # to determine the consensus rules to be used for signing. try: signed_tx = offline_node.signrawtransaction(create_hex, sign_inputs, privkeys) self.nodes[0].sendrawtransaction(signed_tx['hex']) assert(False) except JSONRPCException: pass # Passing in the consensus branch id resolves the issue for offline regtest nodes. signed_tx = offline_node.signrawtransaction(create_hex, sign_inputs, privkeys, "ALL", "5ba81b19") # If we return the transaction hash, then we have have not thrown an error (success) online_tx_hash = self.nodes[0].sendrawtransaction(signed_tx['hex']) assert_true(len(online_tx_hash) > 0)
def parse_wallet_file(dump_path): file_lines = open(dump_path, "r", encoding="utf8").readlines() # We expect information about the HDSeed and fingerpring in the header assert_true("HDSeed" in file_lines[4], "Expected HDSeed") assert_true("fingerprint" in file_lines[4], "Expected fingerprint") seed_comment_line = file_lines[4][2:].split() # ["HDSeed=...", "fingerprint=..."] assert_true(seed_comment_line[0].split("=")[1] != seed_comment_line[1].split("=")[1], "The seed should not equal the fingerprint") (t_keys, i) = parse_wallet_file_lines(file_lines, 0) (sapling_keys, i) = parse_wallet_file_lines(file_lines, i) return (t_keys, sapling_keys)
def parse_wallet_file(dump_path): file_lines = open(dump_path, "r").readlines() # We expect information about the HDSeed and fingerpring in the header assert_true("HDSeed" in file_lines[4], "Expected HDSeed") assert_true("fingerprint" in file_lines[4], "Expected fingerprint") seed_comment_line = file_lines[4][2:].split() # ["HDSeed=...", "fingerprint=..."] assert_true(seed_comment_line[0].split("=")[1] != seed_comment_line[1].split("=")[1], "The seed should not equal the fingerprint") (t_keys, i) = parse_wallet_file_lines(file_lines, 0) (sprout_keys, i) = parse_wallet_file_lines(file_lines, i) (sapling_keys, i) = parse_wallet_file_lines(file_lines, i) return (t_keys, sprout_keys, sapling_keys)
def parse_wallet_file(dump_path): file_lines = open(dump_path, "r", encoding="utf8").readlines() # We expect information about the HDSeed and fingerpring in the header assert_true("recovery_phrase" in file_lines[5], "Expected emergency recovery phrase") assert_true("language" in file_lines[6], "Expected mnemonic seed language") assert_true("fingerprint" in file_lines[7], "Expected mnemonic seed fingerprint") mnemonic = file_lines[5].split("=")[1].replace("\"", "").strip() (t_keys, i) = parse_wallet_file_lines(file_lines, 0) (sprout_keys, i) = parse_wallet_file_lines(file_lines, i) (sapling_keys, i) = parse_wallet_file_lines(file_lines, i) return (mnemonic, t_keys, sprout_keys, sapling_keys)
def run_test_release(self, release, height): self.generate_and_sync(height + 1) taddr = self.nodes[1].getnewaddress() zaddr1 = self.nodes[1].z_getnewaddress(release) self.nodes[0].sendtoaddress(taddr, 2.0) self.generate_and_sync(height + 2) # Send 1 BLV to zaddr1 opid = self.nodes[1].z_sendmany(taddr, [{ 'address': zaddr1, 'amount': 1, 'memo': my_memo }]) txid = wait_and_assert_operationid_status(self.nodes[1], opid) self.sync_all() r = self.nodes[1].z_listreceivedbyaddress(zaddr1) assert_equal(0, len(r), "Should have received no confirmed note") # No confirmation required, one note should be present r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0) assert_equal(1, len(r), "Should have received one (unconfirmed) note") assert_equal(txid, r[0]['txid']) assert_equal(1, r[0]['amount']) assert_false(r[0]['change'], "Note should not be change") assert_equal(my_memo, r[0]['memo']) # Confirm transaction (1 BLV from taddr to zaddr1) self.generate_and_sync(height + 3) # Require one confirmation, note should be present assert_equal(r, self.nodes[1].z_listreceivedbyaddress(zaddr1)) # Generate some change by sending part of zaddr1 to zaddr2 zaddr2 = self.nodes[1].z_getnewaddress(release) opid = self.nodes[1].z_sendmany(zaddr1, [{ 'address': zaddr2, 'amount': 0.6 }]) txid = wait_and_assert_operationid_status(self.nodes[1], opid) self.sync_all() self.generate_and_sync(height + 4) # zaddr1 should have a note with change r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0) r = sorted(r, key=lambda received: received['amount']) assert_equal(2, len(r), "zaddr1 Should have received 2 notes") assert_equal(txid, r[0]['txid']) assert_equal(Decimal('0.4') - fee, r[0]['amount']) assert_true(r[0]['change'], "Note valued at (0.4-fee) should be change") assert_equal(no_memo, r[0]['memo']) # The old note still exists (it's immutable), even though it is spent assert_equal(Decimal('1.0'), r[1]['amount']) assert_false(r[1]['change'], "Note valued at 1.0 should not be change") assert_equal(my_memo, r[1]['memo']) # zaddr2 should not have change r = self.nodes[1].z_listreceivedbyaddress(zaddr2, 0) r = sorted(r, key=lambda received: received['amount']) assert_equal(1, len(r), "zaddr2 Should have received 1 notes") assert_equal(txid, r[0]['txid']) assert_equal(Decimal('0.6'), r[0]['amount']) assert_false(r[0]['change'], "Note valued at 0.6 should not be change") assert_equal(no_memo, r[0]['memo'])
def validate_full_tx(self,endpoint,decodedTx,tx,shielded = False): if (endpoint['version'] == -5): assert_equal(endpoint['cert'],decodedTx['cert']) assert_equal(endpoint['blockheight'],self.nodes[0].getblock(endpoint['blockhash'])['height']) assert_equal(endpoint['confirmations'],tx['confirmations']) assert_equal(endpoint['blocktime'],tx['blocktime']) assert_equal(endpoint['txid'],decodedTx['txid']) assert_equal(endpoint['version'],decodedTx['version']) assert_equal(endpoint['blockhash'],tx['blockhash']) if('isCoinBase' in endpoint and endpoint['isCoinBase'] == True): assert_equal(len(endpoint['vin']),1) assert_equal(endpoint['vin'][0]['coinbase'],decodedTx['vin'][0]['coinbase']) assert_equal(endpoint['vin'][0]['sequence'],decodedTx['vin'][0]['sequence']) assert_equal(endpoint['vin'][0]['n'],0) else: assert_equal(len(endpoint['vin']),len(decodedTx['vin'])) valueIn = 0 for endpointVin in endpoint['vin']: decodedVin = None for vin in decodedTx['vin']: if(vin['txid'] == endpointVin['txid'] and vin['vout'] == endpointVin['vout']): decodedVin = vin break; assert_equal(endpointVin['txid'],decodedVin['txid']) assert_equal(endpointVin['vout'],decodedVin['vout']) assert_equal(endpointVin['sequence'],decodedVin['sequence']) previousTx = self.nodes[0].gettransaction(endpointVin['txid']) decodedPreviousTx = self.nodes[0].decoderawtransaction(previousTx['hex']) previousUtxo = decodedPreviousTx['vout'][endpointVin['vout']] assert_equal(round(Decimal(endpointVin['value']),8),round(Decimal(previousUtxo['value']),8)) assert_equal(endpointVin['valueSat'],previousUtxo['valueZat']) assert_equal(endpointVin['addr'],previousUtxo['scriptPubKey']['addresses'][0]) assert_equal(endpointVin['scriptSig']['hex'],decodedVin['scriptSig']['hex']) assert_equal(endpointVin['scriptSig']['asm'],decodedVin['scriptSig']['asm']) valueIn += endpointVin['value'] assert_equal(str(endpoint['valueIn']),str(valueIn)) if(not shielded): assert_equal("{:.8f}".format(float(endpoint['fees'])),"{:.8f}".format(float(abs(tx['fee'])))) assert_equal(len(endpoint['vout']),len(decodedTx['vout'])) valueOut = 0 for i in range (0,len(endpoint['vout'])): assert_equal(round(Decimal(endpoint['vout'][i]['value']),8),round(Decimal(decodedTx['vout'][i]['value']),8)) assert_equal(endpoint['vout'][i]['n'],decodedTx['vout'][i]['n']) assert_equal(endpoint['vout'][i]['scriptPubKey']['hex'],decodedTx['vout'][i]['scriptPubKey']['hex']) assert_equal(endpoint['vout'][i]['scriptPubKey']['addresses'],decodedTx['vout'][i]['scriptPubKey']['addresses']) #The explorer doesn't distinguish from pubkeyhash and pubkeyhashreplay if (endpoint['vout'][i]['scriptPubKey']['type'] == "pubkeyhash"): assert_true( (decodedTx['vout'][i]['scriptPubKey']['type'] == "pubkeyhashreplay") or (decodedTx['vout'][i]['scriptPubKey']['type'] == "pubkeyhash")) #The explorer doesn't distinguish from scripthash and scripthashreplay if (endpoint['vout'][i]['scriptPubKey']['type'] == "scripthash"): assert_true( (decodedTx['vout'][i]['scriptPubKey']['type'] == "scripthashreplay") or (decodedTx['vout'][i]['scriptPubKey']['type'] == "scripthash")) if('asm' in endpoint['vout'][i]['scriptPubKey']): assert_equal(endpoint['vout'][i]['scriptPubKey']['asm'],decodedTx['vout'][i]['scriptPubKey']['asm']) valueOut += float(endpoint['vout'][i]['value']) assert_equal(round(Decimal(endpoint['valueOut']),8),round(Decimal(valueOut),8)) #assert_equal(endpoint['time'],tx['blocktime']) TODO: add tollerance in the check #if(not shielded): Wait fix on zendoo #assert_equal(endpoint['size'],tx['details'][0]['size']) #Check joinsplit if(endpoint['version'] == -3): assert_equal(len(endpoint['vjoinsplit']),len(decodedTx['vjoinsplit'])) for i in range (0,len(endpoint['vjoinsplit'])): assert_equal(round(Decimal(endpoint['vjoinsplit'][i]['vpub_old']),8),round(Decimal(decodedTx['vjoinsplit'][i]['vpub_old']),8)) assert_equal(round(Decimal(endpoint['vjoinsplit'][i]['vpub_new']),8),round(Decimal(decodedTx['vjoinsplit'][i]['vpub_new']),8)) assert_equal(endpoint['vjoinsplit'][i]['n'],i) #Check sc_params if(decodedTx['version'] == -4): #Vsc_ccout assert_equal(len(endpoint['vsc_ccout']),len(decodedTx['vsc_ccout'])) for i in range (0,len(endpoint['vsc_ccout'])): assert_equal(endpoint['vsc_ccout'][i]['scid'],decodedTx['vsc_ccout'][i]['scid']) assert_equal(endpoint['vsc_ccout'][i]['withdrawalEpochLength'],decodedTx['vsc_ccout'][i]['withdrawalEpochLength']) assert_equal(endpoint['vsc_ccout'][i]['n'],decodedTx['vsc_ccout'][i]['n']) assert_equal(endpoint['vsc_ccout'][i]['address'],decodedTx['vsc_ccout'][i]['address']) assert_equal(endpoint['vsc_ccout'][i]['customData'],decodedTx['vsc_ccout'][i]['customData']) assert_equal(endpoint['vsc_ccout'][i]['version'],decodedTx['vsc_ccout'][i]['version']) #Vft_ccout assert_equal(len(endpoint['vft_ccout']),len(decodedTx['vft_ccout'])) for i in range (0,len(endpoint['vft_ccout'])): assert_equal(endpoint['vft_ccout'][i]['scid'],decodedTx['vft_ccout'][i]['scid']) assert_equal(round(Decimal(endpoint['vft_ccout'][i]['value']),8),round(Decimal(decodedTx['vft_ccout'][i]['value']),8)) assert_equal(endpoint['vft_ccout'][i]['address'],decodedTx['vft_ccout'][i]['address']) assert_equal(endpoint['vft_ccout'][i]['n'],decodedTx['vft_ccout'][i]['n']) #Vmbtr_out assert_equal(len(endpoint['vmbtr_out']),len(decodedTx['vmbtr_out'])) for i in range (0,len(endpoint['vmbtr_out'])): assert_equal(endpoint['vmbtr_out'][i]['scid'],decodedTx['vmbtr_out'][i]['scid']) #assert_equal(endpoint['vmbtr_out'][i]['mcDestinationAddress']['pubkeyhash'],decodedTx['vmbtr_out'][i]['mcDestinationAddress']) assert_equal(endpoint['vmbtr_out'][i]['mcDestinationAddress'],decodedTx['vmbtr_out'][i]['mcDestinationAddress']) assert_equal(endpoint['vmbtr_out'][i]['n'],decodedTx['vmbtr_out'][i]['n']) assert_equal(round(Decimal(endpoint['vmbtr_out'][i]['scFee']),8),round(Decimal(decodedTx['vmbtr_out'][i]['scFee']),8)) assert_equal(len(endpoint['vmbtr_out'][i]['vScRequestData']),len(decodedTx['vmbtr_out'][i]['vScRequestData'])) #Vcsw_ccin assert_equal(len(endpoint['vcsw_ccin']),len(decodedTx['vcsw_ccin'])) for i in range (0,len(endpoint['vcsw_ccin'])): assert_equal(endpoint['vcsw_ccin'][i]['scId'],decodedTx['vcsw_ccin'][i]['scId']) assert_equal(round(Decimal(endpoint['vcsw_ccin'][i]['value']),8),round(Decimal(decodedTx['vcsw_ccin'][i]['value']),8)) assert_equal(endpoint['vcsw_ccin'][i]['nullifier'],decodedTx['vcsw_ccin'][i]['nullifier']) assert_equal(endpoint['vcsw_ccin'][i]['actCertDataHash'],decodedTx['vcsw_ccin'][i]['actCertDataHash']) assert_equal(endpoint['vcsw_ccin'][i]['ceasingCumScTxCommTree'],decodedTx['vcsw_ccin'][i]['ceasingCumScTxCommTree']) assert_equal(endpoint['vcsw_ccin'][i]['redeemScript']['hex'],decodedTx['vcsw_ccin'][i]['redeemScript']['hex']) assert_equal(endpoint['vcsw_ccin'][i]['redeemScript']['asm'],decodedTx['vcsw_ccin'][i]['redeemScript']['asm']) assert_equal(endpoint['vcsw_ccin'][i]['scriptPubKey'],decodedTx['vcsw_ccin'][i]['scriptPubKey']) return None
def run_test(self): #Give time to explorer to start self.nodes[0].generate(MINIMAL_SC_HEIGHT) self.sync_all() time.sleep(35) self.nodes[0].getnewaddress() tAddr = self.nodes[0].getnewaddress() tAddr2 = self.nodes[0].getnewaddress() zAddr = self.nodes[0].z_getnewaddress() zAddr2 = self.nodes[1].z_getnewaddress() ############################################################################################################################# #### /tx/:txid #### print("######## /tx/:txid ########") #Test coinbase-transaction coinbaseTxId = self.nodes[0].getblock("100")['tx'][0] coinbaseTx = self.nodes[0].gettransaction(coinbaseTxId) decodedCoinbaseTx = self.nodes[0].decoderawtransaction(coinbaseTx['hex']) r = requests.get(url = self.BASE_URL+"block/"+self.nodes[0].getblock("400")['hash'], params = {}) data = r.json() r = requests.get(url = self.BASE_URL+"tx/"+coinbaseTxId, params = {}) data = r.json() self.validate_full_tx(data,decodedCoinbaseTx,coinbaseTx) #Test t-transaction tTxId = self.nodes[0].sendtoaddress(tAddr,10.0001) self.sync_all() self.nodes[0].generate(2) self.sync_all() time.sleep(5) transparentTx = self.nodes[0].gettransaction(tTxId) decodedTransparentTx = self.nodes[0].decoderawtransaction(transparentTx['hex']) r = requests.get(url = self.BASE_URL+"tx/"+tTxId, params = {}) data = r.json() self.validate_full_tx(data,decodedTransparentTx, transparentTx) ''' #This parameter doesn't work on this version of the explorer #Test noAsm parameter r = requests.get(url = self.BASE_URL+"tx/"+tTxId+"?noAsm=true", params = {}) data = r.json() print(data) for output in data['vout']: assert_false('asm' in output['scriptPubKey']) ''' #Test z-transaction t->z myopid = self.nodes[0].z_sendmany(tAddr,[{"address":zAddr,"amount":4.0},{"address":zAddr2,"amount":6.0}]) zTxid = wait_and_assert_operationid_status(self.nodes[0],myopid) self.sync_all() self.nodes[0].generate(1) self.sync_all() assert_equal(self.nodes[0].z_getbalance(zAddr),4) assert_equal(self.nodes[1].z_getbalance(zAddr2),6) shieldTx = self.nodes[0].gettransaction(zTxid) decodedShieldTx = self.nodes[0].decoderawtransaction(shieldTx['hex']) r = requests.get(url = self.BASE_URL+"tx/"+zTxid, params = {}) data = r.json() self.validate_full_tx(data,decodedShieldTx,shieldTx) #Test z-transaction z->z myopid = self.nodes[0].z_sendmany(zAddr,[{"address":zAddr2,"amount":3.0}]) zTxid2 = wait_and_assert_operationid_status(self.nodes[0],myopid) self.sync_all() self.nodes[0].generate(1) self.sync_all() shieldTx = self.nodes[0].gettransaction(zTxid2) decodedShieldTx = self.nodes[0].decoderawtransaction(shieldTx['hex']) r = requests.get(url = self.BASE_URL+"tx/"+zTxid2, params = {}) data = r.json() self.validate_full_tx(data,decodedShieldTx,shieldTx,True) #Test multiple sidechain creation txId = self.nodes[0].sendtoaddress(tAddr2,20.0) self.sync_all() self.nodes[0].generate(1) self.sync_all() tx = self.nodes[0].gettransaction(txId) rawtx = self.nodes[0].decoderawtransaction(tx['hex']) vout = {} for outpoint in rawtx['vout']: if (outpoint['value'] == Decimal('20.0')): vout = outpoint break sc_address = "0000000000000000000000000000000000000000000000000000000000000abc" sc_address2 = "0000000000000000000000000000000000000000000000000000000000000acb" sc_epoch = 100 sc_cr_amount = Decimal('5.00000000') #generate wCertVk and constant mcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir) cswMcTest = CSWTestUtils(self.options.tmpdir, self.options.srcdir) vk = mcTest.generate_params("sc1") constant = generate_random_field_element_hex() vk2 = mcTest.generate_params("sc2") cswVk = cswMcTest.generate_params("sc1") cswVk2 = cswMcTest.generate_params("sc2") sc = [{"epoch_length": sc_epoch, "address": sc_address, "amount": sc_cr_amount,"wCertVk": vk, "constant": constant, "mainchainBackwardTransferScFee": MBTR_SC_FEE, "mainchainBackwardTransferRequestDataLength": 1, "wCeasedVk": cswVk, "version":1}, {"epoch_length": sc_epoch, "address": sc_address2, "amount": sc_cr_amount, "wCertVk": vk2, "constant": constant, "mainchainBackwardTransferScFee": MBTR_SC_FEE, "mainchainBackwardTransferRequestDataLength": 1, "wCeasedVk": cswVk2, "version":1}] inputs = [{'txid': txId, 'vout': vout['n']}] rawtx = self.nodes[0].createrawtransaction(inputs, {tAddr2: 10.0}, [], sc, []) sigRawtx = self.nodes[0].signrawtransaction(rawtx) scTxid = self.nodes[0].sendrawtransaction(sigRawtx['hex']) self.sync_all() time.sleep(2) self.nodes[0].generate(1) self.sync_all() time.sleep(2) scTx = self.nodes[0].gettransaction(scTxid) scid = scTx['vsc_ccout'][0]['scid'] scid2 = scTx['vsc_ccout'][1]['scid'] assert_equal(len(self.nodes[0].getscinfo("*")['items']),2) decodedScTx = self.nodes[0].decoderawtransaction(scTx['hex']) r = requests.get(url = self.BASE_URL+"tx/"+scTxid, params = {}) data = r.json() self.validate_full_tx(data,decodedScTx,scTx) #Test with multiple forward transfers rawtx = self.nodes[0].decoderawtransaction(scTx['hex']) vout = {} for outpoint in rawtx['vout']: if (outpoint['value'] == Decimal('10.0')): vout = outpoint break mcReturnAddress = self.nodes[0].getnewaddress() ft = [{"address": sc_address, "amount": sc_cr_amount, "scid": scid, "mcReturnAddress": mcReturnAddress}, {"address": sc_address2, "amount": sc_cr_amount, "scid": scid2, "mcReturnAddress": mcReturnAddress}] inputs = [{'txid': scTxid, 'vout': vout['n']}] rawtx = self.nodes[0].createrawtransaction(inputs, {}, [], [], ft) sigRawtx = self.nodes[0].signrawtransaction(rawtx) ftTxid = self.nodes[0].sendrawtransaction(sigRawtx['hex']) self.sync_all() self.nodes[0].generate(1) self.sync_all() ftTx = self.nodes[0].gettransaction(ftTxid) decodedFtTx = self.nodes[0].decoderawtransaction(ftTx['hex']) r = requests.get(url = self.BASE_URL+"tx/"+ftTxid, params = {}) data = r.json() self.validate_full_tx(data,decodedFtTx,ftTx) #Test with BackwardTransferRequest bwtr_address = self.nodes[0].getnewaddress() btwr_txid=self.nodes[0].sc_request_transfer([ {'mcDestinationAddress': bwtr_address, 'vScRequestData': [generate_random_field_element_hex()], 'scid': scid, 'scFee': Decimal('1.0')}, {'mcDestinationAddress': bwtr_address, 'vScRequestData': [generate_random_field_element_hex()], 'scid': scid2, 'scFee': Decimal('1.0')} ]) self.sync_all() time.sleep(1) self.nodes[0].generate(1) self.sync_all() time.sleep(2) bwtrTx = self.nodes[0].gettransaction(btwr_txid) decodedBwtrTx = self.nodes[0].decoderawtransaction(bwtrTx['hex']) r = requests.get(url = self.BASE_URL+"tx/"+btwr_txid, params = {}) data = r.json() self.validate_full_tx(data,decodedBwtrTx,bwtrTx) #Test with a immature certificate self.nodes[0].generate(sc_epoch) self.sync_all() time.sleep(5) #Mine Certificate 1 with quality = 5 epoch_number, epoch_cum_tree_hash = get_epoch_data(scid, self.nodes[0], sc_epoch) quality = 5 pkh_node1 = self.nodes[1].getnewaddress() bwt_amount = Decimal('3.0') proof = mcTest.create_test_proof( "sc1", swap_bytes(scid), epoch_number, quality, MBTR_SC_FEE, FT_SC_FEE, epoch_cum_tree_hash, constant, [pkh_node1], [bwt_amount]) amount_cert_1 = [{"address": pkh_node1, "amount": bwt_amount}] cert1 = self.nodes[0].sc_send_certificate(scid, epoch_number, quality, epoch_cum_tree_hash, proof, amount_cert_1, FT_SC_FEE, MBTR_SC_FEE, CERT_FEE) self.sync_all() cert1_block = self.nodes[0].generate(1)[0] self.sync_all() time.sleep(2) r = requests.get(url = self.BASE_URL+"tx/"+cert1+"?showImmatureBTs=1", params = {}) data = r.json() certTx = self.nodes[0].gettransaction(cert1) decodedCertTx = self.nodes[0].decoderawtransaction(certTx['hex']) certInfo = self.nodes[0].getcertmaturityinfo(cert1) self.validate_full_tx(data, decodedCertTx, certTx) self.validate_certificate(data, certInfo, True) r = requests.get(url = self.BASE_URL+"tx/"+cert1+"?showImmatureBTs=0", params = {}) data = r.json() self.validate_certificate(data, certInfo, False) r = requests.get(url = self.BASE_URL+"tx/"+cert1, params = {}) data = r.json() self.validate_certificate(data, certInfo, False) #Test also the /txs endpoint with blockhash r = requests.get(url = self.BASE_URL+"txs?block="+cert1_block+"&showImmatureBTs=1", params = {}) data = r.json() assert_equal(len(data['txs']), 2) self.validate_certificate(data['txs'][1], certInfo, True) r = requests.get(url = self.BASE_URL+"txs?block="+cert1_block+"&showImmatureBTs=0", params = {}) data = r.json() assert_equal(len(data['txs']), 2) self.validate_certificate(data['txs'][1], certInfo, False) r = requests.get(url = self.BASE_URL+"txs?block="+cert1_block, params = {}) data = r.json() assert_equal(len(data['txs']), 2) self.validate_certificate(data['txs'][1], certInfo, False) #Test also the /txs endpoint with address r = requests.get(url = self.BASE_URL+"txs?address="+pkh_node1+"&showImmatureBTs=1", params = {}) data = r.json() found = False for tx in data['txs']: if (tx['version'] == -5): assert_false(found) found = True self.validate_certificate(tx, certInfo, True) assert_true(found) found = False r = requests.get(url = self.BASE_URL+"txs?address="+pkh_node1+"&showImmatureBTs=0", params = {}) data = r.json() for tx in data['txs']: if (tx['version'] == -5): assert_false(found) found = True self.validate_certificate(tx, certInfo, True) assert_true(found) found = False r = requests.get(url = self.BASE_URL+"txs?address="+pkh_node1, params = {}) data = r.json() for tx in data['txs']: if (tx['version'] == -5): assert_false(found) found = True self.validate_certificate(tx, certInfo, True) assert_true(found) #Advance of 1 epoch self.nodes[0].generate(110) self.sync_all() #Create a block with 2 certificates (one will be superseded) that let mature the certificate of the previous epoch quality = 7 epoch_number, epoch_cum_tree_hash = get_epoch_data(scid, self.nodes[0], sc_epoch) proof = mcTest.create_test_proof( "sc1", str(swap_bytes(scid)), epoch_number, quality, MBTR_SC_FEE, FT_SC_FEE, epoch_cum_tree_hash, constant, [pkh_node1], [bwt_amount]) amount_cert_2 = [{"address": pkh_node1, "amount": bwt_amount}] cert2 = self.nodes[0].sc_send_certificate(scid, epoch_number, quality, epoch_cum_tree_hash, proof, amount_cert_2, FT_SC_FEE, MBTR_SC_FEE, CERT_FEE) self.sync_all() quality = 9 proof = mcTest.create_test_proof( "sc1", str(swap_bytes(scid)), epoch_number, quality, MBTR_SC_FEE, FT_SC_FEE, epoch_cum_tree_hash, constant, [pkh_node1], [bwt_amount]) cert3 = self.nodes[0].sc_send_certificate(scid, epoch_number, quality, epoch_cum_tree_hash, proof, amount_cert_2, FT_SC_FEE, MBTR_SC_FEE, CERT_FEE) cert2_3_block = self.nodes[0].generate(30)[0] self.sync_all() time.sleep(2) #Test that the first certificate became mature certInfo = self.nodes[0].getcertmaturityinfo(cert1) r = requests.get(url = self.BASE_URL+"tx/"+cert1+"?showImmatureBTs=1", params = {}) data = r.json() self.validate_certificate(data, certInfo, True) r = requests.get(url = self.BASE_URL+"tx/"+cert1+"?showImmatureBTs=0", params = {}) data = r.json() self.validate_certificate(data, certInfo, True) r = requests.get(url = self.BASE_URL+"tx/"+cert1, params = {}) data = r.json() self.validate_certificate(data, certInfo, True) #Test also the /txs endpoint with blockhash r = requests.get(url = self.BASE_URL+"txs?block="+cert1_block+"&showImmatureBTs=1", params = {}) data = r.json() assert_equal(len(data['txs']), 2) self.validate_certificate(data['txs'][1], certInfo, True) r = requests.get(url = self.BASE_URL+"txs?block="+cert1_block+"&showImmatureBTs=0", params = {}) data = r.json() assert_equal(len(data['txs']), 2) self.validate_certificate(data['txs'][1], certInfo, True) r = requests.get(url = self.BASE_URL+"txs?block="+cert1_block, params = {}) data = r.json() assert_equal(len(data['txs']), 2) self.validate_certificate(data['txs'][1], certInfo, True) #Test also the /txs endpoint with address r = requests.get(url = self.BASE_URL+"txs?address="+pkh_node1+"&showImmatureBTs=1", params = {}) data = r.json() for tx in data['txs']: if (tx['txid'] == cert1): self.validate_certificate(tx, certInfo, True) r = requests.get(url = self.BASE_URL+"txs?address="+pkh_node1+"&showImmatureBTs=0", params = {}) data = r.json() for tx in data['txs']: if (tx['txid'] == cert1): self.validate_certificate(tx, certInfo, True) r = requests.get(url = self.BASE_URL+"txs?address="+pkh_node1, params = {}) data = r.json() for tx in data['txs']: if (tx['txid'] == cert1): self.validate_certificate(tx, certInfo, True) #Test that the certificate 2 is superseded certTx2 = self.nodes[0].gettransaction(cert2) certInfo2 = self.nodes[0].getcertmaturityinfo(cert2) r = requests.get(url = self.BASE_URL+"tx/"+cert2+"?showImmatureBTs=1", params = {}) data = r.json() self.validate_certificate(data, certInfo2, False) r = requests.get(url = self.BASE_URL+"tx/"+cert2+"?showImmatureBTs=0", params = {}) data = r.json() self.validate_certificate(data, certInfo2, False) r = requests.get(url = self.BASE_URL+"tx/"+cert2, params = {}) data = r.json() self.validate_certificate(data, certInfo2, False) #Test also the /txs endpoint with blockhash r = requests.get(url = self.BASE_URL+"txs?block="+cert2_3_block+"&showImmatureBTs=1", params = {}) data = r.json() for tx in data['txs']: if (tx['txid'] == cert2): self.validate_certificate(tx, certInfo2, False) r = requests.get(url = self.BASE_URL+"txs?block="+cert2_3_block+"&showImmatureBTs=0", params = {}) data = r.json() for tx in data['txs']: if (tx['txid'] == cert2): self.validate_certificate(tx, certInfo2, False) r = requests.get(url = self.BASE_URL+"txs?block="+cert2_3_block, params = {}) data = r.json() for tx in data['txs']: if (tx['txid'] == cert2): self.validate_certificate(tx, certInfo2, False) #Test also the /txs endpoint with address r = requests.get(url = self.BASE_URL+"txs?address="+pkh_node1+"&showImmatureBTs=1", params = {}) data = r.json() for tx in data['txs']: if (tx['txid'] == cert2): self.validate_certificate(tx, certInfo2, False) r = requests.get(url = self.BASE_URL+"txs?address="+pkh_node1+"&showImmatureBTs=0", params = {}) data = r.json() for tx in data['txs']: if (tx['txid'] == cert2): self.validate_certificate(tx, certInfo2, False) r = requests.get(url = self.BASE_URL+"txs?address="+pkh_node1, params = {}) data = r.json() for tx in data['txs']: if (tx['txid'] == cert2): self.validate_certificate(tx, certInfo2, False) #Let the sidechains to cease self.nodes[0].generate(120) self.sync_all() assert_equal(self.nodes[0].getscinfo("*",True)['totalItems'], 0) time.sleep(20) #Test with a CSW # CSW sender MC address, in taddress and pub key hash formats csw_mc_address = self.nodes[0].getnewaddress() sc_csw_amount = Decimal('1.0') nullifier = generate_random_field_element_hex() # Get the active cert data hash actCertData = self.nodes[0].getactivecertdatahash(scid)['certDataHash'] ceasingCumScTxCommTree = self.nodes[0].getceasingcumsccommtreehash(scid)['ceasingCumScTxCommTree'] scid1_swapped = swap_bytes(scid) sc_proof = cswMcTest.create_test_proof( "sc1", sc_csw_amount, str(scid1_swapped), nullifier, csw_mc_address, ceasingCumScTxCommTree, actCertData, constant) sc_csws = [ { "amount": sc_csw_amount, "senderAddress": csw_mc_address, "scId": scid, "epoch": 0, "nullifier": nullifier, "activeCertData": actCertData, "ceasingCumScTxCommTree": ceasingCumScTxCommTree, "scProof": sc_proof } ] # recipient MC address taddr_2 = self.nodes[0].getnewaddress() sc_csw_tx_outs = {taddr_2: Decimal(sc_csw_amount)} rawtx = self.nodes[0].createrawtransaction([], sc_csw_tx_outs, sc_csws) funded_tx = self.nodes[0].fundrawtransaction(rawtx) sigRawtx = self.nodes[0].signrawtransaction(funded_tx['hex'], None, None, "NONE") cswTxid = self.nodes[0].sendrawtransaction(sigRawtx['hex']) self.sync_all() time.sleep(2) self.nodes[0].generate(1) self.sync_all() time.sleep(2) r = requests.get(url = self.BASE_URL+"tx/"+cswTxid, params = {}) data = r.json() cswTx = self.nodes[0].gettransaction(cswTxid) decodedCswTx = self.nodes[0].decoderawtransaction(cswTx['hex']) self.validate_full_tx(data,decodedCswTx,cswTx) #Test with an invalid txid invalidTxId = "fe86fa1c6d61585e5e24424997d1542d8857758033937fa0812c407d83adfd14" r = requests.get(url = self.BASE_URL+"tx/"+invalidTxId, params = {}) assert_equal(r.text,"Not found") ############################################################################################################################# #### /rawtx/:rawId #### print("######## /rawtx/:rawId ########") #Test coinbase-transaction r = requests.get(url = self.BASE_URL+"rawtx/"+coinbaseTxId, params = {}) data = r.json() assert_equal(data['rawtx'],self.nodes[0].gettransaction(coinbaseTxId)['hex']) #Test t-transaction r = requests.get(url = self.BASE_URL+"rawtx/"+tTxId, params = {}) data = r.json() assert_equal(data['rawtx'],self.nodes[0].gettransaction(tTxId)['hex']) #Test z-transaction t->z r = requests.get(url = self.BASE_URL+"rawtx/"+zTxid, params = {}) data = r.json() assert_equal(data['rawtx'],self.nodes[0].gettransaction(zTxid)['hex']) #Test z-transaction z->z r = requests.get(url = self.BASE_URL+"rawtx/"+zTxid2, params = {}) data = r.json() assert_equal(data['rawtx'],self.nodes[0].gettransaction(zTxid2)['hex']) #Test multiple sidechain creation and ft r = requests.get(url = self.BASE_URL+"rawtx/"+scTxid, params = {}) data = r.json() assert_equal(data['rawtx'],self.nodes[0].gettransaction(scTxid)['hex']) #Test with an invalid txid invalidTxId = "fe86fa1c6d61585e5e24424997d1542d8857758033937fa0812c407d83adfd14" r = requests.get(url = self.BASE_URL+"rawtx/"+invalidTxId, params = {}) assert_equal(r.text,"Not found") ############################################################################################################################# #### /tx/send #### print("######## /tx/send ########") txId = self.nodes[0].sendtoaddress(tAddr,10.0001) self.sync_all() self.nodes[0].generate(1) self.sync_all() tx = self.nodes[0].gettransaction(txId) rawtx = self.nodes[0].decoderawtransaction(tx['hex']) vout = {} for outpoint in rawtx['vout']: if (outpoint['value'] == Decimal('10.0001')): vout = outpoint break inputs = [{'txid': txId, 'vout': vout['n']}] rawtx = self.nodes[0].createrawtransaction(inputs, {tAddr2:8.0,tAddr:2.0}) sigRawtx = self.nodes[0].signrawtransaction(rawtx) #Test with not signed tx r = requests.post(url = self.BASE_URL+"tx/send", json={"rawtx":rawtx}) assert_equal(r.status_code,400) #Test with signed tx r = requests.post(url = self.BASE_URL+"tx/send", json={"rawtx":sigRawtx['hex']}) assert_equal(r.status_code,200) self.sync_all() self.nodes[0].generate(1) self.sync_all() txid = r.json()['txid'] tx = self.nodes[0].gettransaction(txid) decodedTx = self.nodes[0].decoderawtransaction(tx['hex']) assert_equal(tx['hex'],sigRawtx['hex']) r = requests.get(url = self.BASE_URL+"tx/"+txid, params = {}) data = r.json() self.validate_full_tx(data,decodedTx, tx) ############################################################################################################################# #### /txs #### #Test with blockhash txs = [] for i in range (1,36): txs += [self.nodes[0].sendtoaddress(tAddr,Decimal(str(i)))] self.sync_all() block = self.nodes[0].generate(1) self.sync_all() #Add the coinbase to the list of transactions txs +=[self.nodes[0].getblock(block[0])['tx'][0]] time.sleep(5) #Test withouth pageNum (1st page) r = requests.get(url = self.BASE_URL+"txs?block="+block[0], params = {}) data = r.json() assert_equal(len(data['txs']),10) assert_equal(data['pagesTotal'],4) for tx in data['txs']: assert_true(tx['txid'] in txs) transaction = self.nodes[0].gettransaction(tx['txid']) decodedTransaction = self.nodes[0].decoderawtransaction(transaction['hex']) self.validate_full_tx(tx,decodedTransaction,transaction) #Test with pageNum r = requests.get(url = self.BASE_URL+"txs?pageNum=1&block="+block[0], params = {}) data = r.json() assert_equal(len(data['txs']),10) assert_equal(data['pagesTotal'],4) for tx in data['txs']: assert_true(tx['txid'] in txs) transaction = self.nodes[0].gettransaction(tx['txid']) decodedTransaction = self.nodes[0].decoderawtransaction(transaction['hex']) self.validate_full_tx(tx,decodedTransaction,transaction) #Test with last pageNum r = requests.get(url = self.BASE_URL+"txs?pageNum=3&block="+block[0], params = {}) data = r.json() assert_equal(len(data['txs']),6) assert_equal(data['pagesTotal'],4) for tx in data['txs']: assert_true(tx['txid'] in txs) transaction = self.nodes[0].gettransaction(tx['txid']) decodedTransaction = self.nodes[0].decoderawtransaction(transaction['hex']) self.validate_full_tx(tx,decodedTransaction,transaction) #Test with invalid blockhash invalidBlockHash = "010857e2c8d072c0142aad2faeca8a856e438fe2d1fe963d78dba8d9e5f664b8" r = requests.get(url = self.BASE_URL+"txs?block="+invalidBlockHash, params = {}) assert_equal(r.status_code,404) #Test with address and no pageNum (1st page) r = requests.get(url = self.BASE_URL+"txs?address="+tAddr, params = {}) data = r.json() assert_equal(len(data['txs']),10) assert_equal(data['pagesTotal'],4) txs += [txid,txId,tTxId,zTxid] for tx in data['txs']: assert_true(tx['txid'] in txs) transaction = self.nodes[0].gettransaction(tx['txid']) decodedTransaction = self.nodes[0].decoderawtransaction(transaction['hex']) self.validate_full_tx(tx,decodedTransaction,transaction) #Test with address and no pageNum (1st page) r = requests.get(url = self.BASE_URL+"txs?pageNum=1&address="+tAddr, params = {}) data = r.json() assert_equal(len(data['txs']),10) assert_equal(data['pagesTotal'],4) for tx in data['txs']: assert_true(tx['txid'] in txs) transaction = self.nodes[0].gettransaction(tx['txid']) decodedTransaction = self.nodes[0].decoderawtransaction(transaction['hex']) self.validate_full_tx(tx,decodedTransaction,transaction) #Test with address and last pageNum r = requests.get(url = self.BASE_URL+"txs?pageNum=3&address="+tAddr, params = {}) data = r.json() assert_equal(len(data['txs']),9) assert_equal(data['pagesTotal'],4) for tx in data['txs']: assert_true(tx['txid'] in txs) transaction = self.nodes[0].gettransaction(tx['txid']) decodedTransaction = self.nodes[0].decoderawtransaction(transaction['hex']) self.validate_full_tx(tx,decodedTransaction,transaction) #Test with invalid address invalidAddress = "ztVfuvhoNcrunLThJvNeRmg7on4NWidvsVk" r = requests.get(url = self.BASE_URL+"txs?address="+invalidAddress, params = {}) data = r.json() assert_equal(len(data['txs']),0) assert_equal(data['pagesTotal'],0) #Test with no parameters r = requests.get(url = self.BASE_URL+"txs", params = {}) assert_equal(r.status_code,503)
def run_migration_test(self, node, sproutAddr, saplingAddr, target_height): # Make sure we are in a good state to run the test assert_equal(102, node.getblockcount() % 500, "Should be at block 102 % 500") assert_equal(node.z_getbalance(sproutAddr), Decimal('10')) assert_equal(node.z_getbalance(saplingAddr), Decimal('0')) check_migration_status(node, saplingAddr, DISABLED_BEFORE_MIGRATION) # Migrate node.z_setmigration(True) print("Mining to block 494 % 500...") node.generate(392) # 102 % 500 -> 494 % 500 self.sync_all() # At 494 % 500 we should have no async operations assert_equal(0, len(node.z_getoperationstatus()), "num async operations at 494 % 500") check_migration_status(node, saplingAddr, ENABLED_BEFORE_MIGRATION) node.generate(1) self.sync_all() # At 495 % 500 we should have an async operation operationstatus = node.z_getoperationstatus() print("migration operation: {}".format(operationstatus)) assert_equal(1, len(operationstatus), "num async operations at 495 % 500") assert_equal('saplingmigration', operationstatus[0]['method']) assert_equal(target_height, operationstatus[0]['target_height']) result = wait_and_assert_operationid_status_result( node, operationstatus[0]['id']) print("result: {}".format(result)) assert_equal('saplingmigration', result['method']) assert_equal(target_height, result['target_height']) assert_equal(1, result['result']['num_tx_created']) assert_equal(1, len(result['result']['migration_txids'])) assert_true( Decimal(result['result']['amount_migrated']) > Decimal('0')) assert_equal(0, len(node.getrawmempool()), "mempool size at 495 % 500") node.generate(3) self.sync_all() # At 498 % 500 the mempool will be empty and no funds will have moved assert_equal(0, len(node.getrawmempool()), "mempool size at 498 % 500") assert_equal(node.z_getbalance(sproutAddr), Decimal('10')) assert_equal(node.z_getbalance(saplingAddr), Decimal('0')) node.generate(1) self.sync_all() # At 499 % 500 there will be a transaction in the mempool and the note will be locked mempool = node.getrawmempool() print("mempool: {}".format(mempool)) assert_equal(1, len(mempool), "mempool size at 499 % 500") assert_equal(node.z_getbalance(sproutAddr), Decimal('0')) assert_equal(node.z_getbalance(saplingAddr), Decimal('0')) assert_true( node.z_getbalance(saplingAddr, 0) > Decimal('0'), "Unconfirmed sapling balance at 499 % 500") # Check that unmigrated amount + unfinalized = starting balance - fee status = node.z_getmigrationstatus() print("status: {}".format(status)) assert_equal( Decimal('9.9999'), Decimal(status['unmigrated_amount']) + Decimal(status['unfinalized_migrated_amount'])) # The transaction in the mempool should be the one listed in migration_txids, # and it should expire at the next 450 % 500. assert_equal(1, len(status['migration_txids'])) txid = status['migration_txids'][0] assert_equal(txid, mempool[0]) tx = node.getrawtransaction(txid, 1) assert_equal(target_height + 450, tx['expiryheight']) node.generate(1) self.sync_all() # At 0 % 500 funds will have moved sprout_balance = node.z_getbalance(sproutAddr) sapling_balance = node.z_getbalance(saplingAddr) print("sprout balance: {}, sapling balance: {}".format( sprout_balance, sapling_balance)) assert_true(sprout_balance < Decimal('10'), "Should have less Sprout funds") assert_true(sapling_balance > Decimal('0'), "Should have more Sapling funds") assert_true(sprout_balance + sapling_balance, Decimal('9.9999')) check_migration_status(node, saplingAddr, DURING_MIGRATION) # At 10 % 500 the transactions will be considered 'finalized' node.generate(10) self.sync_all() check_migration_status(node, saplingAddr, AFTER_MIGRATION) # Check exact migration status amounts to make sure we account for fee status = node.z_getmigrationstatus() assert_equal(sprout_balance, Decimal(status['unmigrated_amount'])) assert_equal(sapling_balance, Decimal(status['finalized_migrated_amount']))
def run_migration_test(self, node, sproutAddr, saplingAddr, target_height): # Make sure we are in a good state to run the test assert_equal(102, node.getblockcount() % 500, "Should be at block 102 % 500") assert_equal(node.z_getbalance(sproutAddr), Decimal('10')) assert_equal(node.z_getbalance(saplingAddr), Decimal('0')) check_migration_status(node, False, saplingAddr, True, False, False, 0, 0) # Migrate node.z_setmigration(True) print("Mining to block 494 % 500...") node.generate(392) # 102 % 500 -> 494 % 500 self.sync_all() # At 494 % 500 we should have no async operations assert_equal(0, len(node.z_getoperationstatus()), "num async operations at 494 % 500") check_migration_status(node, True, saplingAddr, True, False, False, 0, 0) node.generate(1) self.sync_all() # At 495 % 500 we should have an async operation operationstatus = node.z_getoperationstatus() print("migration operation: {}".format(operationstatus)) assert_equal(1, len(operationstatus), "num async operations at 495 % 500") assert_equal('saplingmigration', operationstatus[0]['method']) assert_equal(target_height, operationstatus[0]['target_height']) result = wait_and_assert_operationid_status_result(node, operationstatus[0]['id']) print("result: {}".format(result)) assert_equal('saplingmigration', result['method']) assert_equal(target_height, result['target_height']) assert_equal(1, result['result']['num_tx_created']) assert_equal(0, len(node.getrawmempool()), "mempool size at 495 % 500") node.generate(3) self.sync_all() # At 498 % 500 the mempool will be empty and no funds will have moved assert_equal(0, len(node.getrawmempool()), "mempool size at 498 % 500") assert_equal(node.z_getbalance(sproutAddr), Decimal('10')) assert_equal(node.z_getbalance(saplingAddr), Decimal('0')) node.generate(1) self.sync_all() # At 499 % 500 there will be a transaction in the mempool and the note will be locked assert_equal(1, len(node.getrawmempool()), "mempool size at 499 % 500") assert_equal(node.z_getbalance(sproutAddr), Decimal('0')) assert_equal(node.z_getbalance(saplingAddr), Decimal('0')) assert_true(node.z_getbalance(saplingAddr, 0) > Decimal('0'), "Unconfirmed sapling balance at 499 % 500") # Check that unmigrated amount + unfinalized = starting balance - fee status = node.z_getmigrationstatus() assert_equal(Decimal('9.9999'), Decimal(status['unmigrated_amount']) + Decimal(status['unfinalized_migrated_amount'])) node.generate(1) self.sync_all() # At 0 % 500 funds will have moved sprout_balance = node.z_getbalance(sproutAddr) sapling_balance = node.z_getbalance(saplingAddr) print("sprout balance: {}, sapling balance: {}".format(sprout_balance, sapling_balance)) assert_true(sprout_balance < Decimal('10'), "Should have less Sprout funds") assert_true(sapling_balance > Decimal('0'), "Should have more Sapling funds") assert_true(sprout_balance + sapling_balance, Decimal('9.9999')) check_migration_status(node, True, saplingAddr, True, True, False, 0, 1) # At 10 % 500 the transactions will be considered 'finalized' node.generate(10) self.sync_all() check_migration_status(node, True, saplingAddr, True, False, True, 1, 1) # Check exact migration status amounts to make sure we account for fee status = node.z_getmigrationstatus() assert_equal(sprout_balance, Decimal(status['unmigrated_amount'])) assert_equal(sapling_balance, Decimal(status['finalized_migrated_amount']))
class SCCreateTest(BitcoinTestFramework): alert_filename = None def setup_chain(self, split=False): print("Initializing test directory " + self.options.tmpdir) initialize_chain_clean(self.options.tmpdir, NUMB_OF_NODES) self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt") with open(self.alert_filename, 'w'): pass # Just open then close to create zero-length file def setup_network(self, split=False): self.nodes = start_nodes( NUMB_OF_NODES, self.options.tmpdir, extra_args=[[ "-sccoinsmaturity=%d" % SC_COINS_MAT, '-logtimemicros=1', '-debug=sc', '-debug=py', '-debug=mempool', '-debug=net', '-debug=bench' ]] * NUMB_OF_NODES) connect_nodes_bi(self.nodes, 0, 1) self.is_network_split = split self.sync_all() def run_test(self): ''' This test try to create a SC using the command sc_create using invalid parameters and valid parameters. ''' #{"withdrawalEpochLength", "fromaddress", "toaddress", "amount", "minconf", "fee", "customData"}; # network topology: (0)--(1) mark_logs("Node 1 generates 2 block", self.nodes, DEBUG_MODE) self.nodes[1].generate(2) self.sync_all() mark_logs("Node 0 generates {} block".format(MINIMAL_SC_HEIGHT), self.nodes, DEBUG_MODE) self.nodes[0].generate(MINIMAL_SC_HEIGHT) self.sync_all() tx = [] errorString = "" toaddress = "abcdef" #generate wCertVk and constant mcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir) vk = mcTest.generate_params('sc1') constant = generate_random_field_element_hex() # create with wrong key in input #------------------------------------ amount = 12.0 fee = 0.000025 cmdInput = { 'version': 0, 'wrong_key': 123, 'toaddress': toaddress, 'amount': amount, 'fee': fee, 'wCertVk': vk } mark_logs("\nNode 1 create SC with wrong key in input", self.nodes, DEBUG_MODE) try: self.nodes[1].sc_create(cmdInput) assert_true(False) except JSONRPCException, e: errorString = e.error['message'] mark_logs(errorString, self.nodes, DEBUG_MODE) assert_true("wrong_key" in errorString) # create with duplicate key in input #------------------------------------ cmdInput = FakeDict([('version', 0), ('fee', fee), ('amount', amount), ('amount', 6.0), ('toaddress', str(toaddress)), ('wCertVk', vk)]) mark_logs("\nNode 1 create SC with duplicate key in input", self.nodes, DEBUG_MODE) try: self.nodes[1].sc_create(cmdInput) assert_true(False) except JSONRPCException, e: errorString = e.error['message'] mark_logs(errorString, self.nodes, DEBUG_MODE) assert_true("amount" in errorString)
def run_test(self): print "Mining blocks..." self.nodes[0].generate(101) self.sync_all() # Send some ZEC to a Sprout address tAddr = get_coinbase_address(self.nodes[0]) sproutAddr = self.nodes[0].z_getnewaddress('sprout') saplingAddr = self.nodes[0].z_getnewaddress('sapling') opid = self.nodes[0].z_sendmany(tAddr, [{ "address": sproutAddr, "amount": Decimal('10') }], 1, 0) wait_and_assert_operationid_status(self.nodes[0], opid) self.nodes[0].generate(1) self.sync_all() assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('10')) assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('0')) # Migrate self.nodes[0].z_setmigration(True) print "Mining to block 494..." self.nodes[0].generate(392) # 102 -> 494 self.sync_all() # At 494 we should have no async operations assert_equal(0, len(self.nodes[0].z_getoperationstatus()), "num async operations at 494") self.nodes[0].generate(1) self.sync_all() # At 495 we should have an async operation operationstatus = self.nodes[0].z_getoperationstatus() print "migration operation: {}".format(operationstatus) assert_equal(1, len(operationstatus), "num async operations at 495") assert_equal('saplingmigration', operationstatus[0]['method']) assert_equal(500, operationstatus[0]['target_height']) result = wait_and_assert_operationid_status_result( self.nodes[0], operationstatus[0]['id']) print "result: {}".format(result) assert_equal('saplingmigration', result['method']) assert_equal(500, result['target_height']) assert_equal(1, result['result']['num_tx_created']) assert_equal(0, len(self.nodes[0].getrawmempool()), "mempool size at 495") self.nodes[0].generate(3) self.sync_all() # At 498 the mempool will be empty and no funds will have moved assert_equal(0, len(self.nodes[0].getrawmempool()), "mempool size at 498") assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('10')) assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('0')) self.nodes[0].generate(1) self.sync_all() # At 499 there will be a transaction in the mempool and the note will be locked assert_equal(1, len(self.nodes[0].getrawmempool()), "mempool size at 499") assert_equal(self.nodes[0].z_getbalance(sproutAddr), Decimal('0')) assert_equal(self.nodes[0].z_getbalance(saplingAddr), Decimal('0')) assert_true(self.nodes[0].z_getbalance(saplingAddr, 0) > Decimal('0'), "Unconfirmed sapling") self.nodes[0].generate(1) self.sync_all() # At 500 funds will have moved sprout_balance = self.nodes[0].z_getbalance(sproutAddr) sapling_balance = self.nodes[0].z_getbalance(saplingAddr) print "sprout balance: {}, sapling balance: {}".format( sprout_balance, sapling_balance) assert_true(sprout_balance < Decimal('10'), "Should have less Sprout funds") assert_true(sapling_balance > Decimal('0'), "Should have more Sapling funds") assert_true(sprout_balance + sapling_balance, Decimal('9.9999'))
def run_test(self): def get_spendable(nodeIdx, min_amount): # get a UTXO for setting fee utx = False listunspent = self.nodes[nodeIdx].listunspent() for aUtx in listunspent: if aUtx['amount'] > min_amount: utx = aUtx change = aUtx['amount'] - min_amount break if utx == False: pprint.pprint(listunspent) assert_equal(utx != False, True) return utx, change ''' Testing the capabilities of the api for creating raw certificates and handling their decoding. Negative tests are also performed by specifying wrong params and incorrect pkey for the signing ''' # forward transfer amount cr_amount = Decimal("5.0") bt_amount = Decimal("4.0") sc_amount = cr_amount # node 1 earns some coins, they would be available after 100 blocks mark_logs("Node 1 generates 1 block", self.nodes, DEBUG_MODE) self.nodes[1].generate(1) self.sync_all() mark_logs("Node 0 generates 1 block", self.nodes, DEBUG_MODE) self.nodes[0].generate(1) self.sync_all() mark_logs("Node 3 generates {} block".format(MINIMAL_SC_HEIGHT - 1), self.nodes, DEBUG_MODE) self.nodes[3].generate(MINIMAL_SC_HEIGHT - 1) self.sync_all() # node 1 has just the coinbase which is now mature bal_before = self.nodes[1].getbalance("", 0) # create a sc via createraw cmd mark_logs( "Node 1 creates the SC spending " + str(sc_amount) + " coins ...", self.nodes, DEBUG_MODE) sc_address = "fade" #generate vk and constant for this sidechain mcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir) vk = mcTest.generate_params("sc1") constant = generate_random_field_element_hex() sc_cr = [{ "version": 0, "epoch_length": EPOCH_LENGTH, "amount": cr_amount, "address": sc_address, "wCertVk": vk, "constant": constant }] sc_ft = [] raw_tx = self.nodes[1].createrawtransaction([], {}, [], sc_cr, sc_ft) funded_tx = self.nodes[1].fundrawtransaction(raw_tx) signed_tx = self.nodes[1].signrawtransaction(funded_tx['hex']) creating_tx = self.nodes[1].sendrawtransaction(signed_tx['hex']) self.sync_all() decoded_tx = self.nodes[1].getrawtransaction(creating_tx, 1) scid = decoded_tx['vsc_ccout'][0]['scid'] scid_swapped = str(swap_bytes(scid)) mark_logs("created SC id: {}".format(scid), self.nodes, DEBUG_MODE) #retrieve previous_end_epoch_mc_b_hash current_height = self.nodes[3].getblockcount() mark_logs("Node3 generating {} blocks".format(EPOCH_LENGTH), self.nodes, DEBUG_MODE) self.nodes[3].generate(EPOCH_LENGTH) self.sync_all() epoch_number, epoch_cum_tree_hash = get_epoch_data( scid, self.nodes[0], EPOCH_LENGTH) # save them for the last test epn_0 = epoch_number epoch_cum_tree_hash_0 = epoch_cum_tree_hash # -------------------------- end epoch sc_funds_pre = self.nodes[3].getscinfo(scid)['items'][0]['balance'] addr_node2 = self.nodes[2].getnewaddress() mark_logs("Node3 generating 2 block, overcoming safeguard", self.nodes, DEBUG_MODE) self.nodes[3].generate(2) self.sync_all() # create wCert proof quality = 0 proof = mcTest.create_test_proof("sc1", scid_swapped, epoch_number, quality, MBTR_SC_FEE, FT_SC_FEE, epoch_cum_tree_hash, constant, [addr_node2], [bt_amount]) utx, change = get_spendable(0, CERT_FEE) raw_inputs = [{'txid': utx['txid'], 'vout': utx['vout']}] raw_outs = {self.nodes[0].getnewaddress(): change} raw_bwt_outs = [{"address": addr_node2, "amount": bt_amount}] raw_params = { "scid": scid, "quality": quality, "endEpochCumScTxCommTreeRoot": epoch_cum_tree_hash, "scProof": proof, "withdrawalEpochNumber": epoch_number } raw_cert = [] cert = [] try: raw_cert = self.nodes[0].createrawcertificate( raw_inputs, raw_outs, raw_bwt_outs, raw_params) signed_cert = self.nodes[0].signrawtransaction(raw_cert) except JSONRPCException, e: errorString = e.error['message'] print "\n======> ", errorString assert_true(False)
class sc_rawcert(BitcoinTestFramework): alert_filename = None def setup_chain(self, split=False): print("Initializing test directory " + self.options.tmpdir) initialize_chain_clean(self.options.tmpdir, NUMB_OF_NODES) self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt") with open(self.alert_filename, 'w'): pass # Just open then close to create zero-length file def setup_network(self, split=False): self.nodes = [] self.nodes = start_nodes( NUMB_OF_NODES, self.options.tmpdir, extra_args=[[ '-debug=py', '-debug=sc', '-debug=mempool', '-debug=net', '-debug=cert', '-scproofqueuesize=0', '-logtimemicros=1', '-txindex=1', '-zapwallettxes=2' ]] * NUMB_OF_NODES) for idx, _ in enumerate(self.nodes): if idx < (NUMB_OF_NODES - 1): connect_nodes_bi(self.nodes, idx, idx + 1) sync_blocks(self.nodes[1:NUMB_OF_NODES]) sync_mempools(self.nodes[1:NUMB_OF_NODES]) self.is_network_split = split self.sync_all() def run_test(self): def get_spendable(nodeIdx, min_amount): # get a UTXO for setting fee utx = False listunspent = self.nodes[nodeIdx].listunspent() for aUtx in listunspent: if aUtx['amount'] > min_amount: utx = aUtx change = aUtx['amount'] - min_amount break if utx == False: pprint.pprint(listunspent) assert_equal(utx != False, True) return utx, change ''' Testing the capabilities of the api for creating raw certificates and handling their decoding. Negative tests are also performed by specifying wrong params and incorrect pkey for the signing ''' # forward transfer amount cr_amount = Decimal("5.0") bt_amount = Decimal("4.0") sc_amount = cr_amount # node 1 earns some coins, they would be available after 100 blocks mark_logs("Node 1 generates 1 block", self.nodes, DEBUG_MODE) self.nodes[1].generate(1) self.sync_all() mark_logs("Node 0 generates 1 block", self.nodes, DEBUG_MODE) self.nodes[0].generate(1) self.sync_all() mark_logs("Node 3 generates {} block".format(MINIMAL_SC_HEIGHT - 1), self.nodes, DEBUG_MODE) self.nodes[3].generate(MINIMAL_SC_HEIGHT - 1) self.sync_all() # node 1 has just the coinbase which is now mature bal_before = self.nodes[1].getbalance("", 0) # create a sc via createraw cmd mark_logs( "Node 1 creates the SC spending " + str(sc_amount) + " coins ...", self.nodes, DEBUG_MODE) sc_address = "fade" #generate vk and constant for this sidechain mcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir) vk = mcTest.generate_params("sc1") constant = generate_random_field_element_hex() sc_cr = [{ "version": 0, "epoch_length": EPOCH_LENGTH, "amount": cr_amount, "address": sc_address, "wCertVk": vk, "constant": constant }] sc_ft = [] raw_tx = self.nodes[1].createrawtransaction([], {}, [], sc_cr, sc_ft) funded_tx = self.nodes[1].fundrawtransaction(raw_tx) signed_tx = self.nodes[1].signrawtransaction(funded_tx['hex']) creating_tx = self.nodes[1].sendrawtransaction(signed_tx['hex']) self.sync_all() decoded_tx = self.nodes[1].getrawtransaction(creating_tx, 1) scid = decoded_tx['vsc_ccout'][0]['scid'] scid_swapped = str(swap_bytes(scid)) mark_logs("created SC id: {}".format(scid), self.nodes, DEBUG_MODE) #retrieve previous_end_epoch_mc_b_hash current_height = self.nodes[3].getblockcount() mark_logs("Node3 generating {} blocks".format(EPOCH_LENGTH), self.nodes, DEBUG_MODE) self.nodes[3].generate(EPOCH_LENGTH) self.sync_all() epoch_number, epoch_cum_tree_hash = get_epoch_data( scid, self.nodes[0], EPOCH_LENGTH) # save them for the last test epn_0 = epoch_number epoch_cum_tree_hash_0 = epoch_cum_tree_hash # -------------------------- end epoch sc_funds_pre = self.nodes[3].getscinfo(scid)['items'][0]['balance'] addr_node2 = self.nodes[2].getnewaddress() mark_logs("Node3 generating 2 block, overcoming safeguard", self.nodes, DEBUG_MODE) self.nodes[3].generate(2) self.sync_all() # create wCert proof quality = 0 proof = mcTest.create_test_proof("sc1", scid_swapped, epoch_number, quality, MBTR_SC_FEE, FT_SC_FEE, epoch_cum_tree_hash, constant, [addr_node2], [bt_amount]) utx, change = get_spendable(0, CERT_FEE) raw_inputs = [{'txid': utx['txid'], 'vout': utx['vout']}] raw_outs = {self.nodes[0].getnewaddress(): change} raw_bwt_outs = [{"address": addr_node2, "amount": bt_amount}] raw_params = { "scid": scid, "quality": quality, "endEpochCumScTxCommTreeRoot": epoch_cum_tree_hash, "scProof": proof, "withdrawalEpochNumber": epoch_number } raw_cert = [] cert = [] try: raw_cert = self.nodes[0].createrawcertificate( raw_inputs, raw_outs, raw_bwt_outs, raw_params) signed_cert = self.nodes[0].signrawtransaction(raw_cert) except JSONRPCException, e: errorString = e.error['message'] print "\n======> ", errorString assert_true(False) decoded_cert_pre = self.nodes[0].decoderawtransaction(raw_cert) decoded_cert_pre_list = sorted(decoded_cert_pre.items()) mark_logs( "Node0 sending raw certificate for epoch {}, expecting failure...". format(epoch_number), self.nodes, DEBUG_MODE) # we expect it to fail because beyond the safeguard try: cert = self.nodes[0].sendrawtransaction(signed_cert['hex']) assert_true(False) except JSONRPCException, e: errorString = e.error['message'] print "======> ", errorString, "\n"
mark_logs( "Node0 invalidates last block, thus shortening the chain by one and returning in the safe margin", self.nodes, DEBUG_MODE) self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) sync_mempools(self.nodes[1:3]) mark_logs( "Node0 sending raw certificate for epoch {}, expecting success". format(epoch_number), self.nodes, DEBUG_MODE) try: cert = self.nodes[0].sendrawtransaction(signed_cert['hex']) except JSONRPCException, e: errorString = e.error['message'] print "\n======> ", errorString assert_true(False) decoded_cert_pre = self.nodes[0].decoderawtransaction( signed_cert['hex']) decoded_cert_pre_list = sorted(decoded_cert_pre.items()) sync_mempools(self.nodes[1:3]) mark_logs( "Node0 generating 4 block, also reverting other nodes' chains", self.nodes, DEBUG_MODE) mined = self.nodes[0].generate(1)[0] minedBlock = self.nodes[0].getblock(mined) #epoch_number = 1 self.nodes[0].generate(3) epoch_number, epoch_cum_tree_hash = get_epoch_data(
def run_test(self): # Sanity-check the test harness self.nodes[0].generate(200) assert_equal(self.nodes[0].getblockcount(), 200) self.sync_all() # Verify Sapling address is persisted in wallet (even when Sapling is not yet active) sapling_addr = self.nodes[0].z_getnewaddress('sapling') # Make sure the node has the addresss addresses = self.nodes[0].z_listaddresses() assert_true(sapling_addr in addresses, "Should contain address before restart") # Restart the nodes stop_nodes(self.nodes) wait_bitcoinds() self.setup_network() # Make sure we still have the address after restarting addresses = self.nodes[0].z_listaddresses() assert_true(sapling_addr in addresses, "Should contain address after restart") # Activate Sapling self.nodes[0].generate(1) self.sync_all() # Node 0 shields funds to Sapling address taddr0 = self.nodes[0].getnewaddress() recipients = [] recipients.append({"address": sapling_addr, "amount": Decimal('20')}) myopid = self.nodes[0].z_sendmany(taddr0, recipients, 1, 0) wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() self.nodes[0].generate(1) self.sync_all() # Verify shielded balance assert_equal(self.nodes[0].z_getbalance(sapling_addr), Decimal('20')) # Verify size of shielded pools pools = self.nodes[0].getblockchaininfo()['valuePools'] assert_equal(pools[0]['chainValue'], Decimal('0')) # Sprout assert_equal(pools[1]['chainValue'], Decimal('20')) # Sapling # Restart the nodes stop_nodes(self.nodes) wait_bitcoinds() self.setup_network() # Verify size of shielded pools pools = self.nodes[0].getblockchaininfo()['valuePools'] assert_equal(pools[0]['chainValue'], Decimal('0')) # Sprout assert_equal(pools[1]['chainValue'], Decimal('20')) # Sapling # Node 0 sends some shielded funds to Node 1 dest_addr = self.nodes[1].z_getnewaddress('sapling') recipients = [] recipients.append({"address": dest_addr, "amount": Decimal('15')}) myopid = self.nodes[0].z_sendmany(sapling_addr, recipients, 1, 0) wait_and_assert_operationid_status(self.nodes[0], myopid) self.sync_all() self.nodes[0].generate(1) self.sync_all() # Verify balances assert_equal(self.nodes[0].z_getbalance(sapling_addr), Decimal('5')) assert_equal(self.nodes[1].z_getbalance(dest_addr), Decimal('15')) # Restart the nodes stop_nodes(self.nodes) wait_bitcoinds() self.setup_network() # Verify balances assert_equal(self.nodes[0].z_getbalance(sapling_addr), Decimal('5')) assert_equal(self.nodes[1].z_getbalance(dest_addr), Decimal('15')) # Verify importing a spending key will update and persist the nullifiers and witnesses correctly sk0 = self.nodes[0].z_exportkey(sapling_addr) self.nodes[2].z_importkey(sk0, "yes") assert_equal(self.nodes[2].z_getbalance(sapling_addr), Decimal('5')) # Restart the nodes stop_nodes(self.nodes) wait_bitcoinds() self.setup_network() # Verify nullifiers persisted correctly by checking balance # Prior to PR #3590, there will be an error as spent notes are considered unspent: # Assertion failed: expected: <25.00000000> but was: <5> assert_equal(self.nodes[2].z_getbalance(sapling_addr), Decimal('5')) # Verity witnesses persisted correctly by sending shielded funds recipients = [] recipients.append({"address": dest_addr, "amount": Decimal('1')}) myopid = self.nodes[2].z_sendmany(sapling_addr, recipients, 1, 0) wait_and_assert_operationid_status(self.nodes[2], myopid) self.sync_all() self.nodes[0].generate(1) self.sync_all() # Verify balances assert_equal(self.nodes[2].z_getbalance(sapling_addr), Decimal('4')) assert_equal(self.nodes[1].z_getbalance(dest_addr), Decimal('16'))
def run_test(self): sapling_address2 = self.nodes[2].z_getnewaddress('sapling') privkey2 = self.nodes[2].z_exportkey(sapling_address2) self.nodes[0].z_importkey(privkey2) sprout_address0 = self.nodes[0].z_getnewaddress('sprout') sapling_address0 = self.nodes[0].z_getnewaddress('sapling') # node 0 should have the keys dump_path0 = self.nodes[0].z_exportwallet('walletdump') (t_keys0, sprout_keys0, sapling_keys0) = parse_wallet_file(dump_path0) sapling_line_lengths = [len(sapling_key0.split(' #')[0].split()) for sapling_key0 in sapling_keys0.splitlines()] assert_equal(2, len(sapling_line_lengths), "Should have 2 sapling keys") assert_true(2 in sapling_line_lengths, "Should have a key with 2 parameters") assert_true(4 in sapling_line_lengths, "Should have a key with 4 parameters") assert_true(sprout_address0 in sprout_keys0) assert_true(sapling_address0 in sapling_keys0) assert_true(sapling_address2 in sapling_keys0) # node 1 should not have the keys dump_path1 = self.nodes[1].z_exportwallet('walletdumpbefore') (t_keys1, sprout_keys1, sapling_keys1) = parse_wallet_file(dump_path1) assert_true(sprout_address0 not in sprout_keys1) assert_true(sapling_address0 not in sapling_keys1) # import wallet to node 1 self.nodes[1].z_importwallet(dump_path0) # node 1 should now have the keys dump_path1 = self.nodes[1].z_exportwallet('walletdumpafter') (t_keys1, sprout_keys1, sapling_keys1) = parse_wallet_file(dump_path1) assert_true(sprout_address0 in sprout_keys1) assert_true(sapling_address0 in sapling_keys1) assert_true(sapling_address2 in sapling_keys1) # make sure we have perserved the metadata for sapling_key0 in sapling_keys0.splitlines(): assert_true(sapling_key0 in sapling_keys1)
def run_test(self): taddr = self.nodes[1].getnewaddress() zaddr1 = self.nodes[1].z_getnewaddress('sprout') zaddr2 = self.nodes[1].z_getnewaddress('sprout') self.nodes[0].sendtoaddress(taddr, Decimal('1.0')) self.generate_and_sync() # Send 1 ANK to a zaddr wait_and_assert_operationid_status( self.nodes[1], self.nodes[1].z_sendmany(taddr, [{ 'address': zaddr1, 'amount': 1.0, 'memo': 'c0ffee01' }], 1, 0)) self.generate_and_sync() # Check that we have received 1 note which is not change receivedbyaddress = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0) listunspent = self.nodes[1].z_listunspent() assert_equal(1, len(receivedbyaddress), "Should have received 1 note") assert_false(receivedbyaddress[0]['change'], "Note should not be change") assert_equal(1, len(listunspent), "Should have 1 unspent note") assert_false(listunspent[0]['change'], "Unspent note should not be change") # Generate some change wait_and_assert_operationid_status( self.nodes[1], self.nodes[1].z_sendmany(zaddr1, [{ 'address': zaddr2, 'amount': 0.6, 'memo': 'c0ffee02' }], 1, 0)) self.generate_and_sync() # Check zaddr1 received sortedreceived1 = sorted(self.nodes[1].z_listreceivedbyaddress( zaddr1, 0), key=lambda received: received['amount']) assert_equal(2, len(sortedreceived1), "zaddr1 Should have received 2 notes") assert_equal(Decimal('0.4'), sortedreceived1[0]['amount']) assert_true(sortedreceived1[0]['change'], "Note valued at 0.4 should be change") assert_equal(Decimal('1.0'), sortedreceived1[1]['amount']) assert_false(sortedreceived1[1]['change'], "Note valued at 1.0 should not be change") # Check zaddr2 received sortedreceived2 = sorted(self.nodes[1].z_listreceivedbyaddress( zaddr2, 0), key=lambda received: received['amount']) assert_equal(1, len(sortedreceived2), "zaddr2 Should have received 1 notes") assert_equal(Decimal('0.6'), sortedreceived2[0]['amount']) assert_false(sortedreceived2[0]['change'], "Note valued at 0.6 should not be change") # Check unspent sortedunspent = sorted(self.nodes[1].z_listunspent(), key=lambda received: received['amount']) assert_equal(2, len(sortedunspent), "Should have 2 unspent notes") assert_equal(Decimal('0.4'), sortedunspent[0]['amount']) assert_true(sortedunspent[0]['change'], "Unspent note valued at 0.4 should be change") assert_equal(Decimal('0.6'), sortedunspent[1]['amount']) assert_false(sortedunspent[1]['change'], "Unspent note valued at 0.6 should not be change") # Give node 0 a viewing key viewing_key = self.nodes[1].z_exportviewingkey(zaddr1) self.nodes[0].z_importviewingkey(viewing_key) received_node0 = self.nodes[0].z_listreceivedbyaddress(zaddr1, 0) assert_equal(2, len(received_node0)) unspent_node0 = self.nodes[0].z_listunspent(1, 9999999, True) assert_equal(2, len(unspent_node0)) # node 0 only has a viewing key so does not see the change field assert_false('change' in received_node0[0]) assert_false('change' in received_node0[1]) assert_false('change' in unspent_node0[0]) assert_false('change' in unspent_node0[1])
def run_test(self): self.enable_mocktime() self.setup_2_masternodes_network() # Prepare the proposal self.log.info("preparing budget proposal..") firstProposalName = "super-cool" firstProposalLink = "https://forum.flitswallet.app/t/test-proposal" firstProposalCycles = 2 firstProposalAddress = self.miner.getnewaddress() firstProposalAmountPerCycle = 300 nextSuperBlockHeight = self.miner.getnextsuperblock() proposalFeeTxId = self.miner.preparebudget( firstProposalName, firstProposalLink, firstProposalCycles, nextSuperBlockHeight, firstProposalAddress, firstProposalAmountPerCycle) # generate 3 blocks to confirm the tx (and update the mnping) self.stake(3, [self.remoteOne, self.remoteTwo]) # activate sporks self.activate_spork(self.minerPos, "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT") self.activate_spork(self.minerPos, "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT") self.activate_spork(self.minerPos, "SPORK_13_ENABLE_SUPERBLOCKS") txinfo = self.miner.gettransaction(proposalFeeTxId) assert_equal(txinfo['amount'], -50.00) self.log.info("submitting the budget proposal..") proposalHash = self.miner.submitbudget( firstProposalName, firstProposalLink, firstProposalCycles, nextSuperBlockHeight, firstProposalAddress, firstProposalAmountPerCycle, proposalFeeTxId) # let's wait a little bit and see if all nodes are sync time.sleep(1) self.check_proposal_existence(firstProposalName, proposalHash) self.log.info("proposal broadcast successful!") # Proposal is established after 5 minutes. Mine 7 blocks # Proposal needs to be on the chain > 5 min. self.stake(7, [self.remoteOne, self.remoteTwo]) # now let's vote for the proposal with the first MN self.log.info("broadcasting votes for the proposal now..") voteResult = self.ownerOne.mnbudgetvote("alias", proposalHash, "yes", self.masternodeOneAlias) assert_equal(voteResult["detail"][0]["result"], "success") # check that the vote was accepted everywhere self.stake(1, [self.remoteOne, self.remoteTwo]) self.check_vote_existence(firstProposalName, self.mnOneTxHash, "YES") self.log.info("all good, MN1 vote accepted everywhere!") # now let's vote for the proposal with the second MN voteResult = self.ownerTwo.mnbudgetvote("alias", proposalHash, "yes", self.masternodeTwoAlias) assert_equal(voteResult["detail"][0]["result"], "success") # check that the vote was accepted everywhere self.stake(1, [self.remoteOne, self.remoteTwo]) self.check_vote_existence(firstProposalName, self.mnTwoTxHash, "YES") self.log.info("all good, MN2 vote accepted everywhere!") # Now check the budget blockStart = nextSuperBlockHeight blockEnd = blockStart + firstProposalCycles * 145 TotalPayment = firstProposalAmountPerCycle * firstProposalCycles Allotted = firstProposalAmountPerCycle RemainingPaymentCount = firstProposalCycles expected_budget = [ self.get_proposal_obj(firstProposalName, firstProposalLink, proposalHash, proposalFeeTxId, blockStart, blockEnd, firstProposalCycles, RemainingPaymentCount, firstProposalAddress, 1, 2, 0, 0, Decimal(str(TotalPayment)), Decimal(str(firstProposalAmountPerCycle)), True, True, Decimal(str(Allotted)), Decimal(str(Allotted))) ] self.check_budgetprojection(expected_budget) # Quick block count check. assert_equal(self.ownerOne.getblockcount(), 276) self.log.info("starting budget finalization sync test..") self.stake(5, [self.remoteOne, self.remoteTwo]) # assert that there is no budget finalization first. assert_true(len(self.ownerOne.mnfinalbudget("show")) == 0) # suggest the budget finalization and confirm the tx (+4 blocks). budgetFinHash = self.broadcastbudgetfinalization( self.miner, with_ping_mns=[self.remoteOne, self.remoteTwo]) assert (budgetFinHash != "") time.sleep(1) self.log.info("checking budget finalization sync..") self.check_budget_finalization_sync(0, "OK") self.log.info( "budget finalization synced!, now voting for the budget finalization.." ) self.ownerOne.mnfinalbudget("vote-many", budgetFinHash) self.ownerTwo.mnfinalbudget("vote-many", budgetFinHash) self.stake(2, [self.remoteOne, self.remoteTwo]) self.log.info("checking finalization votes..") self.check_budget_finalization_sync(2, "OK") self.stake(8, [self.remoteOne, self.remoteTwo]) addrInfo = self.miner.listreceivedbyaddress(0, False, False, firstProposalAddress) assert_equal(addrInfo[0]["amount"], firstProposalAmountPerCycle) self.log.info("budget proposal paid!, all good") # Check that the proposal info returns updated payment count expected_budget[0]["RemainingPaymentCount"] -= 1 self.check_budgetprojection(expected_budget)
assert_equal( retrieved_cert['amount'], amount_cert_1[0]["amount"]) # Certificate amount has matured assert_equal(retrieved_cert['details'][0]['category'], "receive") assert_equal( retrieved_cert['details'][0]['amount'], amount_cert_1[0]["amount"] ) # In cert details you can see the actual amount transferred assert_equal(self.nodes[1].getwalletinfo()['immature_balance'], Decimal(0)) utxos_Node1 = self.nodes[1].listunspent() cert_epoch_0_availalble = False for utxo in utxos_Node1: if ("certified" in utxo.keys()): cert_epoch_0_availalble = True assert_true(utxo["txid"] == cert_epoch_0) assert_true(cert_epoch_0_availalble) mark_logs( "Checking Node1 balance is duly updated,".format(epoch_number), self.nodes, DEBUG_MODE) assert_equal(bal_after_cert_2, bal_before_cert_2 + amount_cert_1[0]["amount"]) Node2_bal_before_cert_expenditure = self.nodes[2].getbalance("", 0) mark_logs( "Checking that Node1 can spend coins received from bwd transfer in previous epoch", self.nodes, DEBUG_MODE) mark_logs( "Node 1 sends {} coins to node2...".format( amount_cert_1[0]["amount"] / 2), self.nodes, DEBUG_MODE)
# create with a missing mandatory key in input #------------------------------------------------ cmdInput = { 'version': 0, 'withdrawalEpochLength': 10, 'toaddress': toaddress, 'fee': fee, 'wCertVk': vk, 'customData': "bb" * 1024 } mark_logs("\nNode 1 create SC with duplicate key in input", self.nodes, DEBUG_MODE) try: self.nodes[1].sc_create(cmdInput) assert_true(False) except JSONRPCException, e: errorString = e.error['message'] mark_logs(errorString, self.nodes, DEBUG_MODE) assert_true("amount" in errorString) # create with a bad value for amount #------------------------------------------------ cmdInput = { 'version': 0, 'withdrawalEpochLength': 10, 'toaddress': toaddress, 'amount': -0.1, 'fee': fee, 'wCertVk': vk, 'constant': constant
def run_test_release(self, release, height): self.generate_and_sync(height + 1) taddr = self.nodes[1].getnewaddress() zaddr1 = self.nodes[1].z_getnewaddress(release) zaddrExt = self.nodes[3].z_getnewaddress(release) self.nodes[0].sendtoaddress(taddr, 4.0) self.generate_and_sync(height + 2) # Send 1 ZEC to zaddr1 opid = self.nodes[1].z_sendmany(taddr, [ { 'address': zaddr1, 'amount': 1, 'memo': my_memo }, { 'address': zaddrExt, 'amount': 2 }, ]) txid = wait_and_assert_operationid_status(self.nodes[1], opid) self.sync_all() # Decrypted transaction details should be correct pt = self.nodes[1].z_viewtransaction(txid) assert_equal(pt['txid'], txid) assert_equal(len(pt['spends']), 0) assert_equal(len(pt['outputs']), 1 if release == 'sprout' else 2) # Output orders can be randomized, so we check the output # positions and contents separately outputs = [] assert_equal(pt['outputs'][0]['type'], release) if release == 'sprout': assert_equal(pt['outputs'][0]['js'], 0) jsOutputPrev = pt['outputs'][0]['jsOutput'] elif pt['outputs'][0]['address'] == zaddr1: assert_equal(pt['outputs'][0]['outgoing'], False) assert_equal(pt['outputs'][0]['memoStr'], my_memo_str) else: assert_equal(pt['outputs'][0]['outgoing'], True) outputs.append({ 'address': pt['outputs'][0]['address'], 'value': pt['outputs'][0]['value'], 'valueZat': pt['outputs'][0]['valueZat'], 'memo': pt['outputs'][0]['memo'], }) if release != 'sprout': assert_equal(pt['outputs'][1]['type'], release) if pt['outputs'][1]['address'] == zaddr1: assert_equal(pt['outputs'][1]['outgoing'], False) assert_equal(pt['outputs'][1]['memoStr'], my_memo_str) else: assert_equal(pt['outputs'][1]['outgoing'], True) outputs.append({ 'address': pt['outputs'][1]['address'], 'value': pt['outputs'][1]['value'], 'valueZat': pt['outputs'][1]['valueZat'], 'memo': pt['outputs'][1]['memo'], }) assert ({ 'address': zaddr1, 'value': Decimal('1'), 'valueZat': 100000000, 'memo': my_memo, } in outputs) if release != 'sprout': assert ({ 'address': zaddrExt, 'value': Decimal('2'), 'valueZat': 200000000, 'memo': no_memo, } in outputs) r = self.nodes[1].z_listreceivedbyaddress(zaddr1) assert_equal(0, len(r), "Should have received no confirmed note") # No confirmation required, one note should be present r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0) assert_equal(1, len(r), "Should have received one (unconfirmed) note") assert_equal(txid, r[0]['txid']) assert_equal(1, r[0]['amount']) assert_false(r[0]['change'], "Note should not be change") assert_equal(my_memo, r[0]['memo']) # Confirm transaction (1 ZEC from taddr to zaddr1) self.generate_and_sync(height + 3) # Require one confirmation, note should be present assert_equal(r, self.nodes[1].z_listreceivedbyaddress(zaddr1)) # Generate some change by sending part of zaddr1 to zaddr2 txidPrev = txid zaddr2 = self.nodes[1].z_getnewaddress(release) opid = self.nodes[1].z_sendmany(zaddr1, [{ 'address': zaddr2, 'amount': 0.6 }]) txid = wait_and_assert_operationid_status(self.nodes[1], opid) self.sync_all() self.generate_and_sync(height + 4) # Decrypted transaction details should be correct pt = self.nodes[1].z_viewtransaction(txid) assert_equal(pt['txid'], txid) assert_equal(len(pt['spends']), 1) assert_equal(len(pt['outputs']), 2) assert_equal(pt['spends'][0]['type'], release) assert_equal(pt['spends'][0]['txidPrev'], txidPrev) if release == 'sprout': assert_equal(pt['spends'][0]['js'], 0) # jsSpend is randomised during transaction creation assert_equal(pt['spends'][0]['jsPrev'], 0) assert_equal(pt['spends'][0]['jsOutputPrev'], jsOutputPrev) else: assert_equal(pt['spends'][0]['spend'], 0) assert_equal(pt['spends'][0]['outputPrev'], 0) assert_equal(pt['spends'][0]['address'], zaddr1) assert_equal(pt['spends'][0]['value'], Decimal('1.0')) assert_equal(pt['spends'][0]['valueZat'], 100000000) # Output orders can be randomized, so we check the output # positions and contents separately outputs = [] assert_equal(pt['outputs'][0]['type'], release) if release == 'sapling': assert_equal(pt['outputs'][0]['output'], 0) assert_equal(pt['outputs'][0]['outgoing'], False) outputs.append({ 'address': pt['outputs'][0]['address'], 'value': pt['outputs'][0]['value'], 'valueZat': pt['outputs'][0]['valueZat'], 'memo': pt['outputs'][0]['memo'], }) assert_equal(pt['outputs'][1]['type'], release) if release == 'sapling': assert_equal(pt['outputs'][1]['output'], 1) assert_equal(pt['outputs'][1]['outgoing'], False) outputs.append({ 'address': pt['outputs'][1]['address'], 'value': pt['outputs'][1]['value'], 'valueZat': pt['outputs'][1]['valueZat'], 'memo': pt['outputs'][1]['memo'], }) assert ({ 'address': zaddr2, 'value': Decimal('0.6'), 'valueZat': 60000000, 'memo': no_memo, } in outputs) assert ({ 'address': zaddr1, 'value': Decimal('0.3999'), 'valueZat': 39990000, 'memo': no_memo, } in outputs) # zaddr1 should have a note with change r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0) r = sorted(r, key=lambda received: received['amount']) assert_equal(2, len(r), "zaddr1 Should have received 2 notes") assert_equal(txid, r[0]['txid']) assert_equal(Decimal('0.4') - fee, r[0]['amount']) assert_true(r[0]['change'], "Note valued at (0.4-fee) should be change") assert_equal(no_memo, r[0]['memo']) # The old note still exists (it's immutable), even though it is spent assert_equal(Decimal('1.0'), r[1]['amount']) assert_false(r[1]['change'], "Note valued at 1.0 should not be change") assert_equal(my_memo, r[1]['memo']) # zaddr2 should not have change r = self.nodes[1].z_listreceivedbyaddress(zaddr2, 0) r = sorted(r, key=lambda received: received['amount']) assert_equal(1, len(r), "zaddr2 Should have received 1 notes") assert_equal(txid, r[0]['txid']) assert_equal(Decimal('0.6'), r[0]['amount']) assert_false(r[0]['change'], "Note valued at 0.6 should not be change") assert_equal(no_memo, r[0]['memo'])
def run_test(self): # add zaddr to node 0 myzaddr0 = self.nodes[0].z_getnewaddress('sprout') # send node 0 taddr to zaddr to get out of coinbase # Tests using the default cached chain have one address per coinbase output mytaddr = get_coinbase_address(self.nodes[0]) recipients = [] recipients.append({ "address": myzaddr0, "amount": Decimal('10.0') - Decimal('0.0001') }) # utxo amount less fee wait_and_assert_operationid_status(self.nodes[0], self.nodes[0].z_sendmany( mytaddr, recipients), timeout=120) self.sync_all() self.nodes[0].generate(1) self.sync_all() # add zaddr to node 2 myzaddr = self.nodes[2].z_getnewaddress('sprout') # import node 2 zaddr into node 1 myzkey = self.nodes[2].z_exportkey(myzaddr) self.nodes[1].z_importkey(myzkey) # encrypt node 1 wallet and wait to terminate self.nodes[1].encryptwallet("test") bitcoind_processes[1].wait() # restart node 1 self.nodes[1] = start_node(1, self.options.tmpdir) connect_nodes_bi(self.nodes, 0, 1) connect_nodes_bi(self.nodes, 1, 2) self.sync_all() # send node 0 zaddr to note 2 zaddr recipients = [] recipients.append({"address": myzaddr, "amount": 7.0}) wait_and_assert_operationid_status(self.nodes[0], self.nodes[0].z_sendmany( myzaddr0, recipients), timeout=120) self.sync_all() self.nodes[0].generate(1) self.sync_all() # check zaddr balance zsendmanynotevalue = Decimal('7.0') assert_equal(self.nodes[2].z_getbalance(myzaddr), zsendmanynotevalue) assert_equal(self.nodes[1].z_getbalance(myzaddr), zsendmanynotevalue) # add zaddr to node 3 myzaddr3 = self.nodes[3].z_getnewaddress('sprout') # send node 2 zaddr to note 3 zaddr recipients = [] recipients.append({"address": myzaddr3, "amount": 2.0}) wait_and_assert_operationid_status(self.nodes[2], self.nodes[2].z_sendmany( myzaddr, recipients), timeout=120) self.sync_all() self.nodes[2].generate(1) self.sync_all() # check zaddr balance zsendmany2notevalue = Decimal('2.0') zsendmanyfee = Decimal('0.0001') zaddrremaining = zsendmanynotevalue - zsendmany2notevalue - zsendmanyfee assert_equal(self.nodes[3].z_getbalance(myzaddr3), zsendmany2notevalue) assert_equal(self.nodes[2].z_getbalance(myzaddr), zaddrremaining) # Parallel encrypted wallet can't cache nullifiers for received notes, # and therefore can't detect spends. So it sees a balance corresponding # to the sum of both notes it received (one as change). # TODO: Devise a way to avoid this issue (#1528) assert_equal(self.nodes[1].z_getbalance(myzaddr), zsendmanynotevalue + zaddrremaining) # send node 2 zaddr on node 1 to taddr # This requires that node 1 be unlocked, which triggers caching of # uncached nullifiers. self.nodes[1].walletpassphrase("test", 600) mytaddr1 = self.nodes[1].getnewaddress() recipients = [] recipients.append({"address": mytaddr1, "amount": 1.0}) wait_and_assert_operationid_status(self.nodes[1], self.nodes[1].z_sendmany( myzaddr, recipients), timeout=120) self.sync_all() self.nodes[1].generate(1) self.sync_all() # check zaddr balance # Now that the encrypted wallet has been unlocked, the note nullifiers # have been cached and spent notes can be detected. Thus the two wallets # are in agreement once more. zsendmany3notevalue = Decimal('1.0') zaddrremaining2 = zaddrremaining - zsendmany3notevalue - zsendmanyfee assert_equal(self.nodes[1].z_getbalance(myzaddr), zaddrremaining2) assert_equal(self.nodes[2].z_getbalance(myzaddr), zaddrremaining2) # Test viewing keys node3mined = Decimal('250.0') assert_equal( { k: Decimal(v) for k, v in self.nodes[3].z_gettotalbalance().items() }, { 'transparent': node3mined, 'private': zsendmany2notevalue, 'total': node3mined + zsendmany2notevalue, }) # add node 1 address and node 2 viewing key to node 3 myzvkey = self.nodes[2].z_exportviewingkey(myzaddr) self.nodes[3].importaddress(mytaddr1) self.nodes[3].z_importviewingkey(myzvkey, 'whenkeyisnew', 1) # Check the address has been imported assert_equal(myzaddr in self.nodes[3].z_listaddresses(), False) assert_equal(myzaddr in self.nodes[3].z_listaddresses(True), True) # Node 3 should see the same received notes as node 2; however, # some of the notes were change for node 2 but not for node 3. # Aside from that the recieved notes should be the same. So, # group by txid and then check that all properties aside from # change are equal. node2Received = dict( [r['txid'], r] for r in self.nodes[2].z_listreceivedbyaddress(myzaddr)) node3Received = dict( [r['txid'], r] for r in self.nodes[3].z_listreceivedbyaddress(myzaddr)) assert_equal(len(node2Received), len(node2Received)) for txid in node2Received: received2 = node2Received[txid] received3 = node3Received[txid] # the change field will be omitted for received3, but all other fields should be shared assert_true(len(received2) >= len(received3)) for key in received2: # check all the properties except for change if key != 'change': assert_equal(received2[key], received3[key]) # Node 3's balances should be unchanged without explicitly requesting # to include watch-only balances assert_equal( { k: Decimal(v) for k, v in self.nodes[3].z_gettotalbalance().items() }, { 'transparent': node3mined, 'private': zsendmany2notevalue, 'total': node3mined + zsendmany2notevalue, }) # Wallet can't cache nullifiers for notes received by addresses it only has a # viewing key for, and therefore can't detect spends. So it sees a balance # corresponding to the sum of all notes the address received. # TODO: Fix this during the Sapling upgrade (via #2277) assert_equal( { k: Decimal(v) for k, v in self.nodes[3].z_gettotalbalance(1, True).items() }, { 'transparent': node3mined + Decimal('1.0'), 'private': zsendmany2notevalue + zsendmanynotevalue + zaddrremaining + zaddrremaining2, 'total': node3mined + Decimal('1.0') + zsendmany2notevalue + zsendmanynotevalue + zaddrremaining + zaddrremaining2, }) # Check individual balances reflect the above assert_equal(self.nodes[3].z_getbalance(mytaddr1), Decimal('1.0')) assert_equal(self.nodes[3].z_getbalance(myzaddr), zsendmanynotevalue + zaddrremaining + zaddrremaining2)
def run_test_release(self, release, height): self.generate_and_sync(height+1) taddr = self.nodes[1].getnewaddress() zaddr1 = self.nodes[1].z_getnewaddress(release) self.nodes[0].sendtoaddress(taddr, 2.0) self.generate_and_sync(height+2) # Send 1 ZEC to zaddr1 opid = self.nodes[1].z_sendmany(taddr, [{'address': zaddr1, 'amount': 1, 'memo': my_memo}]) txid = wait_and_assert_operationid_status(self.nodes[1], opid) self.sync_all() r = self.nodes[1].z_listreceivedbyaddress(zaddr1) assert_equal(0, len(r), "Should have received no confirmed note") # No confirmation required, one note should be present r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0) assert_equal(1, len(r), "Should have received one (unconfirmed) note") assert_equal(txid, r[0]['txid']) assert_equal(1, r[0]['amount']) assert_false(r[0]['change'], "Note should not be change") assert_equal(my_memo, r[0]['memo']) # Confirm transaction (1 ZEC from taddr to zaddr1) self.generate_and_sync(height+3) # Require one confirmation, note should be present assert_equal(r, self.nodes[1].z_listreceivedbyaddress(zaddr1)) # Generate some change by sending part of zaddr1 to zaddr2 zaddr2 = self.nodes[1].z_getnewaddress(release) opid = self.nodes[1].z_sendmany(zaddr1, [{'address': zaddr2, 'amount': 0.6}]) txid = wait_and_assert_operationid_status(self.nodes[1], opid) self.sync_all() self.generate_and_sync(height+4) # zaddr1 should have a note with change r = self.nodes[1].z_listreceivedbyaddress(zaddr1, 0) r = sorted(r, key = lambda received: received['amount']) assert_equal(2, len(r), "zaddr1 Should have received 2 notes") assert_equal(txid, r[0]['txid']) assert_equal(Decimal('0.4')-fee, r[0]['amount']) assert_true(r[0]['change'], "Note valued at (0.4-fee) should be change") assert_equal(no_memo, r[0]['memo']) # The old note still exists (it's immutable), even though it is spent assert_equal(Decimal('1.0'), r[1]['amount']) assert_false(r[1]['change'], "Note valued at 1.0 should not be change") assert_equal(my_memo, r[1]['memo']) # zaddr2 should not have change r = self.nodes[1].z_listreceivedbyaddress(zaddr2, 0) r = sorted(r, key = lambda received: received['amount']) assert_equal(1, len(r), "zaddr2 Should have received 1 notes") assert_equal(txid, r[0]['txid']) assert_equal(Decimal('0.6'), r[0]['amount']) assert_false(r[0]['change'], "Note valued at 0.6 should not be change") assert_equal(no_memo, r[0]['memo'])