示例#1
0
        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 run_test(self):

        '''
        Test the accept and removal of certificates in the mempool, checking that the quality is correctly handled
        and reported as expected in the output of the rpc cmd getaddressmempool().
        This test can be run only if the -addressindex', '-timestampindex', '-spentindex' options are supported by the zend_oo binary
        '''

        logging.info("Generating initial blockchain")
        self.nodes[0].generate(100)
        self.sync_all()
        self.nodes[1].generate(1)
        self.sync_all()

        # reach sidechain fork
        nb = int(self.nodes[0].getblockcount())
        node2_cb_height = 341

        nb_to_gen1 = node2_cb_height - nb
        if nb_to_gen1 > 0:
            mark_logs("Node 0 generates {} block".format(nb_to_gen1), self.nodes, DEBUG_MODE)
            self.nodes[0].generate(nb_to_gen1)
            self.sync_all()

        mark_logs("Node 2 generates 1 block for coinbase to be used after 100 blocks", self.nodes, DEBUG_MODE)
        self.nodes[2].generate(1)
        self.sync_all()
        print("Chain height=", self.nodes[3].getblockcount())

        # reach sidechain fork
        nb = int(self.nodes[0].getblockcount())
        nb_to_gen = MINIMAL_SC_HEIGHT - nb -1
        if nb_to_gen > 0:
            mark_logs("Node 0 generates {} block for reaching sc fork".format(nb_to_gen), self.nodes, DEBUG_MODE)
            self.nodes[0].generate(nb_to_gen)
            self.sync_all()

        print("Chain height=", self.nodes[3].getblockcount())

        safe_guard_size = EPOCH_LENGTH//5
        if safe_guard_size < 2:
            safe_guard_size = 2

        creation_amount = Decimal("1.0")

        prev_epoch_hash = self.nodes[0].getbestblockhash()

        #generate wCertVk and constant
        mcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir)
        vk = mcTest.generate_params("sc1")
        constant = generate_random_field_element_hex()

        # Create a SC
        cmdInput = {
            'version': 0,
            'withdrawalEpochLength': EPOCH_LENGTH,
            'toaddress': "dada",
            'amount': creation_amount,
            'wCertVk': vk,
            'constant': constant
        }

        ret = self.nodes[0].sc_create(cmdInput)
        scid = ret['scid']
        tx_cr = ret['txid']
        scid_swapped = str(swap_bytes(scid))
        mark_logs("tx={} created SC id: {}".format(tx_cr, scid), self.nodes, DEBUG_MODE)
        self.sync_all()

        mark_logs("Node0 confirms Sc creation generating 1 block", self.nodes, DEBUG_MODE)
        self.nodes[0].generate(1)
        sc_creating_height = self.nodes[0].getblockcount()
        self.sync_all()

        mark_logs("Node0 generates {} more blocks to achieve end of withdrawal epochs".format(EPOCH_LENGTH - 1), self.nodes, DEBUG_MODE)
        self.nodes[0].generate(EPOCH_LENGTH - 1)
        self.sync_all()

        mark_logs("Node0 generates 3 more blocks to give spendable funds to node2", self.nodes, DEBUG_MODE)
        bl = self.nodes[0].generate(3)
        #self.nodes[0].generate(1)
        self.sync_all()

        utxos_2 = self.nodes[2].listunspent()
        #pprint.pprint(utxos_2)
        assert_equal(len(utxos_2), 1)
        assert_equal(utxos_2[0]['confirmations'], 101)

        epoch_number, epoch_cum_tree_hash = get_epoch_data(scid, self.nodes[0], EPOCH_LENGTH)

        taddr0 = self.nodes[0].getnewaddress()
        taddr1 = self.nodes[1].getnewaddress()
        taddr2 = self.nodes[2].getnewaddress()

        node0Addr = self.nodes[0].validateaddress(taddr0)['address']
        node1Addr = self.nodes[1].validateaddress(taddr1)['address']
        node2Addr = self.nodes[2].validateaddress(taddr2)['address']

        bwt_amount0      = Decimal("0.10")
        bwt_amount1      = Decimal("0.20")
        bwt_amount2      = Decimal("0.30")

        try:
            #Create proof for WCert
            quality = 1
            amounts = [{"address": node0Addr, "amount": bwt_amount0}]
            proof = mcTest.create_test_proof("sc1", scid_swapped, epoch_number, quality,
                MBTR_SC_FEE, FT_SC_FEE, epoch_cum_tree_hash, constant, [node0Addr], [bwt_amount0])

            mark_logs("Node 0 sends a cert with a bwd transfers of {} coins to Node0 taddr {}".format(bwt_amount0, taddr0), self.nodes, DEBUG_MODE)
            cert_0_top = self.nodes[0].sc_send_certificate(scid, epoch_number, quality,
                epoch_cum_tree_hash, proof, amounts, FT_SC_FEE, MBTR_SC_FEE, CERT_FEE)
            mark_logs("==> certificate is {}".format(cert_0_top), self.nodes, DEBUG_MODE)
            self.sync_all()

            quality = 2
            amounts = [{"address": node1Addr, "amount": bwt_amount1}]
            proof = mcTest.create_test_proof("sc1", scid_swapped, epoch_number, quality,
                MBTR_SC_FEE, FT_SC_FEE, epoch_cum_tree_hash, constant, [node1Addr], [bwt_amount1])

            mark_logs("Node 1 sends a cert with a bwd transfers of {} coins to Node1 taddr {}".format(bwt_amount1, taddr1), self.nodes, DEBUG_MODE)
            cert_1_top = self.nodes[1].sc_send_certificate(scid, epoch_number, quality,
                epoch_cum_tree_hash, proof, amounts, FT_SC_FEE, MBTR_SC_FEE, CERT_FEE)
            mark_logs("==> certificate is {}".format(cert_1_top), self.nodes, DEBUG_MODE)

            self.sync_all()

            quality = 3
            amounts = [{"address": node2Addr, "amount": bwt_amount2}]
            proof = mcTest.create_test_proof("sc1", scid_swapped, epoch_number, quality,
                MBTR_SC_FEE, FT_SC_FEE, epoch_cum_tree_hash, constant, [node2Addr], [bwt_amount2])

            mark_logs("Node 2 sends a cert with a bwd transfers of {} coins to Node2 taddr {}".format(bwt_amount2, taddr2), self.nodes, DEBUG_MODE)
            cert_2_top = self.nodes[2].sc_send_certificate(scid, epoch_number, quality,
                epoch_cum_tree_hash, proof, amounts, FT_SC_FEE, MBTR_SC_FEE, CERT_FEE)
            mark_logs("==> certificate is {}".format(cert_2_top), self.nodes, DEBUG_MODE)

            self.sync_all()

            cert_hex = self.nodes[2].getrawtransaction(cert_2_top)

        except JSONRPCException as e:
            errorString = e.error['message']
            mark_logs("Send certificate failed with reason {}".format(errorString), self.nodes, DEBUG_MODE)
            assert(False)

        print("Calling getcertmaturityinfo for cert {} , it should be in mempool, non top quality".format(cert_0_top))
        ret = self.nodes[0].getcertmaturityinfo(cert_0_top)
        assert_equal(ret['blocksToMaturity'], -1)
        assert_equal(ret['certificateState'], "LOW_QUALITY_MEMPOOL")
        assert_equal(ret['maturityHeight'], -1)

        print("Calling getcertmaturityinfo for cert {} , it should be in mempool, top quality".format(cert_2_top))
        ret = self.nodes[0].getcertmaturityinfo(cert_2_top)
        assert_equal(ret['blocksToMaturity'], -1)
        assert_equal(ret['certificateState'], "TOP_QUALITY_MEMPOOL")
        assert_equal(ret['maturityHeight'], -1)

        addr_list = []
        addr_list.append(taddr0)
        addr_list.append(taddr1)
        addr_list.append(taddr2)

        args = {"addresses": addr_list} 
        ret = self.nodes[3].getaddressmempool(args)
        #pprint.pprint(ret)

        for x in ret:
            addr = x['address']
            sat = x['satoshis']
            if sat < 0:
                # skip inputs
                continue

            cert_id = x['txid']
            out_status = x['outstatus']
            if addr == taddr0:
                assert_equal(sat, to_satoshis(bwt_amount0)) 
                assert_equal(cert_id, cert_0_top)
                assert_equal(out_status, 2)
            if addr == taddr1:
                assert_equal(sat, to_satoshis(bwt_amount1)) 
                assert_equal(cert_id, cert_1_top)
                assert_equal(out_status, 2)
            if addr == taddr2:
                assert_equal(sat, to_satoshis(bwt_amount2)) 
                assert_equal(cert_id, cert_2_top)
                assert_equal(out_status, 1)

        # start first epoch + 2*epocs + safe guard
        bwtMaturityHeight = (sc_creating_height-1) + 2*EPOCH_LENGTH + safe_guard_size

        # revert last 3 blocks, thus causing the eviction of top quality cert from mempool
        # since its input, which is a coinbase, is not mature anymore
        mark_logs("Nodes revert last 3 blocks", self.nodes, DEBUG_MODE)
        for i in range(0, NUMB_OF_NODES):
            self.nodes[i].invalidateblock(bl[0])
        self.sync_all()

        # cert_2_top is not in mempool, has been removed
        for i in range(0, NUMB_OF_NODES):
            assert_equal(False, cert_2_top in self.nodes[i].getrawmempool())

        ret = self.nodes[3].getaddressmempool(args)

        for x in ret:
            addr = x['address']

            # last top quality cert has been removed from mempool address data too
            assert_false(addr == taddr2)

            sat = x['satoshis']
            if sat < 0:
                # skip inputs
                continue

            cert_id = x['txid']
            out_status = x['outstatus']
            if addr == taddr0:
                assert_equal(sat, to_satoshis(bwt_amount0)) 
                assert_equal(cert_id, cert_0_top)
                assert_equal(out_status, 2)
            if addr == taddr1:
                assert_equal(sat, to_satoshis(bwt_amount1)) 
                assert_equal(cert_id, cert_1_top)
                # last superseeded quality cert has been promoted to top
                assert_equal(out_status, 1)


        mark_logs("Node0 generates 3 more block", self.nodes, DEBUG_MODE)
        self.nodes[0].generate(3)
        self.sync_all()

        # coinbase utxo in node2 wallet is spendable again
        utxos_2 = self.nodes[2].listunspent()
        assert_equal(len(utxos_2), 1)
        assert_equal(utxos_2[0]['confirmations'], 101)

        mark_logs("Node2 resend a certificate", self.nodes, DEBUG_MODE)
        try:
            # slightly increase the fee, just for not having the same cert id hash. The reason is that an inventory already
            # known (and this would be since already broadcasted and then evicted) are not broadcasted by th p2p network
            new_cert_fee = CERT_FEE + Decimal(0.00001)
            cert_2_top_retried = self.nodes[2].sc_send_certificate(scid, epoch_number, quality,
                epoch_cum_tree_hash, proof, amounts, FT_SC_FEE, MBTR_SC_FEE, new_cert_fee)

            mark_logs("==> certificate is {}".format(cert_2_top_retried), self.nodes, DEBUG_MODE)
            assert_true(cert_2_top_retried != cert_2_top)

            self.sync_all()

        except JSONRPCException as e:
            errorString = e.error['message']
            mark_logs(errorString, self.nodes, DEBUG_MODE)
            assert(False)

        assert_true(cert_2_top_retried in self.nodes[0].getrawmempool())

        # the certificate in blockchain is still the top quality
        print("Calling getcertmaturityinfo for cert {}".format(cert_1_top))
        ret = self.nodes[3].getcertmaturityinfo(cert_1_top)
        #pprint.pprint(ret)

        nb = self.nodes[3].getblockcount()
        bl_to_mat = bwtMaturityHeight - nb 
        print("nb = {}, bwtMaturityHeight = {}".format(nb, bwtMaturityHeight))
        assert_equal(ret['blocksToMaturity'], bl_to_mat)
        assert_equal(ret['certificateState'], "IMMATURE")
        assert_equal(ret['maturityHeight'], bwtMaturityHeight)

        mark_logs("Calling getcertmaturityinfo for cert {} ...".format(cert_2_top_retried), self.nodes, DEBUG_MODE)
        try:
            ret = self.nodes[3].getcertmaturityinfo(cert_2_top_retried)
            assert_equal(ret['blocksToMaturity'], -1)
            assert_equal(ret['certificateState'], "TOP_QUALITY_MEMPOOL")
            assert_equal(ret['maturityHeight'], -1)
        except JSONRPCException as e:
            errorString = e.error['message']
            mark_logs(errorString, self.nodes, DEBUG_MODE)

        mark_logs("Calling getaddressmempool for cert {}".format(cert_2_top_retried), self.nodes, DEBUG_MODE)
        ret = self.nodes[3].getaddressmempool(args)
        #pprint.pprint(ret)

        for x in ret:
            sat = x['satoshis']
            if sat < 0:
                # skip inputs
                continue

            addr       = x['address']
            cert_id    = x['txid']
            out_status = x['outstatus']

            assert_equal(addr, taddr2)
            assert_equal(sat, to_satoshis(bwt_amount2)) 
            assert_equal(cert_id, cert_2_top_retried)
            assert_equal(out_status, 1)

        
        # create wCert proof
        mark_logs("Node 0 sends a cert with 2 outs and 2 bwts", self.nodes, DEBUG_MODE)
        quality = 10
        am_bwt1 = Decimal(0.011)
        am_bwt2 = Decimal(0.022)
        am_out  = Decimal(0.001)

        # python orders dictionaries by key, therefore we must use the same order when creating the proof
        pkh_arr = []
        am_bwt_arr = []
        raw_bwt_outs = [
            {"address": node1Addr, "amount": am_bwt1},
            {"address": node2Addr, "amount": am_bwt2}
        ]
        for entry in raw_bwt_outs:
            pkh_arr.append(entry["address"])
            am_bwt_arr.append(entry["amount"])
 
        proof = mcTest.create_test_proof(
            "sc1", scid_swapped, epoch_number, quality, MBTR_SC_FEE, FT_SC_FEE, epoch_cum_tree_hash, constant,
            pkh_arr, am_bwt_arr)
        
        utx, change = get_spendable(self.nodes[0], CERT_FEE + am_out)
        raw_inputs  = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]

        # do not use the same address, this is not supported (and python would prevent it anyway since this is a dictionary)
        taddr3 = self.nodes[3].getnewaddress()
        raw_outs    = { taddr0: change, taddr3: am_out }

        raw_params = {
            "scid": scid,
            "quality": quality,
            "endEpochCumScTxCommTreeRoot": epoch_cum_tree_hash,
            "scProof": proof,
            "withdrawalEpochNumber": epoch_number
        }
        raw_cert = []
        cert_last = []

        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 as e:
            errorString = e.error['message']
            print("\n======> ", errorString)
            assert_true(False)

        #pprint.pprint(self.nodes[0].decoderawcertificate(signed_cert['hex']))

        try:
            cert_last = self.nodes[0].sendrawtransaction(signed_cert['hex'])
            self.sync_all()
        except JSONRPCException as e:
            errorString = e.error['message']
            print("======> ", errorString, "\n")
            assert_true(False)

        addr_list.append(taddr3)
        args = {"addresses": addr_list} 
        mark_logs("Calling getaddressmempool for cert {}".format(cert_last), self.nodes, DEBUG_MODE)
        ret = self.nodes[3].getaddressmempool(args)
        #pprint.pprint(ret)

        for x in ret:
            sat = x['satoshis']
            if sat < 0:
                # skip inputs
                continue

            addr = x['address']
            cert_id = x['txid']
            out_status = x['outstatus']

            # ordinary outputs
            if addr == taddr0:
                assert_equal(sat, to_satoshis(change)) 
                assert_equal(out_status, 0)
            if addr == taddr3:
                assert_equal(sat, to_satoshis(am_out)) 
                assert_equal(out_status, 0)

            # certificates
            if addr == taddr2:
                # two certificates refer to this address, the latest is top quality, the former has been superseeded 
                if cert_id == cert_last:
                    assert_equal(sat, to_satoshis(am_bwt2)) 
                    assert_equal(out_status, 1)
                if cert_id == cert_2_top_retried:
                    assert_equal(sat, to_satoshis(bwt_amount2)) 
                    assert_equal(out_status, 2)
            if addr == taddr1:
                assert_equal(cert_id, cert_last)
                assert_equal(sat, to_satoshis(am_bwt1)) 
                assert_equal(out_status, 1)

        # the certificate in blockchain is still the top quality
        print("Calling getcertmaturityinfo for cert {}".format(cert_1_top))
        ret = self.nodes[3].getcertmaturityinfo(cert_1_top)
        pprint.pprint(ret)

        bl = self.nodes[0].generate(1)
        self.sync_all()

        print("Calling getcertmaturityinfo for cert {}".format(cert_1_top))
        ret = self.nodes[3].getcertmaturityinfo(cert_1_top)
        pprint.pprint(ret)

        print("Calling getcertmaturityinfo for cert {}".format(cert_last))
        ret = self.nodes[3].getcertmaturityinfo(cert_last)
        pprint.pprint(ret)

        mark_logs("\nInvalidating the last block and checking RPC call results...", self.nodes, DEBUG_MODE)
        for i in range(0, NUMB_OF_NODES):
            self.nodes[i].invalidateblock(bl[0])
        self.sync_all()

        print("Calling getcertmaturityinfo for cert {} , it should be in mempool".format(cert_last))
        assert_true(cert_last in self.nodes[3].getrawmempool())
        ret = self.nodes[3].getcertmaturityinfo(cert_last)
        pprint.pprint(ret)
        assert_equal(ret['blocksToMaturity'], -1)
        assert_equal(ret['certificateState'], "TOP_QUALITY_MEMPOOL")
        assert_equal(ret['maturityHeight'], -1)

        print("Clearing the mempool of all nodes...")
        for i in range(0, NUMB_OF_NODES):
            self.nodes[i].clearmempool()
        self.sync_all()

        for i in range(0, NUMB_OF_NODES):
            assert_equal(len(self.nodes[i].getrawmempool()), 0)

        print("Calling getcertmaturityinfo for cert {} , it shouldn't be in mempool anymore".format(cert_last))
        assert_false(cert_last in self.nodes[3].getrawmempool())
        ret = self.nodes[3].getcertmaturityinfo(cert_last)
        pprint.pprint(ret)
        assert_equal(ret['blocksToMaturity'], -1)
        assert_equal(ret['certificateState'], "INVALID")
        assert_equal(ret['maturityHeight'], -1)

        ret = self.nodes[1].verifychain(4, 0)
        assert_equal(ret, True)
示例#3
0
class sc_cert_getraw(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', '-debug=zendoo_mc_cryptolib',
                '-scproofqueuesize=0', '-logtimemicros=1'
            ],
                        [
                            '-debug=py', '-debug=sc', '-debug=mempool',
                            '-debug=net', '-debug=cert',
                            '-debug=zendoo_mc_cryptolib',
                            '-scproofqueuesize=0', '-logtimemicros=1'
                        ],
                        [
                            '-txindex=1', '-debug=py', '-debug=sc',
                            '-debug=mempool', '-debug=net', '-debug=cert',
                            '-debug=zendoo_mc_cryptolib',
                            '-scproofqueuesize=0', '-logtimemicros=1'
                        ]])

        connect_nodes_bi(self.nodes, 0, 1)
        connect_nodes_bi(self.nodes, 1, 2)
        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):
        '''
        The test creates a sc, send funds to it and then sends a certificate to it,
        Then test that getrawtransaction decodes correctly tx and cert when possible. 
        '''

        # forward transfer amounts
        creation_amount = Decimal("0.5")
        fwt_amount = Decimal("50")
        bwt_amount = Decimal("50")

        # 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 {} block".format(MINIMAL_SC_HEIGHT),
                  self.nodes, DEBUG_MODE)
        self.nodes[0].generate(MINIMAL_SC_HEIGHT)
        self.sync_all()

        # SC creation
        #generate wCertVk and constant
        mcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir)
        vk_tag = "sc1"
        vk = mcTest.generate_params(vk_tag)
        constant = generate_random_field_element_hex()
        cmdInput = {
            "version": 0,
            "withdrawalEpochLength": EPOCH_LENGTH,
            "toaddress": "dada",
            "amount": creation_amount,
            "wCertVk": vk,
            "constant": constant,
        }

        ret = self.nodes[1].sc_create(cmdInput)

        creating_tx = ret['txid']
        scid = ret['scid']
        scid_swapped = str(swap_bytes(scid))
        mark_logs(
            "Node 1 created the SC spending {} coins via tx {}.".format(
                creation_amount, creating_tx), self.nodes, DEBUG_MODE)
        self.sync_all()

        decoded_tx_mempool = self.nodes[1].getrawtransaction(creating_tx, 1)
        assert_equal(scid, decoded_tx_mempool['vsc_ccout'][0]['scid'])

        decoded_tx_mempool_hex = self.nodes[1].getrawtransaction(creating_tx)
        dec = self.nodes[1].decoderawtransaction(decoded_tx_mempool_hex)
        assert_equal(creating_tx, dec['txid'])
        assert_equal(scid, dec['vsc_ccout'][0]['scid'])

        mark_logs("Node0 confirms Sc creation generating 1 block", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        sc_creating_height = self.nodes[0].getblockcount()
        self.sync_all()

        decoded_tx_notxindex = self.nodes[1].getrawtransaction(creating_tx, 1)
        assert_equal(decoded_tx_mempool['hex'], decoded_tx_notxindex['hex'])

        decoded_tx_txindex = self.nodes[2].getrawtransaction(creating_tx, 1)
        assert_equal(decoded_tx_mempool['hex'], decoded_tx_txindex['hex'])

        # Fwd Transfer to Sc
        mark_logs("Node0 sends fwd transfer", self.nodes, DEBUG_MODE)

        mc_return_address = self.nodes[0].getnewaddress()
        cmdInput = [{
            'toaddress': "abcd",
            'amount': fwt_amount,
            "scid": scid,
            'mcReturnAddress': mc_return_address
        }]
        fwd_tx = self.nodes[0].sc_send(cmdInput)

        self.sync_all()

        decoded_tx_mempool = self.nodes[1].getrawtransaction(fwd_tx, 1)
        assert_equal(scid, decoded_tx_mempool['vft_ccout'][0]['scid'])

        mark_logs("Node0 confirms fwd transfer generating 1 block", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        self.sync_all()

        decoded_tx_notxindex = self.nodes[1].getrawtransaction(fwd_tx, 1)
        assert_equal(decoded_tx_mempool['hex'], decoded_tx_notxindex['hex'])
        decoded_tx_txindex = self.nodes[2].getrawtransaction(fwd_tx, 1)
        assert_equal(decoded_tx_mempool['hex'], decoded_tx_txindex['hex'])

        mark_logs(
            "Node0 generating 3 more blocks to achieve end of withdrawal epoch",
            self.nodes, DEBUG_MODE)
        self.nodes[0].generate(3)
        self.sync_all()

        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)

        addr_node1 = self.nodes[1].getnewaddress()
        amount_cert_1 = [{"address": addr_node1, "amount": bwt_amount}]

        #Create proof for WCert
        quality = 0
        proof = mcTest.create_test_proof(vk_tag, scid_swapped, epoch_number,
                                         quality, MBTR_SC_FEE, FT_SC_FEE,
                                         epoch_cum_tree_hash, constant,
                                         [addr_node1], [bwt_amount])

        mark_logs(
            "Node 0 performs a bwd transfer of {} coins to Node1 address {}".
            format(amount_cert_1[0]["address"],
                   amount_cert_1[0]["amount"]), self.nodes, DEBUG_MODE)
        try:
            cert_epoch_0 = 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)
            mark_logs("Certificate is {}".format(cert_epoch_0), self.nodes,
                      DEBUG_MODE)
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(
                "Send certificate failed with reason {}".format(errorString),
                self.nodes, DEBUG_MODE)
            assert (False)

        self.sync_all()

        decoded_cert_mempool = self.nodes[1].getrawtransaction(cert_epoch_0, 1)
        decoded_cert_mempool2 = self.nodes[1].getrawtransaction(
            cert_epoch_0, 1)
        assert_equal(decoded_cert_mempool, decoded_cert_mempool2)
        assert_equal(scid, decoded_cert_mempool['cert']['scid'])

        decoded_cert_mempool_hex = self.nodes[1].getrawtransaction(
            cert_epoch_0)
        decoded_cert_mempool_hex2 = self.nodes[1].getrawtransaction(
            cert_epoch_0)
        assert_equal(decoded_cert_mempool_hex, decoded_cert_mempool_hex2)
        dec = self.nodes[2].decoderawtransaction(decoded_cert_mempool_hex)
        assert_equal(cert_epoch_0, dec['txid'])
        assert_equal(scid, dec['cert']['scid'])
        dec2 = self.nodes[2].decoderawtransaction(decoded_cert_mempool_hex)
        assert_equal(dec2, dec)

        mark_logs("Node0 confims bwd transfer generating 1 block", self.nodes,
                  DEBUG_MODE)
        mined = self.nodes[0].generate(1)[0]
        self.sync_all()

        decoded_cert_notxindex = self.nodes[1].getrawtransaction(
            cert_epoch_0, 1)
        assert_equal(decoded_cert_mempool['hex'],
                     decoded_cert_notxindex['hex'])
        decoded_cert_txindex = self.nodes[2].getrawtransaction(cert_epoch_0, 1)
        assert_equal(decoded_cert_mempool['hex'], decoded_cert_txindex['hex'])

        mark_logs(
            "Node0 generating enough blocks to move to new withdrawal epoch",
            self.nodes, DEBUG_MODE)
        self.nodes[0].generate(EPOCH_LENGTH - 1)
        self.sync_all()

        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)

        mark_logs(
            "Generate new certificate for epoch {}. No bwt and no fee are included"
            .format(epoch_number), self.nodes, DEBUG_MODE)

        # Create new proof for WCert
        quality = 1
        proof = mcTest.create_test_proof(vk_tag, scid_swapped, epoch_number,
                                         quality, MBTR_SC_FEE, FT_SC_FEE,
                                         epoch_cum_tree_hash, constant, [], [])

        nullFee = Decimal("0.0")
        try:
            cert_epoch_1 = self.nodes[0].sc_send_certificate(
                scid, epoch_number, quality, epoch_cum_tree_hash, proof, [],
                FT_SC_FEE, MBTR_SC_FEE, nullFee)
            mark_logs("Certificate is {}".format(cert_epoch_1), self.nodes,
                      DEBUG_MODE)
            self.sync_all()
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(
                "Send certificate failed with reason {}".format(errorString),
                self.nodes, DEBUG_MODE)
            assert (False)
示例#4
0
    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)
示例#5
0
class CertMempoolCleanupSplit(BitcoinTestFramework):
    def setup_chain(self):
        print("Initializing test directory " + self.options.tmpdir)
        initialize_chain_clean(self.options.tmpdir, NUMB_OF_NODES)

    def setup_network(self, split=False):
        self.nodes = start_nodes(
            NUMB_OF_NODES,
            self.options.tmpdir,
            extra_args=[[
                '-logtimemicros=1', '-scproofqueuesize=0', '-debug=sc',
                '-debug=py', '-debug=mempool', '-debug=net', '-debug=bench'
            ]] * NUMB_OF_NODES)

        if not split:
            # 2 and 3 are joint only if split==false
            connect_nodes_bi(self.nodes, 2, 3)
            sync_blocks(self.nodes[2:4])
            sync_mempools(self.nodes[2:4])

        connect_nodes_bi(self.nodes, 0, 1)
        connect_nodes_bi(self.nodes, 1, 2)
        self.is_network_split = split
        self.sync_all()

    def split_network(self):
        # Split the network of three nodes into nodes 0-1-2 and 3.
        assert not self.is_network_split
        disconnect_nodes(self.nodes[2], 3)
        disconnect_nodes(self.nodes[3], 2)
        self.is_network_split = True

    def join_network(self):
        # Join the (previously split) network pieces together: 0-1-2-3
        assert self.is_network_split
        connect_nodes_bi(self.nodes, 2, 3)
        connect_nodes_bi(self.nodes, 3, 2)
        time.sleep(2)
        self.is_network_split = False

    def run_test(self):
        '''
        Create a SC, advance two epochs, move to the limit of the safe guard and then split the network. 
        One network part sends fwt, mbtr and a certificate, all of them are stored in mempool.
        The other network part sends a certificate and mines one block reaching a longer chain height.
        When the network is joined, verify that the SC is alive, fwt is still in the mempool of the the
        loosing network part, but cert and mbtr have been removed from those mempool.
        '''

        # prepare some coins
        self.nodes[3].generate(1)
        self.sync_all()
        self.nodes[2].generate(1)
        self.sync_all()
        self.nodes[1].generate(1)
        self.sync_all()
        self.nodes[0].generate(MINIMAL_SC_HEIGHT - 3)
        self.sync_all()
        self.nodes[0].generate(1)
        self.sync_all()

        print "Node0 Chain h = ", self.nodes[0].getblockcount()

        sc_address = "0000000000000000000000000000000000000000000000000000000000000abc"
        sc_epoch_len = EPOCH_LENGTH
        sc_cr_amount = Decimal('12.00000000')

        certMcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir)

        # generate wCertVk and constant
        vk = certMcTest.generate_params("sc1")
        constant = generate_random_field_element_hex()

        cmdInput = {
            'version': 0,
            'withdrawalEpochLength': sc_epoch_len,
            'amount': sc_cr_amount,
            'toaddress': sc_address,
            'wCertVk': vk,
            'constant': constant,
            'mainchainBackwardTransferRequestDataLength': 1
        }

        res = self.nodes[0].sc_create(cmdInput)
        tx = res['txid']
        scid = res['scid']
        scid_swapped = str(swap_bytes(scid))
        self.sync_all()
        mark_logs("tx {} created SC {}".format(tx, scid), self.nodes,
                  DEBUG_MODE)

        dest_addr = self.nodes[1].getnewaddress()
        fe1 = [generate_random_field_element_hex()]

        # advance two epochs
        mark_logs("\nLet 2 epochs pass by...", self.nodes, DEBUG_MODE)

        cert, epoch_number = advance_epoch(certMcTest, self.nodes[0],
                                           self.sync_all, scid, "sc1",
                                           constant, sc_epoch_len)

        mark_logs(
            "\n==> certificate for epoch {} {}".format(epoch_number, cert),
            self.nodes, DEBUG_MODE)

        cert, epoch_number = advance_epoch(certMcTest, self.nodes[0],
                                           self.sync_all, scid, "sc1",
                                           constant, sc_epoch_len)

        mark_logs(
            "\n==> certificate for epoch {} {}l".format(epoch_number, cert),
            self.nodes, DEBUG_MODE)

        ceas_height = self.nodes[0].getscinfo(
            scid, False, False)['items'][0]['ceasingHeight']
        numbBlocks = ceas_height - self.nodes[0].getblockcount(
        ) + sc_epoch_len - 1
        print "Node0 Chain h = ", self.nodes[0].getblockcount()

        mark_logs(
            "\nNode0 generates {} block reaching the sg for the next epoch".
            format(numbBlocks), self.nodes, DEBUG_MODE)
        self.nodes[0].generate(numbBlocks)
        self.sync_all()
        print "Node0 Chain h = ", self.nodes[0].getblockcount()

        bal_initial = self.nodes[0].getscinfo(scid, False,
                                              False)['items'][0]['balance']

        #============================================================================================
        mark_logs("\nSplit network", self.nodes, DEBUG_MODE)
        self.split_network()
        mark_logs("The network is split: 0-1-2 .. 3", self.nodes, DEBUG_MODE)

        # Network part 0-1-2
        print "------------------"
        # use different nodes for sending txes and cert in order to be sure there are no dependancies from each other
        fwt_amount = Decimal("2.0")
        mc_return_address = self.nodes[0].getnewaddress()
        mark_logs(
            "\nNTW part 1) Node0 sends {} coins to SC".format(fwt_amount),
            self.nodes, DEBUG_MODE)
        cmdInput = [{
            'toaddress': "abcd",
            'amount': fwt_amount,
            "scid": scid,
            'mcReturnAddress': mc_return_address
        }]
        tx_fwd = self.nodes[0].sc_send(cmdInput)
        sync_mempools(self.nodes[0:3])

        mark_logs("              Check fwd tx {} is in mempool".format(tx_fwd),
                  self.nodes, DEBUG_MODE)
        assert_true(tx_fwd in self.nodes[0].getrawmempool())

        outputs = [{
            'vScRequestData': fe1,
            'scFee': Decimal("0.001"),
            'scid': scid,
            'mcDestinationAddress': dest_addr
        }]
        cmdParms = {"minconf": 0, "fee": 0.0}
        mark_logs("\nNTW part 1) Node1 creates a tx with a bwt request",
                  self.nodes, DEBUG_MODE)
        try:
            tx_bwt = self.nodes[1].sc_request_transfer(outputs, cmdParms)
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(errorString, self.nodes, DEBUG_MODE)
            assert_true(False)

        sync_mempools(self.nodes[0:3])

        mark_logs("              Check bwd tx {} is in mempool".format(tx_bwt),
                  self.nodes, DEBUG_MODE)
        assert_true(tx_bwt in self.nodes[0].getrawmempool())

        mark_logs("\nNTW part 1) Node2 sends a certificate", self.nodes,
                  DEBUG_MODE)
        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[2], sc_epoch_len)

        bt_amount = Decimal("5.0")
        addr_node1 = self.nodes[1].getnewaddress()
        quality = 10

        proof = certMcTest.create_test_proof("sc1", scid_swapped, epoch_number,
                                             quality, MBTR_SC_FEE, FT_SC_FEE,
                                             epoch_cum_tree_hash, constant,
                                             [addr_node1], [bt_amount])

        amount_cert = [{"address": addr_node1, "amount": bt_amount}]
        try:
            cert_bad = self.nodes[2].sc_send_certificate(
                scid, epoch_number, quality, epoch_cum_tree_hash, proof,
                amount_cert, 0, 0, 0.01)
        except JSONRPCException, e:
            errorString = e.error['message']
            print "Send certificate failed with reason {}".format(errorString)
            assert (False)
示例#6
0
    def run_test(self):
        '''
        Node1 creates a sc and sends to it a certificate with a bwt to Node2 and a fee.
        Node0 mines a block and checks that the cert fee is contained in the coinbase
        Node0 sends a lot of small coins to Node3, who will use them as input for including a fee
        in a new certificate
        '''

        # cross chain transfer amounts
        creation_amount = Decimal("0.5")
        bwt_amount = Decimal("0.4")

        # 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 220 block", self.nodes, DEBUG_MODE)
        self.nodes[0].generate(220)
        self.sync_all()

        #generate wCertVk and constant
        mcTest = MCTestUtils(self.options.tmpdir, self.options.srcdir)
        vk = mcTest.generate_params("sc1")
        constant = generate_random_field_element_hex()

        ret = self.nodes[1].sc_create(EPOCH_LENGTH, "dada", creation_amount,
                                      vk, "", constant)
        creating_tx = ret['txid']
        scid = ret['scid']
        mark_logs(
            "Node 1 created the SC spending {} coins via tx {}.".format(
                creation_amount, creating_tx), self.nodes, DEBUG_MODE)
        self.sync_all()

        decoded_tx = self.nodes[1].getrawtransaction(creating_tx, 1)
        assert_equal(scid, decoded_tx['vsc_ccout'][0]['scid'])
        mark_logs("created SC id: {}".format(scid), self.nodes, DEBUG_MODE)

        mark_logs("Node0 confirms Sc creation generating 1 block", self.nodes,
                  DEBUG_MODE)
        prev_epoch_block_hash = self.nodes[0].getblockhash(
            self.nodes[0].getblockcount())
        self.nodes[0].generate(1)
        self.sync_all()

        # fee can be seen on sender wallet (it is a negative value)
        fee = self.nodes[1].gettransaction(creating_tx)['fee']
        mark_logs("Fee paid for SC creation: {}".format(fee), self.nodes,
                  DEBUG_MODE)

        mark_logs(
            "Node0 generating 4 more blocks to achieve end of withdrawal epoch",
            self.nodes, DEBUG_MODE)
        self.nodes[0].generate(4)
        self.sync_all()

        mark_logs(
            "Sc {} state: {}".format(scid, self.nodes[0].getscinfo(scid)),
            self.nodes, DEBUG_MODE)

        epoch_block_hash, epoch_number = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)
        mark_logs(
            "epoch_number = {}, epoch_block_hash = {}".format(
                epoch_number, epoch_block_hash), self.nodes, DEBUG_MODE)

        pkh_node2 = self.nodes[2].getnewaddress("", True)

        amounts = [{"pubkeyhash": pkh_node2, "amount": bwt_amount}]

        #Create proof for WCert
        quality = 1
        proof = mcTest.create_test_proof("sc1", epoch_number, epoch_block_hash,
                                         prev_epoch_block_hash, quality,
                                         constant, [pkh_node2], [bwt_amount])

        mark_logs(
            "Node 1 performs a bwd transfer of {} coins to Node2 pkh".format(
                bwt_amount, pkh_node2), self.nodes, DEBUG_MODE)
        try:
            cert_good = self.nodes[1].send_certificate(scid, epoch_number,
                                                       quality,
                                                       epoch_block_hash, proof,
                                                       amounts, CERT_FEE)
            assert (len(cert_good) > 0)
            mark_logs("Certificate is {}".format(cert_good), self.nodes,
                      DEBUG_MODE)
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(
                "Send certificate failed with reason {}".format(errorString),
                self.nodes, DEBUG_MODE)
            assert (False)
示例#7
0
    def run_test(self):
        def removekey(d, key='unconf'):
            r = dict(d)
            for k in d:
                if key in k:
                    del r[k]
            return r

        '''
        Node0 creates a SC and sends funds to it, and then sends a cert to it with a bwt to Node1
        Node0 then sends a few tx with fwt to the same SC and then a second cert with a bwt to Node2 
        Node0 than invalidates all the latest blocks one by one checking sc state and checking also
        that a cert remains in mempool until its end epoch is reverted
        Node0 finally generates a sufficient number of blocks for reverting other nodes' chains and
        the test checks their sc state
        '''

        sc_txes = []
        certs = []

        # forward transfer amount
        creation_amount = Decimal("0.5")
        fwt_amount_1 = Decimal("1000.0")
        fwt_amount_2 = Decimal("1.0")
        fwt_amount_3 = Decimal("2.0")
        fwt_amount_4 = Decimal("3.0")

        bwt_amount_1 = Decimal("8.0")
        bwt_amount_2 = Decimal("8.5")

        sc_info = []

        # node 1 earns some coins, they would be available after 100 blocks
        mark_logs("Node 0 generates 1 block", self.nodes, DEBUG_MODE)
        self.nodes[0].generate(1)
        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()

        mark_logs(
            "Node0 creates the SC spending {} coins ...".format(
                creation_amount), self.nodes, DEBUG_MODE)

        #generate wCertVk and constant
        mcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir)
        vk = mcTest.generate_params("sc1")
        constant = generate_random_field_element_hex()
        cmdInput = {
            "version": 0,
            "withdrawalEpochLength": EPOCH_LENGTH,
            "toaddress": "dada",
            "amount": creation_amount,
            "wCertVk": vk,
            "constant": constant,
        }

        ret = self.nodes[0].sc_create(cmdInput)
        creating_tx = ret['txid']
        scid = ret['scid']
        scid_swapped = str(swap_bytes(scid))
        sc_info.append(removekey(self.nodes[0].getscinfo(scid)['items'][0]))

        decoded_tx = self.nodes[0].getrawtransaction(creating_tx, 1)
        assert_equal(scid, decoded_tx['vsc_ccout'][0]['scid'])
        mark_logs("created SC id: {}".format(scid), self.nodes, DEBUG_MODE)

        mark_logs("creating_tx = {}".format(creating_tx), self.nodes,
                  DEBUG_MODE)
        sc_txes.append(creating_tx)
        self.sync_all()

        prev_epoch_block_hash = self.nodes[0].getblockhash(
            self.nodes[0].getblockcount())

        self.refresh_sidechain(sc_info, scid)

        sc_creating_height = self.nodes[0].getblockcount()

        mark_logs(
            "Node 0 performs a fwd transfer of {} coins to SC...".format(
                fwt_amount_1), self.nodes, DEBUG_MODE)
        mc_return_address = self.nodes[0].getnewaddress()
        cmdInput = [{
            'toaddress': "abcd",
            'amount': fwt_amount_1,
            "scid": scid,
            'mcReturnAddress': mc_return_address
        }]
        fwd_tx = self.nodes[0].sc_send(cmdInput)
        print "fwd_tx=" + fwd_tx
        sc_txes.append(fwd_tx)
        self.sync_all()

        self.refresh_sidechain(sc_info, scid)

        addr_node1 = self.nodes[1].getnewaddress()
        addr_node2 = self.nodes[2].getnewaddress()

        mark_logs("...3 more blocks needed for achieving sc coins maturity",
                  self.nodes, DEBUG_MODE)
        self.refresh_sidechain(sc_info, scid)
        self.refresh_sidechain(sc_info, scid)
        self.refresh_sidechain(sc_info, scid)

        mark_logs(
            "##### End epoch block = {}".format(
                self.nodes[0].getbestblockhash()), self.nodes, DEBUG_MODE)

        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)
        mark_logs(
            "epoch_number = {}, epoch_cum_tree_hash = {}".format(
                epoch_number, epoch_cum_tree_hash), self.nodes, DEBUG_MODE)

        mark_logs(
            "Node 0 performs a bwd transfer of {} coins to Node1...".format(
                bwt_amount_1), self.nodes, DEBUG_MODE)
        amounts = []
        amounts.append({"address": addr_node1, "amount": bwt_amount_1})

        #Create proof for WCert
        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_node1], [bwt_amount_1])

        cert = self.nodes[0].sc_send_certificate(scid, epoch_number, quality,
                                                 epoch_cum_tree_hash, proof,
                                                 amounts, FT_SC_FEE,
                                                 MBTR_SC_FEE, CERT_FEE)
        mark_logs("cert = {}".format(cert), self.nodes, DEBUG_MODE)
        certs.append(cert)
        self.sync_all()

        self.refresh_sidechain(sc_info, scid)

        mark_logs(
            "Node 0 performs a fwd transfer of {} coins to SC...".format(
                fwt_amount_2), self.nodes, DEBUG_MODE)
        mc_return_address = self.nodes[0].getnewaddress()
        cmdInput = [{
            'toaddress': "abcd",
            'amount': fwt_amount_2,
            "scid": scid,
            'mcReturnAddress': mc_return_address
        }]
        fwd_tx = self.nodes[0].sc_send(cmdInput)
        mark_logs("fwd_tx = {}".format(fwd_tx), self.nodes, DEBUG_MODE)
        sc_txes.append(fwd_tx)
        self.sync_all()

        self.refresh_sidechain(sc_info, scid)

        mark_logs(
            "Node 0 performs a fwd transfer of {} coins to SC...".format(
                fwt_amount_3), self.nodes, DEBUG_MODE)

        mc_return_address = self.nodes[0].getnewaddress()
        cmdInput = [{
            'toaddress': "abcd",
            'amount': fwt_amount_3,
            "scid": scid,
            'mcReturnAddress': mc_return_address
        }]
        fwd_tx = self.nodes[0].sc_send(cmdInput)

        mark_logs("fwd_tx = {}".format(fwd_tx), self.nodes, DEBUG_MODE)
        sc_txes.append(fwd_tx)
        self.sync_all()

        self.refresh_sidechain(sc_info, scid)

        mark_logs(
            "Node 0 performs a fwd transfer of {} coins to SC...".format(
                fwt_amount_4), self.nodes, DEBUG_MODE)
        mc_return_address = self.nodes[0].getnewaddress()
        cmdInput = [{
            'toaddress': "abcd",
            'amount': fwt_amount_4,
            "scid": scid,
            'mcReturnAddress': mc_return_address
        }]
        fwd_tx = self.nodes[0].sc_send(cmdInput)

        mark_logs("fwd_tx = {}".format(fwd_tx), self.nodes, DEBUG_MODE)
        sc_txes.append(fwd_tx)
        self.sync_all()

        self.refresh_sidechain(sc_info, scid)

        self.refresh_sidechain(sc_info, scid)

        mark_logs(
            "##### End epoch block = {}".format(
                self.nodes[0].getbestblockhash()), self.nodes, DEBUG_MODE)

        self.refresh_sidechain(sc_info, scid)

        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)
        sc_creating_height = self.nodes[0].getscinfo(
            scid)['items'][0]['createdAtBlockHeight']
        epoch_block_hash = self.nodes[0].getblockhash(sc_creating_height - 1 +
                                                      ((epoch_number + 1) *
                                                       EPOCH_LENGTH))

        mark_logs(
            "epoch_number = {}, epoch_cum_tree_hash = {}".format(
                epoch_number, epoch_cum_tree_hash), self.nodes, DEBUG_MODE)

        mark_logs(
            "Node 0 performs a bwd transfer of {} coins to Node2...".format(
                bwt_amount_2), self.nodes, DEBUG_MODE)
        amounts = []
        amounts.append({"address": addr_node2, "amount": bwt_amount_2})

        #Create proof for WCert
        quality = 1
        proof = mcTest.create_test_proof("sc1", scid_swapped, epoch_number,
                                         quality, MBTR_SC_FEE, FT_SC_FEE,
                                         epoch_cum_tree_hash, constant,
                                         [addr_node2], [bwt_amount_2])

        cert = self.nodes[0].sc_send_certificate(scid, epoch_number, quality,
                                                 epoch_cum_tree_hash, proof,
                                                 amounts, FT_SC_FEE,
                                                 MBTR_SC_FEE, CERT_FEE)
        mark_logs("cert = {}".format(cert), self.nodes, DEBUG_MODE)
        certs.append(cert)
        self.sync_all()

        self.refresh_sidechain(sc_info, scid)

        old_bal = self.nodes[0].getbalance()

        cross_epoch_1 = False
        cross_epoch_0 = False

        end_epoch_height = self.nodes[0].getblock(epoch_block_hash)['height']

        # invalidate all blocks one by one
        for j in range(0, len(sc_info)):
            inv_hash = self.nodes[0].getbestblockhash()
            inv_heigth = self.nodes[0].getblockcount()
            mark_logs(
                "Node 0 invalidates last block of height = {}".format(
                    inv_heigth), self.nodes, DEBUG_MODE)
            self.nodes[0].invalidateblock(inv_hash)
            sync_mempools(self.nodes[1:3])
            sc_info.pop()

            # check that last cert is always in mempool until end epoch is reverted
            if (end_epoch_height < inv_heigth):
                assert_true(certs[1] in self.nodes[0].getrawmempool())
                mark_logs("cert[{}] is in mempool".format(certs[1]),
                          self.nodes, DEBUG_MODE)
            else:
                assert_false(certs[1] in self.nodes[0].getrawmempool())

            # list are empty, exit loop
            if (len(sc_info) == 0):
                break

            try:
                ret = removekey(self.nodes[0].getscinfo(scid)['items'][0])
                assert_equal(ret, sc_info[-1])
            except JSONRPCException, e:
                errorString = e.error['message']
                print errorString
                if (inv_heigth > sc_creating_height):
                    assert (False)
                assert_true(creating_tx in self.nodes[0].getrawmempool())
                mark_logs("creating tx[{}] is in mempool".format(creating_tx),
                          self.nodes, DEBUG_MODE)
示例#8
0
    def run_test(self):
        '''
        Test that a backward transfer amount under its dust threshold is not accepted in the mempool.
        Since this dust threshold depends on minrelaytxfee and this is an optional zend flag, test that 
        a node with a different value set behaves correctly and the network is not affected (no forks happen)
        '''

        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-2),self.nodes,DEBUG_MODE)
        self.nodes[0].generate(MINIMAL_SC_HEIGHT-2)
        self.sync_all()

        #generate wCertVk and constant
        mc_test = CertTestUtils(self.options.tmpdir, self.options.srcdir)
        vk = mc_test.generate_params('sc1')
        constant = generate_random_field_element_hex()

        # create SC
        #------------------------------------------------------------------------------------------------------------
        cmd_input = {
            'version': 0,
            'toaddress': "abcd",
            'amount': 1.0,
            'wCertVk': vk,
            'withdrawalEpochLength': EPOCH_LENGTH,
            'constant': constant
        }

        mark_logs("\nNode 1 create SC", self.nodes, DEBUG_MODE)
        try:
            res = self.nodes[1].sc_create(cmd_input)
            scid = res['scid']
            pprint.pprint(res)
            self.sync_all()
        except JSONRPCException as e:
            error_string = e.error['message']
            mark_logs(error_string,self.nodes,DEBUG_MODE)
            assert_true(False)

        mark_logs("\nNode 0 generates 1 block", self.nodes, DEBUG_MODE)
        self.nodes[0].generate(1)
        self.sync_all()

        scid_swapped = str(swap_bytes(scid))
        addr_node2   = self.nodes[2].getnewaddress()

        # this amount is next to the border of the dust (54 zat, according to mintxrelayfee default value) but it is sufficiently big not to be refused
        bwt_amount = Decimal('0.00000060')
        bwt_cert = [{"address": addr_node2, "amount": bwt_amount}, {"address": addr_node2, "amount": bwt_amount}]
        bwt_amount_array = [bwt_amount, bwt_amount]
        addr_array = [addr_node2, addr_node2]
        q = 10

        bl_list = []
        # advance some epoch and send a small backward transfer via a certificate for any epoch
        for i in range(3):

            if i == 1:
                # On the second loop, connect a fourth node from scratch with a greater mintxrelayfee, which would make the
                # node mempool reject the cert, and check this option does not prevent the chain update anyway
                mark_logs("Connecting a new Node3 with a greater -mintxrelayfee", self.nodes, DEBUG_MODE)
                self.nodes.append(start_node(
                    3, self.options.tmpdir , extra_args=[
                        '-logtimemicros=1', '-debug=cert', '-debug=sc', '-debug=py', '-debug=mempool',
                        '-allowdustoutput=0', '-minrelaytxfee='+str(CUSTOM_FEE_RATE_ZEN_PER_KBYTE)]))

                connect_nodes_bi(self.nodes, 2, 3)
                self.sync_all()

            mark_logs("\nAdvance epoch...", self.nodes, DEBUG_MODE)
            self.nodes[0].generate(EPOCH_LENGTH - 1)
            self.sync_all()
            epoch_number, epoch_cum_tree_hash = get_epoch_data(scid, self.nodes[0], EPOCH_LENGTH)

            mark_logs("Node 1 sends a cert with a bwd transfers of {} coins to Node2".format(bwt_amount), self.nodes, DEBUG_MODE)
            #==============================================================
            proof = mc_test.create_test_proof(
                "sc1", scid_swapped, epoch_number, q, MBTR_SC_FEE, FT_SC_FEE, epoch_cum_tree_hash,
                constant, addr_array, bwt_amount_array)

            try:
                cert = self.nodes[1].sc_send_certificate(scid, epoch_number, q,
                    epoch_cum_tree_hash, proof, bwt_cert, FT_SC_FEE, MBTR_SC_FEE)
            except JSONRPCException as e:
                error_string = e.error['message']
                print ("Send certificate failed with reason {}".format(error_string))
                assert_true(False)

            sync_blocks(self.nodes[0:2])
            sync_mempools(self.nodes[0:2])

            mark_logs("cert = {}".format(cert), self.nodes, DEBUG_MODE)

            if i == 1:
                # check that the certificate has ben accepted by Node0 but not by Node3 wich has a greater mintxrelayfee
                mp0 = self.nodes[0].getrawmempool()
                mp3 = self.nodes[3].getrawmempool()
                assert_true(cert in mp0)
                assert_false(cert in mp3)

            mark_logs("\nNode 0 generates 1 block", self.nodes, DEBUG_MODE)
            bl_last = self.nodes[0].generate(1)[-1]
            bl_list.append(bl_last)
            self.sync_all()

        # dust amont for a cert backward transfer is 54 Zat using the 100 Zat/Kbyte default mintxrelayfee rate
        # check that no certificates with dust amount can be sent via any command type
        dust_amount = Decimal("0.00000053")
        bwt_cert = [{"address": addr_node2, "amount": dust_amount}]
        bwt_amount_array = [dust_amount]
        addr_array = [addr_node2]
        quality = 0
        proof = mc_test.create_test_proof(
            "sc1", scid_swapped, epoch_number, quality, MBTR_SC_FEE, FT_SC_FEE,
            epoch_cum_tree_hash, constant, addr_array, bwt_amount_array)

        utx, change = get_spendable(self.nodes[0], CERT_FEE)
        raw_inputs  = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
        raw_outs    = { self.nodes[0].getnewaddress() : change }
        raw_bwt_outs = {addr_node2: dust_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)
            mark_logs("Node 0 sends a raw cert with a bwd transfers of {} coins to Node2 ... expecting failure".format(dust_amount), self.nodes, DEBUG_MODE)
            cert = self.nodes[0].sendrawtransaction(signed_cert['hex'])
            assert False
        except JSONRPCException as e:
            error_string = e.error['message']
            print ("======> " + error_string)

        try:
            mark_logs("Node 0 sends a cert with a bwd transfers of {} coins to Node2 ... expecting failure".format(dust_amount), self.nodes, DEBUG_MODE)
            cert = self.nodes[0].sc_send_certificate(scid, epoch_number, q,
                epoch_cum_tree_hash, proof, bwt_cert, FT_SC_FEE, MBTR_SC_FEE)
            assert False
        except JSONRPCException as e:
            error_string = e.error['message']
            print ("======> " + error_string)

        bal = self.nodes[2].getbalance()
        utx = self.nodes[2].listunspent()
        print ("Node2 balance = {}".format(bal))
        assert_equal(bal, 2*bwt_amount)

        # the dust threshold for a bwt (54 Zat) is lower than the one for a standard output due to the replay protection
        # extension in the pub script (63 Zat). As a result we can not spend exactly one UTXOs coming from backward transfer
        # otherwise we would create a dust output.
        mark_logs("Node2 tries to spent one utxo from bwt sending {} coins to Node0 ... expecting failure".format(utx[0]['amount']), self.nodes, DEBUG_MODE)
        # try spending one utxo
        inputs  = [ {'txid' : utx[0]['txid'], 'vout' : utx[0]['vout']}]
        outputs = { self.nodes[0].getnewaddress() : utx[0]['amount'] }
        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)
        rawtx   = self.nodes[2].signrawtransaction(rawtx)

        error_string = ""
        try:
            rawtx   = self.nodes[2].sendrawtransaction(rawtx['hex'])
            assert False
        except JSONRPCException as e:
            error_string = e.error['message']
            print (error_string)

        # we can spend a pair of them instead
        mark_logs("Node2 tries to spent both utxo from bwt sending {} coins to Node0".format(bal), self.nodes, DEBUG_MODE)
        # try spending two utxos
        inputs  = [ {'txid' : utx[0]['txid'], 'vout' : utx[0]['vout']}, {'txid' : utx[1]['txid'], 'vout' : utx[1]['vout']}]
        outputs = { self.nodes[0].getnewaddress() : bal }
        rawtx   = self.nodes[2].createrawtransaction(inputs, outputs)
        rawtx   = self.nodes[2].signrawtransaction(rawtx)

        error_string = ""
        try:
            rawtx   = self.nodes[2].sendrawtransaction(rawtx['hex'])
        except JSONRPCException as e:
            error_string = e.error['message']
            print (error_string)
            assert False

        print ("tx = {}".format(rawtx))

        sync_blocks(self.nodes[0:2])
        sync_mempools(self.nodes[0:2])
        # just to be sure tx is propagated
        time.sleep(2)

        mark_logs("Node 2 generates 1 block", self.nodes, DEBUG_MODE)
        self.nodes[2].generate(1)
        self.sync_all()

        mark_logs("\nChecking persistance stopping and restarting nodes", self.nodes, DEBUG_MODE)
        stop_nodes(self.nodes)
        wait_bitcoinds()
        self.setup_network(False)
示例#9
0
    def run_test(self):
        '''
        The test creates two sc, send funds to them and then sends a certificates to them,
        verifying also that mempool accepts certificate with different quality,
        certificate with higher fee but same quality substitutes certificate with lower fee,
        certificates from different sc are handled independently.
        '''

        # forward transfer amounts
        creation_amount = Decimal("0.5")
        fwt_amount = Decimal("200")
        bwt_amount = Decimal("20")

        self.nodes[0].getblockhash(0)

        # 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()
        self.nodes[2].generate(1)
        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()

        # SC creation
        bal_before_sc_creation = self.nodes[1].getbalance("", 0)
        mark_logs(
            "Node1 balance before SC creation: {}".format(
                bal_before_sc_creation), self.nodes, DEBUG_MODE)

        #generate wCertVk and constant
        mcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir)
        vk_tag_1 = "sc1"
        vk_1 = mcTest.generate_params(vk_tag_1)
        constant_1 = generate_random_field_element_hex()

        vk_tag_2 = "sc2"
        vk_2 = mcTest.generate_params(vk_tag_2)
        constant_2 = generate_random_field_element_hex()
        cmdInput = {
            "version": 0,
            "withdrawalEpochLength": EPOCH_LENGTH,
            "toaddress": "dada",
            "amount": creation_amount,
            "wCertVk": vk_1,
            "constant": constant_1,
        }

        ret = self.nodes[1].sc_create(cmdInput)
        creating_tx_1 = ret['txid']
        scid_1 = ret['scid']
        scid1_swapped = str(swap_bytes(scid_1))
        mark_logs(
            "Node 1 created the SC spending {} coins via tx {}.".format(
                creation_amount, creating_tx_1), self.nodes, DEBUG_MODE)
        self.sync_all()

        cmdInput = {
            "version": 0,
            "withdrawalEpochLength": EPOCH_LENGTH,
            "toaddress": "baba",
            "amount": creation_amount,
            "wCertVk": vk_2,
            "constant": constant_2,
            "minconf": 0
        }

        ret = self.nodes[1].sc_create(cmdInput)
        creating_tx_2 = ret['txid']
        scid_2 = ret['scid']
        scid2_swapped = str(swap_bytes(scid_2))
        mark_logs(
            "Node 1 created the SC spending {} coins via tx {}.".format(
                creation_amount, creating_tx_2), self.nodes, DEBUG_MODE)
        self.sync_all()

        decoded_tx = self.nodes[1].getrawtransaction(creating_tx_1, 1)
        assert_equal(scid_1, decoded_tx['vsc_ccout'][0]['scid'])
        mark_logs("created SC id: {}".format(scid_1), self.nodes, DEBUG_MODE)

        mark_logs("Node0 confirms Sc creation generating 1 block", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        sc_creating_height = self.nodes[0].getblockcount()
        self.sync_all()

        # Check node 1 balance following sc creation
        fee_sc_creation_1 = Decimal(
            self.nodes[1].gettransaction(creating_tx_1)['fee'])
        fee_sc_creation_2 = Decimal(
            self.nodes[1].gettransaction(creating_tx_2)['fee'])
        mark_logs("Fee paid for SC1 creation: {}".format(fee_sc_creation_1),
                  self.nodes, DEBUG_MODE)
        mark_logs("Fee paid for SC2 creation: {}".format(fee_sc_creation_2),
                  self.nodes, DEBUG_MODE)
        bal_after_sc_creation = self.nodes[1].getbalance("", 0)
        mark_logs(
            "Node1 balance after SC creation: {}".format(
                bal_after_sc_creation), self.nodes, DEBUG_MODE)

        assert_equal(
            bal_before_sc_creation, bal_after_sc_creation + creation_amount +
            creation_amount - fee_sc_creation_1 - fee_sc_creation_2)

        assert_equal(self.nodes[0].getscinfo(scid_1)['items'][0]['balance'],
                     Decimal(0))
        assert_equal(
            self.nodes[0].getscinfo(scid_1)['items'][0]['immatureAmounts'][0]
            ['amount'], creation_amount)

        # Fwd Transfer to SC 1
        bal_before_fwd_tx = self.nodes[0].getbalance("", 0)
        mc_return_address = self.nodes[0].getnewaddress()
        mark_logs("Node0 balance before fwd tx: {}".format(bal_before_fwd_tx),
                  self.nodes, DEBUG_MODE)
        cmdInput = [{
            'toaddress': "abcd",
            'amount': fwt_amount,
            "scid": scid_1,
            'mcReturnAddress': mc_return_address
        }]
        fwd_tx = self.nodes[0].sc_send(cmdInput)
        mark_logs(
            "Node0 transfers {} coins to SC 1 with tx {}...".format(
                fwt_amount, fwd_tx), self.nodes, DEBUG_MODE)
        self.sync_all()

        mark_logs("Node0 confirms fwd transfer generating 1 block", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        self.sync_all()

        # Fwd Transfer to SC 2
        bal_before_fwd_tx = self.nodes[0].getbalance("", 0)
        mc_return_address = self.nodes[0].getnewaddress()
        mark_logs("Node0 balance before fwd tx: {}".format(bal_before_fwd_tx),
                  self.nodes, DEBUG_MODE)
        cmdInput = [{
            'toaddress': "abcd",
            'amount': fwt_amount,
            "scid": scid_2,
            'mcReturnAddress': mc_return_address
        }]
        fwd_tx = self.nodes[0].sc_send(cmdInput)
        mark_logs(
            "Node0 transfers {} coins to SC 2 with tx {}...".format(
                fwt_amount, fwd_tx), self.nodes, DEBUG_MODE)
        self.sync_all()

        mark_logs("Node0 confirms fwd transfer generating 1 block", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        self.sync_all()

        # Check node 0 balance following fwd tx
        fee_fwt = self.nodes[0].gettransaction(fwd_tx)['fee']
        mark_logs("Fee paid for fwd tx: {}".format(fee_fwt), self.nodes,
                  DEBUG_MODE)
        bal_after_fwd_tx = self.nodes[0].getbalance("", 0)
        mark_logs("Node0 balance after fwd: {}".format(bal_after_fwd_tx),
                  self.nodes, DEBUG_MODE)
        assert_equal(
            bal_before_fwd_tx, bal_after_fwd_tx + fwt_amount - fee_fwt -
            Decimal(MINER_REWARD_POST_H200))

        assert_equal(self.nodes[0].getscinfo(scid_1)['items'][0]['balance'],
                     Decimal(0))
        assert_equal(
            self.nodes[0].getscinfo(scid_1)['items'][0]['immatureAmounts'][0]
            ['amount'], creation_amount)
        assert_equal(
            self.nodes[0].getscinfo(scid_1)['items'][0]['immatureAmounts'][1]
            ['amount'], fwt_amount)

        mark_logs(
            "Node0 generating more blocks to achieve end of withdrawal epoch",
            self.nodes, DEBUG_MODE)
        self.nodes[0].generate(EPOCH_LENGTH - 3)
        self.sync_all()
        assert_equal(self.nodes[0].getscinfo(scid_1)['items'][0]['balance'],
                     creation_amount + fwt_amount)  # Sc balance has matured
        assert_equal(
            len(self.nodes[0].getscinfo(scid_1)['items'][0]
                ['immatureAmounts']), 0)

        epoch_number_1, epoch_cum_tree_hash_1 = get_epoch_data(
            scid_1, self.nodes[0], EPOCH_LENGTH)

        addr_node1 = self.nodes[1].getnewaddress()
        self.sync_all()

        epoch_number_2, epoch_cum_tree_hash_2 = get_epoch_data(
            scid_2, self.nodes[0], EPOCH_LENGTH)
        amount_cert = [{"address": addr_node1, "amount": bwt_amount}]

        # Create Cert1 with quality 100 and place it in mempool
        mark_logs("Create Cert1 with quality 100 and place it in mempool",
                  self.nodes, DEBUG_MODE)
        quality = 100
        proof = mcTest.create_test_proof(vk_tag_1, scid1_swapped,
                                         epoch_number_1, quality, MBTR_SC_FEE,
                                         FT_SC_FEE, epoch_cum_tree_hash_1,
                                         constant_1, [addr_node1],
                                         [bwt_amount])

        try:
            cert_1_epoch_0 = self.nodes[0].sc_send_certificate(
                scid_1, epoch_number_1, quality, epoch_cum_tree_hash_1, proof,
                amount_cert, FT_SC_FEE, MBTR_SC_FEE, CERT_FEE)
            assert (len(cert_1_epoch_0) > 0)
            mark_logs("Certificate is {}".format(cert_1_epoch_0), self.nodes,
                      DEBUG_MODE)
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(
                "Send certificate failed with reason {}".format(errorString),
                self.nodes, DEBUG_MODE)
            assert (False)
示例#10
0
    def run_test(self):
        '''
        The test creates a sc, send funds to it and then sends a certificate to it,
        verifying also that specifying various combination of bad parameters causes a certificate
        to be refused. This test also checks that the receiver of cert backward transfer can spend it
        only when they become mature. 
        '''

        # forward transfer amounts
        creation_amount = Decimal("0.5")
        fwt_amount = Decimal("50")
        bwt_amount_bad = Decimal("100.0")
        bwt_amount = Decimal("50")

        self.nodes[0].getblockhash(0)

        # 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 220 block", self.nodes, DEBUG_MODE)
        self.nodes[0].generate(220)
        self.sync_all()

        # SC creation
        bal_before_sc_creation = self.nodes[1].getbalance("", 0)
        mark_logs(
            "Node1 balance before SC creation: {}".format(
                bal_before_sc_creation), self.nodes, DEBUG_MODE)

        #generate wCertVk and constant
        mcTest = MCTestUtils(self.options.tmpdir, self.options.srcdir)
        vk = mcTest.generate_params("sc1")
        constant = generate_random_field_element_hex()

        ret = self.nodes[1].sc_create(EPOCH_LENGTH, "dada", creation_amount,
                                      vk, "", constant)
        creating_tx = ret['txid']
        scid = ret['scid']
        mark_logs(
            "Node 1 created the SC spending {} coins via tx {}.".format(
                creation_amount, creating_tx), self.nodes, DEBUG_MODE)
        self.sync_all()

        decoded_tx = self.nodes[1].getrawtransaction(creating_tx, 1)
        assert_equal(scid, decoded_tx['vsc_ccout'][0]['scid'])
        mark_logs("created SC id: {}".format(scid), self.nodes, DEBUG_MODE)

        mark_logs("Node0 confirms Sc creation generating 1 block", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        sc_creating_height = self.nodes[0].getblockcount()
        self.sync_all()

        # Check node 1 balance following sc creation
        fee_sc_creation = self.nodes[1].gettransaction(creating_tx)['fee']
        mark_logs("Fee paid for SC creation: {}".format(fee_sc_creation),
                  self.nodes, DEBUG_MODE)
        bal_after_sc_creation = self.nodes[1].getbalance("", 0)
        mark_logs(
            "Node1 balance after SC creation: {}".format(
                bal_after_sc_creation), self.nodes, DEBUG_MODE)
        assert_equal(bal_before_sc_creation,
                     bal_after_sc_creation + creation_amount - fee_sc_creation)

        assert_equal(self.nodes[0].getscinfo(scid)['balance'], Decimal(0))
        assert_equal(
            self.nodes[0].getscinfo(scid)['immature amounts'][0]['amount'],
            creation_amount)

        # Fwd Transfer to Sc
        bal_before_fwd_tx = self.nodes[0].getbalance("", 0)
        mark_logs("Node0 balance before fwd tx: {}".format(bal_before_fwd_tx),
                  self.nodes, DEBUG_MODE)
        fwd_tx = self.nodes[0].sc_send("abcd", fwt_amount, scid)
        mark_logs(
            "Node0 transfers {} coins to SC with tx {}...".format(
                fwt_amount, fwd_tx), self.nodes, DEBUG_MODE)
        self.sync_all()

        mark_logs("Node0 confirms fwd transfer generating 1 block", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        self.sync_all()

        # Check node 0 balance following fwd tx
        fee_fwt = self.nodes[0].gettransaction(fwd_tx)['fee']
        mark_logs("Fee paid for fwd tx: {}".format(fee_fwt), self.nodes,
                  DEBUG_MODE)
        bal_after_fwd_tx = self.nodes[0].getbalance("", 0)
        mark_logs("Node0 balance after fwd: {}".format(bal_after_fwd_tx),
                  self.nodes, DEBUG_MODE)
        assert_equal(bal_before_fwd_tx, bal_after_fwd_tx + fwt_amount -
                     fee_fwt - Decimal(8.75))  # 8.75 is matured coinbase

        assert_equal(self.nodes[0].getscinfo(scid)['balance'], Decimal(0))
        assert_equal(
            self.nodes[0].getscinfo(scid)['immature amounts'][0]['amount'],
            creation_amount)
        assert_equal(
            self.nodes[0].getscinfo(scid)['immature amounts'][1]['amount'],
            fwt_amount)

        mark_logs(
            "Node0 generating 3 more blocks to achieve end of withdrawal epoch",
            self.nodes, DEBUG_MODE)
        self.nodes[0].generate(3)
        self.sync_all()
        assert_equal(self.nodes[0].getscinfo(scid)['balance'],
                     creation_amount + fwt_amount)  # Sc balance has matured
        assert_equal(len(self.nodes[0].getscinfo(scid)['immature amounts']), 0)

        epoch_block_hash, epoch_number = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)
        mark_logs(
            "epoch_number = {}, epoch_block_hash = {}".format(
                epoch_number, epoch_block_hash), self.nodes, DEBUG_MODE)

        prev_epoch_block_hash = self.nodes[0].getblockhash(sc_creating_height -
                                                           1 +
                                                           ((epoch_number) *
                                                            EPOCH_LENGTH))

        pkh_node1 = self.nodes[1].getnewaddress("", True)

        #Create proof for WCert
        quality = 0
        proof = mcTest.create_test_proof("sc1", epoch_number, epoch_block_hash,
                                         prev_epoch_block_hash, quality,
                                         constant, [pkh_node1], [bwt_amount])

        mark_logs(
            "Node 0 tries to perform a bwd transfer with insufficient Sc balance...",
            self.nodes, DEBUG_MODE)
        amounts = [{"pubkeyhash": pkh_node1, "amount": bwt_amount_bad}]

        try:
            self.nodes[0].send_certificate(scid, epoch_number, quality,
                                           epoch_block_hash, proof, amounts,
                                           CERT_FEE)
            assert (False)
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(errorString, self.nodes, DEBUG_MODE)
示例#11
0
            errorString = e.error['message']
            mark_logs(errorString, self.nodes, DEBUG_MODE)

        assert_equal("Insufficient funds" in errorString, True)

        mark_logs(
            "Show that coins from bwt can be spent once next epoch certificate is received and confirmed",
            self.nodes, DEBUG_MODE)
        mark_logs(
            "Node0 generating enough blocks to move to new withdrawal epoch",
            self.nodes, DEBUG_MODE)
        self.nodes[0].generate(EPOCH_LENGTH - 1)
        self.sync_all()

        prev_epoch_block_hash = epoch_block_hash
        epoch_block_hash, epoch_number = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)
        mark_logs(
            "epoch_number = {}, epoch_block_hash = {}".format(
                epoch_number, epoch_block_hash), self.nodes, DEBUG_MODE)

        amount_cert_2 = []

        bal_before_cert_2 = self.nodes[1].getbalance("", 0)
        mark_logs(
            "Node1 balance before epoch 1 certificate is received: {}".format(
                bal_before_cert_2), self.nodes, DEBUG_MODE)

        mark_logs(
            "Generate new certificate for epoch {}. No bwt and no fee are included"
            .format(epoch_number), self.nodes, DEBUG_MODE)
示例#12
0
            feCfgStr = self.nodes[0].getscinfo(
                val)['items'][0]['vFieldElementCertificateFieldConfig']
            cmtCfgStr = self.nodes[0].getscinfo(
                val)['items'][0]['vBitVectorCertificateFieldConfig']
            assert_equal(feCfgStr, feCfg[i])
            assert_equal(cmtCfgStr, cmtCfg[i])

        #-------------------------------------------------------
        # advance epoch
        certs = []
        mark_logs("\nNode 0 generates {} block".format(EPOCH_LENGTH - 1),
                  self.nodes, DEBUG_MODE)
        self.nodes[0].generate(EPOCH_LENGTH - 1)
        self.sync_all()

        epoch_number_1, epoch_cum_tree_hash_1 = get_epoch_data(
            scid1, self.nodes[0], EPOCH_LENGTH)
        mark_logs(
            "epoch_number = {}, epoch_cum_tree_hash = {}".format(
                epoch_number_1, epoch_cum_tree_hash_1), self.nodes, DEBUG_MODE)

        #-------------------------------------------------------
        # do some negative test for having a raw cert rejected by mempool
        addr_node1 = self.nodes[1].getnewaddress()
        bwt_amount = Decimal("0.1")

        # get a UTXO
        utx, change = get_spendable(self.nodes[0], CERT_FEE)

        inputs = [{'txid': utx['txid'], 'vout': utx['vout']}]
        outputs = {self.nodes[0].getnewaddress(): change}
        bwt_outs = [{"address": addr_node1, "amount": bwt_amount}]
    def run_test(self):

        '''
        The test creates a sc, send funds to it and then:
        ( 1) Switch ON the CZendooLowPrioThreadGuard that should prevent any mempool Cert to be included,
            because of ProofVerifier threads are on pause.
        ( 2) Switch OFF the CZendooLowPrioThreadGuard -> certificate must be applied to mempool.
        ( 3) Switch ON the CZendooLowPrioThreadGuard and try to generate the block with Certificate - must be successful
        '''

        # forward transfer amounts
        creation_amount = Decimal("0.5")
        fwt_amount = Decimal("50")
        bwt_amount_bad = Decimal("100.0")
        bwt_amount = Decimal("50")

        self.nodes[0].getblockhash(0)

        mark_logs("Node generates {} block".format(MINIMAL_SC_HEIGHT), self.nodes, DEBUG_MODE)
        self.nodes[0].generate(MINIMAL_SC_HEIGHT)

        # SC creation
        # Generate wCertVk and constant
        mcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir)
        vk = mcTest.generate_params("sc1")
        constant = generate_random_field_element_hex()
        cmdInput = {
            'version': 0,
            'withdrawalEpochLength': EPOCH_LENGTH,
            'toaddress': "dada",
            'amount': creation_amount,
            'wCertVk': vk,
            'constant': constant
        }

        ret = self.nodes[0].sc_create(cmdInput)
        creating_tx = ret['txid']
        scid = ret['scid']
        scid_swapped = str(swap_bytes(scid))
        mark_logs("Node created the SC spending {} coins via tx {}.".format(creation_amount, creating_tx), self.nodes, DEBUG_MODE)

        decoded_tx = self.nodes[0].getrawtransaction(creating_tx, 1)
        assert_equal(scid, decoded_tx['vsc_ccout'][0]['scid'])
        mark_logs("created SC id: {}".format(scid), self.nodes, DEBUG_MODE)

        mark_logs("Node confirms Sc creation generating 1 block", self.nodes, DEBUG_MODE)
        self.nodes[0].generate(1)

        assert_equal(self.nodes[0].getscinfo(scid)['items'][0]['balance'], Decimal(0))
        assert_equal(self.nodes[0].getscinfo(scid)['items'][0]['immatureAmounts'][0]['amount'], creation_amount)

        # Fwd Transfer to Sc
        bal_before_fwd_tx = self.nodes[0].getbalance("", 0)
        mark_logs("Node balance before fwd tx: {}".format(bal_before_fwd_tx), self.nodes, DEBUG_MODE)
        mc_return_address = self.nodes[0].getnewaddress()
        cmdInput = [{'toaddress': "abcd", 'amount': fwt_amount, "scid": scid, "mcReturnAddress": mc_return_address}]
        fwd_tx = self.nodes[0].sc_send(cmdInput)
        mark_logs("Node transfers {} coins to SC with tx {}...".format(fwt_amount, fwd_tx), self.nodes, DEBUG_MODE)

        mark_logs("Node confirms fwd transfer generating 1 block", self.nodes, DEBUG_MODE)
        self.nodes[0].generate(1)

        assert_equal(self.nodes[0].getscinfo(scid)['items'][0]['balance'], Decimal(0))
        assert_equal(self.nodes[0].getscinfo(scid)['items'][0]['immatureAmounts'][0]['amount'], creation_amount)
        assert_equal(self.nodes[0].getscinfo(scid)['items'][0]['immatureAmounts'][1]['amount'], fwt_amount)

        nblocks = EPOCH_LENGTH - 2
        mark_logs("Node0 generating {} more blocks to achieve end of withdrawal epoch".format(nblocks), self.nodes, DEBUG_MODE)
        self.nodes[0].generate(nblocks)
        assert_equal(self.nodes[0].getscinfo(scid)['items'][0]['balance'], creation_amount + fwt_amount) # Sc balance has matured
        assert_equal(len(self.nodes[0].getscinfo(scid)['items'][0]['immatureAmounts']), 0)

        epoch_number, epoch_cum_tree_hash = get_epoch_data(scid, self.nodes[0], EPOCH_LENGTH)
        mark_logs("epoch_number = {}, epoch_cum_tree_hash = {}".format(epoch_number, epoch_cum_tree_hash), self.nodes, DEBUG_MODE)

        addr_node0 = self.nodes[0].getnewaddress()

        #Create proof for WCert
        quality = 10
        proof = mcTest.create_test_proof(
            "sc1", scid_swapped, epoch_number, quality, MBTR_SC_FEE, FT_SC_FEE, epoch_cum_tree_hash, constant, [addr_node0], [bwt_amount])

        amount_cert_1 = [{"address": addr_node0, "amount": bwt_amount}]

        # Enable CZendooLowPrioThreadGuard
        mark_logs("Enable CZendooLowPrioThreadGuard...", self.nodes, DEBUG_MODE)
        res = self.nodes[0].setproofverifierlowpriorityguard(True)
        assert_equal(res["enabled"], True)

        # Try to send WCert - should fail because of the timeout: mempool proof verifier has low priority
        mark_logs("Node sends a certificate while CZendooLowPrioThreadGuard is enabled...", self.nodes, DEBUG_MODE)
        try:
            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)
            assert(False)
        except Exception as e:
            errorString = e.message
            assert("timed out" == errorString)
            # Establish new AuthServiceProxy, because previous one is dead after the timeout error
            self.nodes[0] = AuthServiceProxy(self.nodes[0].get_service_url(), timeout=10)
            mark_logs("Send certificate failed with reason {}".format(errorString), self.nodes, DEBUG_MODE)

        # Disable CZendooLowPrioThreadGuard
        mark_logs("Disable CZendooLowPrioThreadGuard...", self.nodes, DEBUG_MODE)
        res = self.nodes[0].setproofverifierlowpriorityguard(False)
        assert_equal(res["enabled"], False)


        # Try to send WCert
        mark_logs("Node sends a certificate while CZendooLowPrioThreadGuard is enabled...", self.nodes, DEBUG_MODE)
        try:
            cert_epoch_0 = 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)
            assert (len(cert_epoch_0) > 0)
            mark_logs("Certificate is {}".format(cert_epoch_0), self.nodes, DEBUG_MODE)
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs("Send certificate failed with reason {}".format(errorString), self.nodes, DEBUG_MODE)
            assert (False)
示例#14
0
    def run_test(self):
        '''
        Node0 creates a SC and sends funds to it, and then sends a cert to it with a bwt to Node1
        Node0 then sends a few tx with fwt to the same SC and then a second cert with a bwt to Node2 
        Node0 than invalidates all the latest blocks one by one checking sc state and checking also
        that a cert remains in mempool until its end epoch is reverted
        Node0 finally generates a sufficient number of blocks for reverting other nodes' chains and
        the test checks their sc state
        '''

        sc_txes = []
        certs = []

        # forward transfer amount
        creation_amount = Decimal("0.5")
        fwt_amount_1 = Decimal("1000.0")
        fwt_amount_2 = Decimal("1.0")
        fwt_amount_3 = Decimal("2.0")
        fwt_amount_4 = Decimal("3.0")

        bwt_amount_1 = Decimal("8.0")
        bwt_amount_2 = Decimal("8.5")

        sc_info = []

        # node 1 earns some coins, they would be available after 100 blocks
        mark_logs("Node 0 generates 1 block", self.nodes, DEBUG_MODE)
        self.nodes[0].generate(1)
        self.sync_all()

        mark_logs("Node 0 generates 220 block", self.nodes, DEBUG_MODE)
        self.nodes[0].generate(220)
        self.sync_all()

        sc_info.append("No SC")

        mark_logs(
            "Node0 creates the SC spending {} coins ...".format(
                creation_amount), self.nodes, DEBUG_MODE)

        #generate wCertVk and constant
        mcTest = MCTestUtils(self.options.tmpdir, self.options.srcdir)
        vk = mcTest.generate_params("sc1")
        constant = generate_random_field_element_hex()

        ret = self.nodes[0].sc_create(EPOCH_LENGTH, "dada", creation_amount,
                                      vk, "", constant)
        creating_tx = ret['txid']
        scid = ret['scid']

        decoded_tx = self.nodes[0].getrawtransaction(creating_tx, 1)
        assert_equal(scid, decoded_tx['vsc_ccout'][0]['scid'])
        mark_logs("created SC id: {}".format(scid), self.nodes, DEBUG_MODE)

        mark_logs("creating_tx = {}".format(creating_tx), self.nodes,
                  DEBUG_MODE)
        sc_txes.append(creating_tx)
        self.sync_all()

        prev_epoch_block_hash = self.nodes[0].getblockhash(
            self.nodes[0].getblockcount())

        self.refresh_sidechain(sc_info, scid)

        sc_creating_height = self.nodes[0].getblockcount()

        mark_logs(
            "Node 0 performs a fwd transfer of {} coins to SC...".format(
                fwt_amount_1), self.nodes, DEBUG_MODE)
        fwd_tx = self.nodes[0].sc_send("abcd", fwt_amount_1, scid)
        print "fwd_tx=" + fwd_tx
        sc_txes.append(fwd_tx)
        self.sync_all()

        self.refresh_sidechain(sc_info, scid)

        pkh_node1 = self.nodes[1].getnewaddress("", True)
        pkh_node2 = self.nodes[2].getnewaddress("", True)

        mark_logs("...3 more blocks needed for achieving sc coins maturity",
                  self.nodes, DEBUG_MODE)
        self.refresh_sidechain(sc_info, scid)
        self.refresh_sidechain(sc_info, scid)
        self.refresh_sidechain(sc_info, scid)

        mark_logs(
            "##### End epoch block = {}".format(
                self.nodes[0].getbestblockhash()), self.nodes, DEBUG_MODE)

        epoch_block_hash, epoch_number = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)
        mark_logs(
            "epoch_number = {}, epoch_block_hash = {}".format(
                epoch_number, epoch_block_hash), self.nodes, DEBUG_MODE)

        mark_logs(
            "Node 0 performs a bwd transfer of {} coins to Node1...".format(
                bwt_amount_1), self.nodes, DEBUG_MODE)
        amounts = []
        amounts.append({"pubkeyhash": pkh_node1, "amount": bwt_amount_1})

        #Create proof for WCert
        quality = 0
        proof = mcTest.create_test_proof("sc1", epoch_number, epoch_block_hash,
                                         prev_epoch_block_hash, quality,
                                         constant, [pkh_node1], [bwt_amount_1])

        cert = self.nodes[0].send_certificate(scid, epoch_number, quality,
                                              epoch_block_hash, proof, amounts,
                                              CERT_FEE)
        mark_logs("cert = {}".format(cert), self.nodes, DEBUG_MODE)
        certs.append(cert)
        self.sync_all()

        self.refresh_sidechain(sc_info, scid)

        mark_logs(
            "Node 0 performs a fwd transfer of {} coins to SC...".format(
                fwt_amount_2), self.nodes, DEBUG_MODE)
        fwd_tx = self.nodes[0].sc_send("abcd", fwt_amount_2, scid)
        mark_logs("fwd_tx = {}".format(fwd_tx), self.nodes, DEBUG_MODE)
        sc_txes.append(fwd_tx)
        self.sync_all()

        self.refresh_sidechain(sc_info, scid)

        mark_logs(
            "Node 0 performs a fwd transfer of {} coins to SC...".format(
                fwt_amount_3), self.nodes, DEBUG_MODE)
        fwd_tx = self.nodes[0].sc_send("abcd", fwt_amount_3, scid)
        mark_logs("fwd_tx = {}".format(fwd_tx), self.nodes, DEBUG_MODE)
        sc_txes.append(fwd_tx)
        self.sync_all()

        self.refresh_sidechain(sc_info, scid)

        mark_logs(
            "Node 0 performs a fwd transfer of {} coins to SC...".format(
                fwt_amount_4), self.nodes, DEBUG_MODE)
        fwd_tx = self.nodes[0].sc_send("abcd", fwt_amount_4, scid)
        mark_logs("fwd_tx = {}".format(fwd_tx), self.nodes, DEBUG_MODE)
        sc_txes.append(fwd_tx)
        self.sync_all()

        self.refresh_sidechain(sc_info, scid)

        self.refresh_sidechain(sc_info, scid)

        mark_logs(
            "##### End epoch block = {}".format(
                self.nodes[0].getbestblockhash()), self.nodes, DEBUG_MODE)

        self.refresh_sidechain(sc_info, scid)

        prev_epoch_block_hash = epoch_block_hash
        epoch_block_hash, epoch_number = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)
        mark_logs(
            "epoch_number = {}, epoch_block_hash = {}".format(
                epoch_number, epoch_block_hash), self.nodes, DEBUG_MODE)

        mark_logs(
            "Node 0 performs a bwd transfer of {} coins to Node2...".format(
                bwt_amount_2), self.nodes, DEBUG_MODE)
        amounts = []
        amounts.append({"pubkeyhash": pkh_node2, "amount": bwt_amount_2})

        #Create proof for WCert
        quality = 1
        proof = mcTest.create_test_proof("sc1", epoch_number, epoch_block_hash,
                                         prev_epoch_block_hash, quality,
                                         constant, [pkh_node2], [bwt_amount_2])

        cert = self.nodes[0].send_certificate(scid, epoch_number, quality,
                                              epoch_block_hash, proof, amounts,
                                              CERT_FEE)
        mark_logs("cert = {}".format(cert), self.nodes, DEBUG_MODE)
        certs.append(cert)
        self.sync_all()

        self.refresh_sidechain(sc_info, scid)

        old_bal = self.nodes[0].getbalance()

        cross_epoch_1 = False
        cross_epoch_0 = False

        end_epoch_height = self.nodes[0].getblock(epoch_block_hash)['height']

        # invalidate all blocks one by one
        for j in range(0, len(sc_info)):
            inv_hash = self.nodes[0].getbestblockhash()
            inv_heigth = self.nodes[0].getblockcount()
            mark_logs(
                "Node 0 invalidates last block of height = {}".format(
                    inv_heigth), self.nodes, DEBUG_MODE)
            self.nodes[0].invalidateblock(inv_hash)
            sync_mempools(self.nodes[1:3])
            sc_info.pop()

            # check that last cert is always in mempool until end epoch is reverted
            if (end_epoch_height < inv_heigth):
                assert_true(certs[1] in self.nodes[0].getrawmempool())
                mark_logs("cert[{}] is in mempool".format(certs[1]),
                          self.nodes, DEBUG_MODE)
            else:
                assert_false(certs[1] in self.nodes[0].getrawmempool())

            # list are empty, exit loop
            if (len(sc_info) == 0):
                break

            try:
                assert_equal(self.nodes[0].getscinfo(scid), sc_info[-1])
            except JSONRPCException, e:
                errorString = e.error['message']
                print errorString
                if (inv_heigth > sc_creating_height):
                    assert (False)
                assert_true(creating_tx in self.nodes[0].getrawmempool())
                mark_logs("creating tx[{}] is in mempool".format(creating_tx),
                          self.nodes, DEBUG_MODE)
示例#15
0
class sc_cert_bwt_amount_rounding(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=[[
                '-logtimemicros=1', '-debug=py', '-debug=sc', '-debug=mempool',
                '-debug=cert', '-debug=bench', '-scproofqueuesize=0'
            ]] * NUMB_OF_NODES)

        connect_nodes_bi(self.nodes, 0, 1)
        self.is_network_split = split
        self.sync_all()

    def run_test(self):
        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

        '''
        Purpose of this test is to verify that a decimal amount with many decimal digits is correctly handled, expecially
        with reference to the compatibility between creation and verification of the proof, which are performed by the test
        framework and the zend_oo core implementations.
        '''
        # network topology: (0)--(1)

        mark_logs("Node 1 generates {} block".format(2), 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 - 2)
        self.sync_all()

        #generate Vks and constant
        certMcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir)

        certVk = certMcTest.generate_params('scs')
        constant = generate_random_field_element_hex()
        cr_amount = 1000.0

        #-------------------------------------------------------
        fee = 0.000025

        cmdInput = {
            'version': 0,
            'withdrawalEpochLength': EPOCH_LENGTH,
            'amount': cr_amount,
            'fee': fee,
            'constant': constant,
            'wCertVk': certVk,
            'toaddress': "cdcd"
        }

        tx, scid = create_sc(cmdInput, self.nodes[0])
        mark_logs("Created SC with scid={} via tx={}".format(scid, tx),
                  self.nodes, DEBUG_MODE)
        self.sync_all()
        hexTx = self.nodes[0].getrawtransaction(tx)
        print "sz=", len(hexTx) // 2

        # advance epoch
        self.nodes[0].generate(EPOCH_LENGTH)
        self.sync_all()
        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)

        NUM_OF_BWT = 1
        print "==============================================================================================================================================================================="
        print "Adding {} backward transfers to certificate".format(NUM_OF_BWT)
        print "==============================================================================================================================================================================="

        bwt_amount = Decimal('1.952929687000111')

        print "bwt amount {}".format(bwt_amount)
        bwt_cert = []
        addr_array = []
        bwt_amount_array = []
        proof = None
        addr_node1 = self.nodes[1].getnewaddress()

        for _ in range(0, NUM_OF_BWT):

            addr_array.append(addr_node1)
            bwt_amount_array.append(bwt_amount)

            entry = {"address": addr_node1, "amount": bwt_amount}
            bwt_cert.append(entry)
            pprint.pprint(entry)

        print "Generating cert proof..."
        t0 = time.time()
        q = 10
        scid_swapped = str(swap_bytes(scid))
        print "---------------------"
        proof = certMcTest.create_test_proof("scs", scid_swapped, epoch_number,
                                             q, MBTR_SC_FEE, FT_SC_FEE,
                                             epoch_cum_tree_hash, constant,
                                             addr_array, bwt_amount_array)
        assert_true(proof != None)
        t1 = time.time()
        print "...proof with sz={} generated: {} secs".format(
            len(proof) // 2, t1 - t0)

        try:
            cert = self.nodes[0].sc_send_certificate(scid, epoch_number, q,
                                                     epoch_cum_tree_hash,
                                                     proof, bwt_cert,
                                                     FT_SC_FEE, MBTR_SC_FEE,
                                                     CERT_FEE)
        except JSONRPCException, e:
            errorString = e.error['message']
            print "Send certificate failed with reason {}".format(errorString)
            assert (False)
示例#16
0
class WalletBackupTest(BitcoinTestFramework):
    def setup_chain(self):
        logging.info("Initializing test directory " + self.options.tmpdir)
        initialize_chain_clean(self.options.tmpdir, 4)

    # This mirrors how the network was setup in the bash test
    def setup_network(self, split=False):
        # -exportdir option means we must provide a valid path to the destination folder for wallet backups
        ed0 = "-exportdir=" + self.options.tmpdir + "/node0"
        ed1 = "-exportdir=" + self.options.tmpdir + "/node1"
        ed2 = "-exportdir=" + self.options.tmpdir + "/node2"

        # nodes 1, 2,3 are spenders, let's give them a keypool=100
        extra_args = [['-debug=zrpc', "-keypool=100", ed0],
                      ['-debug=zrpc', "-keypool=100", ed1],
                      ['-debug=zrpc', "-keypool=100", ed2], []]
        self.nodes = start_nodes(4, self.options.tmpdir, extra_args)
        connect_nodes(self.nodes[0], 3)
        connect_nodes(self.nodes[1], 3)
        connect_nodes(self.nodes[2], 3)
        connect_nodes(self.nodes[2], 0)
        self.is_network_split = False
        self.sync_all()

    def one_send(self, from_node, to_address):
        if (randint(1, 2) == 1):
            amount = Decimal(randint(1, 10)) / Decimal(10)
            self.nodes[from_node].sendtoaddress(to_address, amount)

    def do_one_round(self):
        a0 = self.nodes[0].getnewaddress()
        a1 = self.nodes[1].getnewaddress()
        a2 = self.nodes[2].getnewaddress()

        self.one_send(0, a1)
        self.one_send(0, a2)
        self.one_send(1, a0)
        self.one_send(1, a2)
        self.one_send(2, a0)
        self.one_send(2, a1)

        # Have the miner (node3) mine a block.
        # Must sync mempools before mining.
        sync_mempools(self.nodes)
        self.nodes[3].generate(1)

    # As above, this mirrors the original bash test.
    def start_three(self):
        # -exportdir option means we must provide a valid path to the destination folder for wallet backups
        ed0 = "-exportdir=" + self.options.tmpdir + "/node0"
        ed1 = "-exportdir=" + self.options.tmpdir + "/node1"
        ed2 = "-exportdir=" + self.options.tmpdir + "/node2"

        self.nodes[0] = start_node(0, self.options.tmpdir,
                                   ['-debug=zrpc', ed0])
        self.nodes[1] = start_node(1, self.options.tmpdir,
                                   ['-debug=zrpc', ed1])
        self.nodes[2] = start_node(2, self.options.tmpdir,
                                   ['-debug=zrpc', ed2])

        connect_nodes(self.nodes[0], 3)
        connect_nodes(self.nodes[1], 3)
        connect_nodes(self.nodes[2], 3)
        connect_nodes(self.nodes[2], 0)

    def stop_three(self):
        stop_node(self.nodes[0], 0)
        stop_node(self.nodes[1], 1)
        stop_node(self.nodes[2], 2)

    def erase_three(self):
        os.remove(self.options.tmpdir + "/node0/regtest/wallet.dat")
        os.remove(self.options.tmpdir + "/node1/regtest/wallet.dat")
        os.remove(self.options.tmpdir + "/node2/regtest/wallet.dat")

    def run_test(self):
        logging.info("Generating initial blockchain")
        self.nodes[0].generate(1)
        sync_blocks(self.nodes)
        self.nodes[1].generate(1)
        sync_blocks(self.nodes)
        self.nodes[2].generate(1)
        sync_blocks(self.nodes)
        self.nodes[3].generate(100)
        sync_blocks(self.nodes)

        assert_equal(self.nodes[0].getbalance(), 11.4375)
        assert_equal(self.nodes[1].getbalance(), 11.4375)
        assert_equal(self.nodes[2].getbalance(), 11.4375)
        assert_equal(self.nodes[3].getbalance(), 0)

        logging.info("Creating transactions")
        # Five rounds of sending each other transactions.
        for i in range(5):
            self.do_one_round()

        logging.info("Backing up")
        tmpdir = self.options.tmpdir
        self.nodes[0].backupwallet("walletbak")
        self.nodes[0].dumpwallet("walletdump")
        self.nodes[1].backupwallet("walletbak")
        self.nodes[1].dumpwallet("walletdump")
        self.nodes[2].backupwallet("walletbak")
        self.nodes[2].dumpwallet("walletdump")

        # Verify dumpwallet cannot overwrite an existing file
        try:
            self.nodes[2].dumpwallet("walletdump")
            assert (False)
        except JSONRPCException as e:
            errorString = e.error['message']
            assert ("Cannot overwrite existing file" in errorString)

        logging.info("More transactions")
        for i in range(5):
            self.do_one_round()

        # Generate 101 more blocks, so any fees paid mature
        self.nodes[3].generate(101)
        self.sync_all()

        balance0 = self.nodes[0].getbalance()
        balance1 = self.nodes[1].getbalance()
        balance2 = self.nodes[2].getbalance()
        balance3 = self.nodes[3].getbalance()
        total = balance0 + balance1 + balance2 + balance3

        # At this point, there are 214 blocks (103 for setup, then 10 rounds, then 101.)
        # 114 are mature, so the sum of all wallets should be 100*11.4375 + 4 * 11 + 10*8.75 = 1275.25
        assert_equal(total, 1275.25)

        ##
        # Test restoring spender wallets from backups
        ##
        logging.info("Restoring using wallet.dat")
        self.stop_three()
        self.erase_three()

        # Start node2 with no chain
        shutil.rmtree(self.options.tmpdir + "/node2/regtest/blocks")
        shutil.rmtree(self.options.tmpdir + "/node2/regtest/chainstate")

        # Restore wallets from backup
        shutil.copyfile(tmpdir + "/node0/walletbak",
                        tmpdir + "/node0/regtest/wallet.dat")
        shutil.copyfile(tmpdir + "/node1/walletbak",
                        tmpdir + "/node1/regtest/wallet.dat")
        shutil.copyfile(tmpdir + "/node2/walletbak",
                        tmpdir + "/node2/regtest/wallet.dat")

        logging.info("Re-starting nodes")
        self.start_three()
        sync_blocks(self.nodes)

        assert_equal(self.nodes[0].getbalance(), balance0)
        assert_equal(self.nodes[1].getbalance(), balance1)
        assert_equal(self.nodes[2].getbalance(), balance2)

        logging.info("Restoring using dumped wallet")
        self.stop_three()
        self.erase_three()

        #start node2 with no chain
        shutil.rmtree(self.options.tmpdir + "/node2/regtest/blocks")
        shutil.rmtree(self.options.tmpdir + "/node2/regtest/chainstate")

        self.start_three()

        assert_equal(self.nodes[0].getbalance(), 0)
        assert_equal(self.nodes[1].getbalance(), 0)
        assert_equal(self.nodes[2].getbalance(), 0)

        self.nodes[0].importwallet(tmpdir + "/node0/walletdump")
        self.nodes[1].importwallet(tmpdir + "/node1/walletdump")
        self.nodes[2].importwallet(tmpdir + "/node2/walletdump")

        sync_blocks(self.nodes)

        assert_equal(self.nodes[0].getbalance(), balance0)
        assert_equal(self.nodes[1].getbalance(), balance1)
        assert_equal(self.nodes[2].getbalance(), balance2)

        # reach sidechain fork
        nb = int(self.nodes[0].getblockcount())
        nb_to_gen = MINIMAL_SC_HEIGHT - nb
        if nb_to_gen > 0:
            mark_logs("Node 0 generates {} block".format(nb_to_gen),
                      self.nodes, DEBUG_MODE)
            self.nodes[0].generate(nb_to_gen)
            self.sync_all()

        safe_guard_size = EPOCH_LENGTH // 5
        if safe_guard_size < 2:
            safe_guard_size = 2

        creation_amount = Decimal("1.0")
        bwt_amount1 = Decimal("0.10")
        bwt_amount2 = Decimal("0.20")
        bwt_amount3 = Decimal("0.40")

        prev_epoch_hash = self.nodes[0].getbestblockhash()

        #generate wCertVk and constant
        mcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir)
        vk = mcTest.generate_params("sc1")
        constant = generate_random_field_element_hex()

        # do a shielded transaction for testing zaddresses in backup
        mark_logs("node0 shields it coinbase", self.nodes, DEBUG_MODE)
        zaddr0 = self.nodes[0].z_getnewaddress()
        res = self.nodes[0].z_shieldcoinbase("*", zaddr0)
        wait_and_assert_operationid_status(self.nodes[0], res['opid'])
        self.sync_all()

        self.nodes[0].generate(1)
        self.sync_all()

        mark_logs("node0 z_send to node1", self.nodes, DEBUG_MODE)
        zaddr1 = self.nodes[1].z_getnewaddress()
        opid = self.nodes[0].z_sendmany(zaddr0, [{
            "address": zaddr1,
            "amount": Decimal("1.234")
        }])
        wait_and_assert_operationid_status(self.nodes[0], opid)
        self.sync_all()

        # Create a SC
        cmdInput = {
            'version': 0,
            'withdrawalEpochLength': EPOCH_LENGTH,
            'toaddress': "dada",
            'amount': creation_amount,
            'wCertVk': vk,
            'constant': constant
        }

        ret = self.nodes[0].sc_create(cmdInput)
        scid = ret['scid']
        scid_swapped = str(swap_bytes(scid))
        mark_logs("created SC id: {}".format(scid), self.nodes, DEBUG_MODE)
        self.sync_all()

        mark_logs("Node0 confirms Sc creation generating 1 block", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        sc_creating_height = self.nodes[0].getblockcount()
        self.sync_all()

        mark_logs(
            "Node0 generates {} more blocks to achieve end of withdrawal epochs"
            .format(EPOCH_LENGTH - 1), self.nodes, DEBUG_MODE)
        self.nodes[0].generate(EPOCH_LENGTH - 1)
        self.sync_all()

        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)

        n1_initial_balance = self.nodes[1].getbalance()

        # node0 create a cert_1 for funding node1

        # skip default address, just to use a brand new one
        self.nodes[1].getnewaddress()

        addr_node1 = self.nodes[1].getnewaddress()
        amounts = [{
            "address": addr_node1,
            "amount": bwt_amount1
        }, {
            "address": addr_node1,
            "amount": bwt_amount2
        }]
        mark_logs(
            "Node 0 sends a cert for scid {} with 2 bwd transfers of {} coins to Node1 address"
            .format(scid, bwt_amount1 + bwt_amount2,
                    addr_node1), self.nodes, DEBUG_MODE)
        try:
            #Create proof for WCert
            quality = 1
            proof = mcTest.create_test_proof("sc1", scid_swapped, epoch_number,
                                             quality, MBTR_SC_FEE, FT_SC_FEE,
                                             epoch_cum_tree_hash, constant,
                                             [addr_node1, addr_node1],
                                             [bwt_amount1, bwt_amount2])

            cert_1 = self.nodes[0].sc_send_certificate(
                scid, epoch_number, quality, epoch_cum_tree_hash, proof,
                amounts, FT_SC_FEE, MBTR_SC_FEE, CERT_FEE)
            mark_logs("==> certificate is {}".format(cert_1), self.nodes,
                      DEBUG_MODE)
            self.sync_all()
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(
                "Send certificate failed with reason {}".format(errorString),
                self.nodes, DEBUG_MODE)
            assert (False)

        # start first epoch + 2*epocs + safe guard
        bwtMaturityHeight = (sc_creating_height -
                             1) + 2 * EPOCH_LENGTH + safe_guard_size

        # get the taddr of Node1 where the bwt is send to
        bwt_address = self.nodes[0].getrawtransaction(
            cert_1, 1)['vout'][1]['scriptPubKey']['addresses'][0]

        mark_logs(
            "Node0 generates {} more blocks to achieve end of withdrawal epochs"
            .format(EPOCH_LENGTH), self.nodes, DEBUG_MODE)
        self.nodes[0].generate(EPOCH_LENGTH)
        self.sync_all()

        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)
        mark_logs(
            "epoch_number = {}, epoch_cum_tree_hash = {}".format(
                epoch_number, epoch_cum_tree_hash), self.nodes, DEBUG_MODE)

        # node0 create a cert_2 for funding node1
        amounts = [{"address": addr_node1, "amount": bwt_amount3}]
        mark_logs(
            "Node 0 sends a cert for scid {} with 1 bwd transfers of {} coins to Node1 address"
            .format(scid, bwt_amount3, addr_node1), self.nodes, DEBUG_MODE)
        try:
            #Create proof for WCert
            quality = 1
            proof = mcTest.create_test_proof("sc1", scid_swapped, epoch_number,
                                             quality, MBTR_SC_FEE, FT_SC_FEE,
                                             epoch_cum_tree_hash, constant,
                                             [addr_node1], [bwt_amount3])

            cert_2 = self.nodes[0].sc_send_certificate(
                scid, epoch_number, quality, epoch_cum_tree_hash, proof,
                amounts, FT_SC_FEE, MBTR_SC_FEE, CERT_FEE)
            mark_logs("==> certificate is {}".format(cert_2), self.nodes,
                      DEBUG_MODE)
            self.sync_all()
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(
                "Send certificate failed with reason {}".format(errorString),
                self.nodes, DEBUG_MODE)
            assert (False)
示例#17
0
    def run_test(self):
        '''
        The test checks that the "GetBlockTemplate" command correctly detects a new certificate in the mempool,
        in the same way as it happens for normal transactions.
        '''

        # amounts
        creation_amount = Decimal("10")
        bwt_amount = Decimal("1.0")

        mark_logs("Node 0 generates {} block".format(MINIMAL_SC_HEIGHT),
                  self.nodes, DEBUG_MODE)
        self.nodes[0].generate(MINIMAL_SC_HEIGHT)
        self.sync_all()

        #generate wCertVk and constant
        mcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir)
        vk = mcTest.generate_params("sc1")
        constant = generate_random_field_element_hex()
        cmdInput = {
            "version": 0,
            "withdrawalEpochLength": EPOCH_LENGTH,
            "toaddress": "dada",
            "amount": creation_amount,
            "wCertVk": vk,
            "constant": constant,
        }

        ret = self.nodes[0].sc_create(cmdInput)
        scid = ret['scid']
        scid_swapped = str(swap_bytes(scid))
        mark_logs("Node 0 created a SC", self.nodes, DEBUG_MODE)

        nblocks = EPOCH_LENGTH
        mark_logs(
            "Node 0 generating {} more blocks to confirm the sidechain and reach the end of withdrawal epoch"
            .format(nblocks), self.nodes, DEBUG_MODE)
        self.nodes[0].generate(nblocks)
        self.sync_all()

        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)
        addr_node1 = self.nodes[1].getnewaddress()

        #Create proof for WCert
        quality = 10
        proof = mcTest.create_test_proof("sc1", scid_swapped, epoch_number,
                                         quality, MBTR_SC_FEE, FT_SC_FEE,
                                         epoch_cum_tree_hash, constant,
                                         [addr_node1], [bwt_amount])

        amount_cert_1 = [{"address": addr_node1, "amount": bwt_amount}]

        cur_h = self.nodes[0].getblockcount()
        ret = self.nodes[0].getscinfo(scid, True, False)['items'][0]
        ceas_h = ret['ceasingHeight']
        ceas_limit_delta = ceas_h - cur_h - 1

        mark_logs(
            "Node0 generating {} blocks reaching the third to last block before the SC ceasing"
            .format(ceas_limit_delta), self.nodes, DEBUG_MODE)
        self.nodes[0].generate(ceas_limit_delta - 2)
        self.sync_all()

        mark_logs(
            "\nCall GetBlockTemplate on each node to create a cached (empty) version",
            self.nodes, DEBUG_MODE)
        for i in range(0, NUMB_OF_NODES):
            self.nodes[i].getblocktemplate()

        mark_logs(
            "Node 0 sends a normal mainchain transaction to mempool and checks that it's not immediately included into the block template",
            self.nodes, DEBUG_MODE)
        self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 0.1)
        self.sync_all()

        for i in range(0, NUMB_OF_NODES):
            assert (len(self.nodes[i].getblocktemplate()['certificates']) == 0)
            assert (len(self.nodes[i].getblocktemplate()['transactions']) == 0)

        GET_BLOCK_TEMPLATE_DELAY = 5  # Seconds
        mark_logs(
            "Wait {} seconds and check that the transaction is now included into the block template"
            .format(GET_BLOCK_TEMPLATE_DELAY), self.nodes, DEBUG_MODE)
        time.sleep(GET_BLOCK_TEMPLATE_DELAY)
        for i in range(0, NUMB_OF_NODES):
            assert (len(self.nodes[i].getblocktemplate()['certificates']) == 0)
            assert (len(self.nodes[i].getblocktemplate()['transactions']) == 1)

        mark_logs("Node 0 mines one block to clean the mempool", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        self.sync_all()

        mark_logs(
            "\nCall GetBlockTemplate on each node to create a new cached version",
            self.nodes, DEBUG_MODE)
        for i in range(0, NUMB_OF_NODES):
            self.nodes[i].getblocktemplate()

        mark_logs("Node 0 sends a certificate", self.nodes, DEBUG_MODE)
        try:
            cert_epoch_0 = 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)
            assert (len(cert_epoch_0) > 0)
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(
                "Send certificate failed with reason {}".format(errorString),
                self.nodes, DEBUG_MODE)
            assert (False)
示例#18
0
    def run_test(self):

        ''' 
        (1) Create 3 parallel SCs with same epoch length
        (2) Advance epoch
        (3) Send a cert with bwt to sc 1
        (4) Send an empty cert to sc 2
        (5) (do not send any cert to sc 3)
        (6) Advance epoch
        (7) Reach safe guard --> all of 3 sc are ceased
        (8) Mine 3 blocks more
        (9) Restart nodes
        '''

        # transfer amounts
        creation_amount = []
        bwt_amount = []

        creation_amount.append(Decimal("10.0"))
        creation_amount.append(Decimal("20.0"))
        creation_amount.append(Decimal("30.0"))

        bwt_amount.append(Decimal("5.0"))
        bwt_amount.append(Decimal("0.0"))
        bwt_amount.append(Decimal("0.0"))

        mark_logs("Node 0 generates 220 block", self.nodes, DEBUG_MODE)
        self.nodes[0].generate(220)
        self.sync_all()
        prev_epoch_hash = self.nodes[0].getbestblockhash()

        #generate wCertVk and constant
        mcTest = MCTestUtils(self.options.tmpdir, self.options.srcdir)

        constant = generate_random_field_element_hex()

        scids = []
        # SCs creation
        for i in range(0, 3):
            tag = "sc"+str(i+1)
            vk = mcTest.generate_params(tag)
            ret = self.nodes[0].sc_create(EPOCH_LENGTH, "dada", creation_amount[i], vk, "abcdef", constant)
            creating_tx = ret['txid']
            mark_logs("Node 0 created SC spending {} coins via tx1 {}.".format(creation_amount[i], creating_tx), self.nodes, DEBUG_MODE)
            self.sync_all()
            scids.append(self.nodes[0].getrawtransaction(creating_tx, 1)['vsc_ccout'][0]['scid'])
            mark_logs("==> created SC ids {}".format(scids[-1]), self.nodes, DEBUG_MODE)
            

        mark_logs("Node0 generates 5 more blocks to achieve end of withdrawal epochs", self.nodes, DEBUG_MODE)
        self.nodes[0].generate(5)
        self.sync_all()

        # check epoch data are the same for all the scids
        assert_equal(get_epoch_data(scids[0], self.nodes[0], EPOCH_LENGTH), get_epoch_data(scids[1], self.nodes[0], EPOCH_LENGTH))
        assert_equal(get_epoch_data(scids[0], self.nodes[0], EPOCH_LENGTH), get_epoch_data(scids[2], self.nodes[0], EPOCH_LENGTH))

        epoch_block_hash, epoch_number = get_epoch_data(scids[0], self.nodes[0], EPOCH_LENGTH)
        mark_logs("epoch_number = {}, epoch_block_hash = {}".format(epoch_number, epoch_block_hash), self.nodes, DEBUG_MODE)

        last_cert_epochs = []
        last_cert_epochs.append(epoch_number)
        last_cert_epochs.append(epoch_number)
        last_cert_epochs.append(-1)

        # node0 create a cert_1 for funding node1 
        pkh_node1 = self.nodes[1].getnewaddress("", True)
        amounts = [{"pubkeyhash": pkh_node1, "amount": bwt_amount[0]}]
        mark_logs("Node 0 sends a cert for scid_1 {} with a bwd transfer of {} coins to Node1 pkh".format(scids[0], bwt_amount[0], pkh_node1), self.nodes, DEBUG_MODE)
        try:
            #Create proof for WCert
            quality = 1
            proof = mcTest.create_test_proof(
                "sc1", epoch_number, epoch_block_hash, prev_epoch_hash,
                quality, constant, [pkh_node1], [bwt_amount[0]])

            cert_1 = self.nodes[0].send_certificate(scids[0], epoch_number, quality, epoch_block_hash, proof, amounts, CERT_FEE)
            mark_logs("==> certificate is {}".format(cert_1), self.nodes, DEBUG_MODE)
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs("Send certificate failed with reason {}".format(errorString), self.nodes, DEBUG_MODE)
            assert(False)
示例#19
0
    def run_test(self):
        '''
        The test creates a sc, send funds to it and then sends a certificate to it,
        verifying also that specifying various combination of bad parameters causes a certificate
        to be refused. This test also checks that the receiver of cert backward transfer can spend it
        only when they become mature. 
        '''

        # forward transfer amounts
        creation_amount = Decimal("0.5")
        fwt_amount = Decimal("50")
        bwt_amount_bad = Decimal("100.0")
        bwt_amount = Decimal("50")
        bwt_amount_0_b = Decimal("0.10")

        self.nodes[0].getblockhash(0)

        # 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 {} block".format(MINIMAL_SC_HEIGHT),
                  self.nodes, DEBUG_MODE)
        self.nodes[0].generate(MINIMAL_SC_HEIGHT)
        self.sync_all()

        # SC creation
        bal_before_sc_creation = self.nodes[1].getbalance("", 0)
        mark_logs(
            "Node1 balance before SC creation: {}".format(
                bal_before_sc_creation), self.nodes, DEBUG_MODE)

        #generate wCertVk and constant
        mcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir)
        vk = mcTest.generate_params("sc1")
        constant = generate_random_field_element_hex()
        cmdInput = {
            "version": 0,
            "withdrawalEpochLength": EPOCH_LENGTH,
            "toaddress": "dada",
            "amount": creation_amount,
            "wCertVk": vk,
            "constant": constant
        }

        ret = self.nodes[1].sc_create(cmdInput)
        creating_tx = ret['txid']
        scid = ret['scid']
        scid_swapped = str(swap_bytes(scid))
        mark_logs(
            "Node 1 created the SC spending {} coins via tx {}.".format(
                creation_amount, creating_tx), self.nodes, DEBUG_MODE)
        self.sync_all()

        decoded_tx = self.nodes[1].getrawtransaction(creating_tx, 1)
        assert_equal(scid, decoded_tx['vsc_ccout'][0]['scid'])
        mark_logs("created SC id: {}".format(scid), self.nodes, DEBUG_MODE)

        mark_logs("Node0 confirms Sc creation generating 1 block", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        sc_creating_height = self.nodes[0].getblockcount()
        self.sync_all()

        # Check node 1 balance following sc creation
        fee_sc_creation = self.nodes[1].gettransaction(creating_tx)['fee']
        mark_logs("Fee paid for SC creation: {}".format(fee_sc_creation),
                  self.nodes, DEBUG_MODE)
        bal_after_sc_creation = self.nodes[1].getbalance("", 0)
        mark_logs(
            "Node1 balance after SC creation: {}".format(
                bal_after_sc_creation), self.nodes, DEBUG_MODE)
        assert_equal(bal_before_sc_creation,
                     bal_after_sc_creation + creation_amount - fee_sc_creation)

        assert_equal(self.nodes[0].getscinfo(scid)['items'][0]['balance'],
                     Decimal(0))
        assert_equal(
            self.nodes[0].getscinfo(scid)['items'][0]['immatureAmounts'][0]
            ['amount'], creation_amount)

        # Fwd Transfer to Sc
        bal_before_fwd_tx = self.nodes[0].getbalance("", 0)
        mark_logs("Node0 balance before fwd tx: {}".format(bal_before_fwd_tx),
                  self.nodes, DEBUG_MODE)
        mc_return_address = self.nodes[0].getnewaddress()
        cmdInput = [{
            'toaddress': "abcd",
            'amount': fwt_amount,
            "scid": scid,
            "mcReturnAddress": mc_return_address
        }]
        fwd_tx = self.nodes[0].sc_send(cmdInput)
        mark_logs(
            "Node0 transfers {} coins to SC with tx {}...".format(
                fwt_amount, fwd_tx), self.nodes, DEBUG_MODE)
        self.sync_all()

        mark_logs("Node0 confirms fwd transfer generating 1 block", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        self.sync_all()

        # Check node 0 balance following fwd tx
        fee_fwt = self.nodes[0].gettransaction(fwd_tx)['fee']
        mark_logs("Fee paid for fwd tx: {}".format(fee_fwt), self.nodes,
                  DEBUG_MODE)
        bal_after_fwd_tx = self.nodes[0].getbalance("", 0)
        mark_logs("Node0 balance after fwd: {}".format(bal_after_fwd_tx),
                  self.nodes, DEBUG_MODE)
        assert_equal(
            bal_before_fwd_tx, bal_after_fwd_tx + fwt_amount - fee_fwt -
            Decimal(MINER_REWARD_POST_H200))

        assert_equal(self.nodes[0].getscinfo(scid)['items'][0]['balance'],
                     Decimal(0))
        assert_equal(
            self.nodes[0].getscinfo(scid)['items'][0]['immatureAmounts'][0]
            ['amount'], creation_amount)
        assert_equal(
            self.nodes[0].getscinfo(scid)['items'][0]['immatureAmounts'][1]
            ['amount'], fwt_amount)

        nblocks = EPOCH_LENGTH - 2
        mark_logs(
            "Node0 generating {} more blocks to achieve end of withdrawal epoch"
            .format(nblocks), self.nodes, DEBUG_MODE)
        self.nodes[0].generate(nblocks)
        self.sync_all()
        assert_equal(self.nodes[0].getscinfo(scid)['items'][0]['balance'],
                     creation_amount + fwt_amount)  # Sc balance has matured
        assert_equal(
            len(self.nodes[0].getscinfo(scid)['items'][0]['immatureAmounts']),
            0)

        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)
        mark_logs(
            "epoch_number = {}, epoch_cum_tree_hash = {}".format(
                epoch_number, epoch_cum_tree_hash), self.nodes, DEBUG_MODE)

        addr_node1 = self.nodes[1].getnewaddress()

        #Create proof for WCert
        quality = 10
        proof = mcTest.create_test_proof("sc1", scid_swapped, epoch_number,
                                         quality, MBTR_SC_FEE, FT_SC_FEE,
                                         epoch_cum_tree_hash, constant,
                                         [addr_node1], [bwt_amount])

        amount_cert_1 = [{"address": addr_node1, "amount": bwt_amount}]

        #---------------------start negative tests-------------------------

        mark_logs(
            "Node 0 tries to send a cert with insufficient Sc balance...",
            self.nodes, DEBUG_MODE)
        amounts = [{"address": addr_node1, "amount": bwt_amount_bad}]

        try:
            self.nodes[0].sc_send_certificate(scid, epoch_number, quality,
                                              epoch_cum_tree_hash, proof,
                                              amounts, FT_SC_FEE, MBTR_SC_FEE,
                                              CERT_FEE)
            assert (False)
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(errorString, self.nodes, DEBUG_MODE)
示例#20
0
    def run_test(self):
        '''
        This script is useful for the generation of json outputs to be stored in github:
        (https://github.com/HorizenOfficial/zen/tree/master/doc/json-examples)
        ---
        System calls to the zen-cli are used (instead for instance of json.dump()) in order to preserve the exact order 
        of the JSON keys as the one the user gets when sending rpc commands on the console.
        ---
        In order to enable the writing of the cmds output to a file please set the constant WRITE_OUTPUT_TO_FILE to 'True'
        and if needed, set the preferred path where to write to, in the constant JSON_FILES_FOLDER_PATH
        '''
        WRITE_OUTPUT_TO_FILE = False
        JSON_FILES_FOLDER_PATH = "../../doc/json-examples/"

        def _get_path_info(nodeid, fileName):
            node_data_dir = os.path.join(self.options.tmpdir,
                                         "node" + str(nodeid))
            node_conf_dir = os.path.join(node_data_dir, "zen.conf")
            file_with_path = os.path.join(JSON_FILES_FOLDER_PATH + fileName)
            return node_conf_dir, file_with_path

        def dump_json_tx(fileName, tx, nodeid=0):

            if WRITE_OUTPUT_TO_FILE == False:
                return

            node_conf_dir, file_with_path = _get_path_info(nodeid, fileName)

            hex_tx = self.nodes[nodeid].getrawtransaction(tx)
            cmd_ret = subprocess.check_output([
                os.getenv("BITCOINCLI", "zen-cli"), "-conf=" + node_conf_dir,
                "-rpcwait", "decoderawtransaction",
                str(hex_tx).rstrip()
            ])
            with open(file_with_path, 'w') as f:
                f.write(cmd_ret)

        def dump_json_block(fileName, blockhash, verbose=2, nodeid=0):
            if WRITE_OUTPUT_TO_FILE == False:
                return

            node_conf_dir, file_with_path = _get_path_info(nodeid, fileName)

            cmd_ret = subprocess.check_output([
                os.getenv("BITCOINCLI", "zen-cli"), "-conf=" + node_conf_dir,
                "-rpcwait", "getblock", blockhash,
                str(verbose)
            ])
            with open(file_with_path, 'w') as f:
                f.write(cmd_ret)

        def dump_json_getscinfo(fileName, nodeid=0):
            if WRITE_OUTPUT_TO_FILE == False:
                return

            node_conf_dir, file_with_path = _get_path_info(nodeid, fileName)

            cmd_ret = subprocess.check_output([
                os.getenv("BITCOINCLI", "zen-cli"), "-conf=" + node_conf_dir,
                "-rpcwait", "getscinfo", "*"
            ])
            with open(file_with_path, 'w') as f:
                f.write(cmd_ret)

        def dump_json_getblocktemplate(fileName, nodeid=0):
            if WRITE_OUTPUT_TO_FILE == False:
                return

            node_conf_dir, file_with_path = _get_path_info(nodeid, fileName)

            cmd_ret = subprocess.check_output([
                os.getenv("BITCOINCLI", "zen-cli"), "-conf=" + node_conf_dir,
                "-rpcwait", "getblocktemplate"
            ])
            with open(file_with_path, 'w') as f:
                f.write(cmd_ret)

        # 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()

        #generate wCertVk and constant
        certMcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir)
        cswMcTest = CSWTestUtils(self.options.tmpdir, self.options.srcdir)
        vk = certMcTest.generate_params('sc1')
        cswVk = cswMcTest.generate_params("sc1")
        constant1 = generate_random_field_element_hex()

        amount = Decimal('10.0')
        fee = Decimal('0.000025')
        feCfg = []
        cmtCfg = []

        # all certs must have custom FieldElements with exactly those values as size in bits
        feCfg.append([31, 48, 16])

        # one custom bv element with:
        # - as many bits in the uncompressed form (must be divisible by 254 and 8)
        # - a compressed size that allows the usage of BIT_VECTOR_BUF
        cmtCfg.append([[254 * 4, len(BIT_VECTOR_BUF) / 2]])

        # ascii chars, just for storing a text string
        customData = "746869732069732061207465737420737472696e67"

        cmdInput = {
            'version': 0,
            'withdrawalEpochLength': EPOCH_LENGTH,
            'amount': amount,
            'fee': fee,
            'constant': constant1,
            'wCertVk': vk,
            'toaddress': "cdcd",
            'wCeasedVk': cswVk,
            'customData': customData,
            'vFieldElementCertificateFieldConfig': feCfg[0],
            'vBitVectorCertificateFieldConfig': cmtCfg[0],
            'forwardTransferScFee': Decimal('0.001'),
            'mainchainBackwardTransferScFee': Decimal('0.002'),
            'mainchainBackwardTransferRequestDataLength': 2
        }

        mark_logs(
            "\nNode 1 create SC1 with valid vFieldElementCertificateFieldConfig / vBitVectorCertificateFieldConfig pair",
            self.nodes, DEBUG_MODE)
        try:
            res = self.nodes[1].sc_create(cmdInput)
            tx = res['txid']
            scid1 = res['scid']
            scid1_swapped = str(swap_bytes(scid1))
        except JSONRPCException as e:
            errorString = e.error['message']
            mark_logs(errorString, self.nodes, DEBUG_MODE)
            assert_true(False)

        self.sync_all()
        print("tx = {}".format(tx))

        dump_json_tx('sidechain-creation-output.json', tx)

        # two more SC creations
        #-------------------------------------------------------
        vk = certMcTest.generate_params("sc2")
        constant2 = generate_random_field_element_hex()
        customData = "c0ffee"
        cswVk = ""
        feCfg.append([16])
        cmtCfg.append([])

        cmdInput = {
            'version': 0,
            'withdrawalEpochLength': EPOCH_LENGTH,
            'toaddress': "dada",
            'amount': amount,
            'wCertVk': vk,
            'customData': customData,
            'constant': constant2,
            'wCeasedVk': cswVk,
            'vFieldElementCertificateFieldConfig': feCfg[1],
            'vBitVectorCertificateFieldConfig': cmtCfg[1],
            'forwardTransferScFee': 0,
            'mainchainBackwardTransferScFee': 0,
            'mainchainBackwardTransferRequestDataLength': 1
        }

        mark_logs(
            "\nNode 1 create SC2 with valid vFieldElementCertificateFieldConfig / vBitVectorCertificateFieldConfig pair",
            self.nodes, DEBUG_MODE)
        try:
            ret = self.nodes[1].sc_create(cmdInput)
        except JSONRPCException as e:
            errorString = e.error['message']
            mark_logs(errorString, self.nodes, DEBUG_MODE)
            assert_true(False)
        self.sync_all()

        creating_tx = ret['txid']
        scid2 = ret['scid']
        scid2_swapped = str(swap_bytes(scid2))

        print("tx = {}".format(creating_tx))

        decoded_tx = self.nodes[1].getrawtransaction(creating_tx, 1)
        dec_sc_id = decoded_tx['vsc_ccout'][0]['scid']

        #-------------------------------------------------------
        vk = certMcTest.generate_params("sc3")
        constant3 = generate_random_field_element_hex()
        customData = "badc0ffee"
        feCfg.append([])
        cmtCfg.append([[254 * 8 * 4, 1967]])

        sc_cr = [{
            "version": 0,
            "epoch_length": EPOCH_LENGTH,
            "amount": amount,
            "address": "ddaa",
            "wCertVk": vk,
            "constant": constant3,
            "vFieldElementCertificateFieldConfig": feCfg[2],
            "vBitVectorCertificateFieldConfig": cmtCfg[2]
        }]

        mark_logs(
            "\nNode 0 create SC3 with valid vFieldElementCertificateFieldConfig / vBitVectorCertificateFieldConfig pair",
            self.nodes, DEBUG_MODE)
        try:
            rawtx = self.nodes[0].createrawtransaction([], {}, [], sc_cr)
            funded_tx = self.nodes[0].fundrawtransaction(rawtx)
            sigRawtx = self.nodes[0].signrawtransaction(funded_tx['hex'])
            creating_tx = self.nodes[0].sendrawtransaction(sigRawtx['hex'])
        except JSONRPCException as e:
            errorString = e.error['message']
            mark_logs(errorString, self.nodes, DEBUG_MODE)
            assert_true(False)
        self.sync_all()

        decoded_tx = self.nodes[0].getrawtransaction(creating_tx, 1)
        scid3 = decoded_tx['vsc_ccout'][0]['scid']
        print("tx = {}".format(creating_tx))

        #-------------------------------------------------------
        mark_logs("\nNode 0 generates 1 block confirming SC creations",
                  self.nodes, DEBUG_MODE)
        self.nodes[0].generate(1)
        self.sync_all()

        # send funds to SC1
        amounts = []
        fwt_amount_1 = Decimal("2.0")
        fwt_amount_2 = Decimal("10.0")
        fwt_amount_3 = Decimal("3.0")
        fwt_amount_many = fwt_amount_1 + fwt_amount_2 + fwt_amount_3

        mark_logs(
            "\nNode 0 sends 3 amounts to SC 1 (tot: " + str(fwt_amount_many) +
            ")", self.nodes, DEBUG_MODE)
        mc_return_address1 = self.nodes[0].getnewaddress()
        mc_return_address2 = self.nodes[0].getnewaddress()
        mc_return_address3 = self.nodes[0].getnewaddress()
        amounts.append({
            "toaddress": "add1",
            "amount": fwt_amount_1,
            "scid": scid1,
            "mcReturnAddress": mc_return_address1
        })
        amounts.append({
            "toaddress": "add2",
            "amount": fwt_amount_2,
            "scid": scid2,
            "mcReturnAddress": mc_return_address2
        })
        amounts.append({
            "toaddress": "add3",
            "amount": fwt_amount_3,
            "scid": scid3,
            "mcReturnAddress": mc_return_address3
        })
        tx = self.nodes[0].sc_send(amounts)
        self.sync_all()

        print("tx = {}".format(tx))
        dump_json_tx('forward-transfer-output.json', tx)

        # request some mainchain backward transfer
        mark_logs("\nNode0 creates a tx with a bwt request", self.nodes,
                  DEBUG_MODE)
        fe1 = generate_random_field_element_hex()
        fe2 = generate_random_field_element_hex()
        fe3 = generate_random_field_element_hex()
        mc_dest_addr0 = self.nodes[0].getnewaddress()
        mc_dest_addr1 = self.nodes[1].getnewaddress()
        outputs = [{
            'vScRequestData': [fe1, fe2],
            'scFee': Decimal("0.0025"),
            'scid': scid1,
            'mcDestinationAddress': mc_dest_addr0
        }, {
            'vScRequestData': [fe3],
            'scFee': Decimal("0.0026"),
            'scid': scid2,
            'mcDestinationAddress': mc_dest_addr1
        }]

        cmdParms = {"minconf": 0, "changeaddress": mc_dest_addr0}
        try:
            tx = self.nodes[0].sc_request_transfer(outputs, cmdParms)
        except JSONRPCException as e:
            errorString = e.error['message']
            mark_logs(errorString, self.nodes, DEBUG_MODE)
            assert_true(False)
        print("tx = {}".format(tx))
        dump_json_tx('mainchain-backward-transfer-request.json', tx)

        #-------------------------------------------------------
        # advance epoch
        mark_logs("\nNode 0 generates {} block".format(EPOCH_LENGTH - 1),
                  self.nodes, DEBUG_MODE)
        self.nodes[0].generate(EPOCH_LENGTH - 1)
        self.sync_all()

        epoch_number_1, epoch_cum_tree_hash_1 = get_epoch_data(
            scid1, self.nodes[0], EPOCH_LENGTH)
        mark_logs(
            "epoch_number = {}, epoch_cum_tree_hash = {}".format(
                epoch_number_1, epoch_cum_tree_hash_1), self.nodes, DEBUG_MODE)

        addr_node1a = self.nodes[1].getnewaddress()
        addr_node1b = self.nodes[1].getnewaddress()
        addr_node0 = self.nodes[1].getnewaddress()
        bwt_amount_1 = Decimal("0.2")
        bwt_amount_2 = Decimal("0.15")

        # get a UTXO
        utx, change = get_spendable(self.nodes[0], CERT_FEE)

        inputs = [{'txid': utx['txid'], 'vout': utx['vout']}]
        outputs = {addr_node0: change}
        bwt_outs = [{
            "address": addr_node1a,
            "amount": bwt_amount_1
        }, {
            "address": addr_node1b,
            "amount": bwt_amount_2
        }]
        addresses = []
        amounts = []

        # preserve order for proof validity
        for entry in bwt_outs:
            addresses.append(entry["address"])
            amounts.append(entry["amount"])

        #-------------------------------------------------------
        mark_logs(
            "\nCreate raw cert with good custom field elements for SC2...",
            self.nodes, DEBUG_MODE)
        # cfgs for SC2: [16], []
        # we must be careful with ending bits for having valid fe.
        vCfe = ["0100"]
        vCmt = []

        # serialized fe for the proof has 32 byte size
        fe1 = get_field_element_with_padding("0100", 0)

        quality = 72
        scProof3 = certMcTest.create_test_proof('sc2', scid2_swapped,
                                                epoch_number_1, quality,
                                                MBTR_SC_FEE, FT_SC_FEE,
                                                epoch_cum_tree_hash_1,
                                                constant2, addresses, amounts,
                                                [fe1])

        params = {
            'scid': scid2,
            'quality': quality,
            'endEpochCumScTxCommTreeRoot': epoch_cum_tree_hash_1,
            'scProof': scProof3,
            'withdrawalEpochNumber': epoch_number_1,
            'vFieldElementCertificateField': vCfe,
            'vBitVectorCertificateField': vCmt,
            'ftScFee': FT_SC_FEE,
            'mbtrScFee': MBTR_SC_FEE
        }

        try:
            rawcert = self.nodes[0].createrawcertificate(
                inputs, outputs, bwt_outs, params)
            signed_cert = self.nodes[0].signrawtransaction(rawcert)
            cert = self.nodes[0].sendrawtransaction(signed_cert['hex'])
        except JSONRPCException as e:
            errorString = e.error['message']
            mark_logs(
                "Send certificate failed with reason {}".format(errorString),
                self.nodes, DEBUG_MODE)
            assert (False)

        self.sync_all()
        print("cert = {}".format(cert))

        #-------------------------------------------------------
        # get another UTXO
        utx, change = get_spendable(self.nodes[0], CERT_FEE)
        inputs = [{'txid': utx['txid'], 'vout': utx['vout']}]
        outputs = {self.nodes[0].getnewaddress(): change}

        mark_logs(
            "\nCreate raw cert with good custom field elements for SC1...",
            self.nodes, DEBUG_MODE)

        # Any number ending with 0x00 is not over module for being a valid field element, therefore it is OK
        vCfe = ["ab000100", "ccccdddd0000", "0100"]
        # this is a compressed buffer which will yield a valid field element for the proof (see below)
        vCmt = [BIT_VECTOR_BUF]

        fe1 = get_field_element_with_padding("ab000100", 0)
        fe2 = get_field_element_with_padding("ccccdddd0000", 0)
        fe3 = get_field_element_with_padding("0100", 0)
        fe4 = BIT_VECTOR_FE

        quality = 18
        scProof3 = certMcTest.create_test_proof('sc1', scid1_swapped,
                                                epoch_number_1, quality,
                                                MBTR_SC_FEE, FT_SC_FEE,
                                                epoch_cum_tree_hash_1,
                                                constant1, addresses, amounts,
                                                [fe1, fe2, fe3, fe4])

        params = {
            'scid': scid1,
            'quality': quality,
            'endEpochCumScTxCommTreeRoot': epoch_cum_tree_hash_1,
            'scProof': scProof3,
            'withdrawalEpochNumber': epoch_number_1,
            'vFieldElementCertificateField': vCfe,
            'vBitVectorCertificateField': vCmt,
            'ftScFee': FT_SC_FEE,
            'mbtrScFee': MBTR_SC_FEE
        }

        try:
            rawcert = self.nodes[0].createrawcertificate(
                inputs, outputs, bwt_outs, params)
            signed_cert = self.nodes[0].signrawtransaction(rawcert)
            cert = self.nodes[0].sendrawtransaction(signed_cert['hex'])
        except JSONRPCException as e:
            errorString = e.error['message']
            mark_logs(
                "Send certificate failed with reason {}".format(errorString),
                self.nodes, DEBUG_MODE)
            assert (False)
        self.sync_all()

        print("cert = {}".format(cert))
        dump_json_tx('certificate-with-backward-transfer.json', cert)

        # add a pair of standard txes
        self.nodes[0].sendtoaddress(addr_node1a, Decimal('0.1'))
        self.nodes[1].sendtoaddress(addr_node0, Decimal('0.2'))

        dump_json_getblocktemplate('getblocktemplate.json', nodeid=0)

        bl = self.nodes[0].generate(1)[-1]
        self.sync_all()

        dump_json_block('block-with-certificates.json', bl, 1)
        dump_json_block('block-with-certificates-expanded.json', bl, 2)

        # advance one epochs for SC1 and let the others cease
        mark_logs(
            "\nLet 1 epoch pass by and send a cert for SC1 only...".format(
                EPOCH_LENGTH), self.nodes, DEBUG_MODE)

        cert, epoch_number = advance_epoch(certMcTest, self.nodes[0],
                                           self.sync_all, scid1, "sc1",
                                           constant1, EPOCH_LENGTH, 10,
                                           CERT_FEE, FT_SC_FEE, MBTR_SC_FEE,
                                           vCfe, vCmt, [fe1, fe2, fe3, fe4])

        mark_logs(
            "\n==> certificate from SC1 for epoch {} {}".format(
                epoch_number, cert), self.nodes, DEBUG_MODE)

        dump_json_getscinfo('getscinfo-output.json', nodeid=0)

        mark_logs("Let also SC1 cease... ".format(scid2), self.nodes,
                  DEBUG_MODE)

        nbl = int(EPOCH_LENGTH * 1.5)
        mark_logs("Node0 generates {} blocks".format(nbl), self.nodes,
                  DEBUG_MODE)
        # let all sidechains cease
        self.nodes[0].generate(3 * EPOCH_LENGTH)
        self.sync_all()

        mark_logs(
            "\nCreate a CSW for SC1 withdrawing coins for two different addresses... ",
            self.nodes, DEBUG_MODE)

        # CSW sender MC address
        csw_mc_address = self.nodes[0].getnewaddress()

        sc_csw_amount_0 = Decimal('2.0')
        sc_csw_amount_1 = Decimal('1.0')
        null0 = generate_random_field_element_hex()
        null1 = generate_random_field_element_hex()
        actCertData = self.nodes[0].getactivecertdatahash(
            scid1)['certDataHash']

        ceasingCumScTxCommTree = self.nodes[0].getceasingcumsccommtreehash(
            scid1)['ceasingCumScTxCommTree']

        sc_proof0 = cswMcTest.create_test_proof("sc1", sc_csw_amount_0,
                                                scid1_swapped, null0,
                                                csw_mc_address,
                                                ceasingCumScTxCommTree,
                                                actCertData, constant1)

        sc_proof1 = cswMcTest.create_test_proof("sc1", sc_csw_amount_1,
                                                scid1_swapped, null1,
                                                csw_mc_address,
                                                ceasingCumScTxCommTree,
                                                actCertData, constant1)

        sc_csws = [{
            "amount": sc_csw_amount_0,
            "senderAddress": csw_mc_address,
            "scId": scid1,
            "epoch": 0,
            "nullifier": null0,
            "activeCertData": actCertData,
            "ceasingCumScTxCommTree": ceasingCumScTxCommTree,
            "scProof": sc_proof0
        }, {
            "amount": sc_csw_amount_1,
            "senderAddress": csw_mc_address,
            "scId": scid1,
            "epoch": 0,
            "nullifier": null1,
            "activeCertData": actCertData,
            "ceasingCumScTxCommTree": ceasingCumScTxCommTree,
            "scProof": sc_proof1
        }]

        # recipient MC address
        taddr_0 = self.nodes[0].getnewaddress()
        taddr_1 = self.nodes[1].getnewaddress()
        sc_csw_tx_outs = {taddr_0: sc_csw_amount_0, taddr_1: sc_csw_amount_1}

        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")
        tx = self.nodes[0].sendrawtransaction(sigRawtx['hex'])
        mark_logs("sent csw retrieving coins on Node0 and Node1 behalf",
                  self.nodes, DEBUG_MODE)
        self.sync_all()

        print("tx = {}".format(tx))
        dump_json_tx('ceased-sidechain-withdrawal.json', tx)
示例#21
0
class sc_cert_base(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', '-debug=zendoo_mc_cryptolib', '-logtimemicros=1'
            ]] * NUMB_OF_NODES)

        for k in range(0, NUMB_OF_NODES - 1):
            connect_nodes_bi(self.nodes, k, k + 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):
        '''
        Node1 creates a sc and sends to it a certificate with a bwt to Node2 and a fee.
        Node0 mines a block and checks that the cert fee is contained in the coinbase
        Node0 sends a lot of small coins to Node3, who will use them as input for including a fee
        in a new certificate
        '''

        # cross chain transfer amounts
        creation_amount = Decimal("0.5")
        bwt_amount = Decimal("0.4")

        # 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 220 block", self.nodes, DEBUG_MODE)
        self.nodes[0].generate(220)
        self.sync_all()

        #generate wCertVk and constant
        mcTest = MCTestUtils(self.options.tmpdir, self.options.srcdir)
        vk = mcTest.generate_params("sc1")
        constant = generate_random_field_element_hex()

        ret = self.nodes[1].sc_create(EPOCH_LENGTH, "dada", creation_amount,
                                      vk, "", constant)
        creating_tx = ret['txid']
        scid = ret['scid']
        mark_logs(
            "Node 1 created the SC spending {} coins via tx {}.".format(
                creation_amount, creating_tx), self.nodes, DEBUG_MODE)
        self.sync_all()

        decoded_tx = self.nodes[1].getrawtransaction(creating_tx, 1)
        assert_equal(scid, decoded_tx['vsc_ccout'][0]['scid'])
        mark_logs("created SC id: {}".format(scid), self.nodes, DEBUG_MODE)

        mark_logs("Node0 confirms Sc creation generating 1 block", self.nodes,
                  DEBUG_MODE)
        prev_epoch_block_hash = self.nodes[0].getblockhash(
            self.nodes[0].getblockcount())
        self.nodes[0].generate(1)
        self.sync_all()

        # fee can be seen on sender wallet (it is a negative value)
        fee = self.nodes[1].gettransaction(creating_tx)['fee']
        mark_logs("Fee paid for SC creation: {}".format(fee), self.nodes,
                  DEBUG_MODE)

        mark_logs(
            "Node0 generating 4 more blocks to achieve end of withdrawal epoch",
            self.nodes, DEBUG_MODE)
        self.nodes[0].generate(4)
        self.sync_all()

        mark_logs(
            "Sc {} state: {}".format(scid, self.nodes[0].getscinfo(scid)),
            self.nodes, DEBUG_MODE)

        epoch_block_hash, epoch_number = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)
        mark_logs(
            "epoch_number = {}, epoch_block_hash = {}".format(
                epoch_number, epoch_block_hash), self.nodes, DEBUG_MODE)

        pkh_node2 = self.nodes[2].getnewaddress("", True)

        amounts = [{"pubkeyhash": pkh_node2, "amount": bwt_amount}]

        #Create proof for WCert
        quality = 1
        proof = mcTest.create_test_proof("sc1", epoch_number, epoch_block_hash,
                                         prev_epoch_block_hash, quality,
                                         constant, [pkh_node2], [bwt_amount])

        mark_logs(
            "Node 1 performs a bwd transfer of {} coins to Node2 pkh".format(
                bwt_amount, pkh_node2), self.nodes, DEBUG_MODE)
        try:
            cert_good = self.nodes[1].send_certificate(scid, epoch_number,
                                                       quality,
                                                       epoch_block_hash, proof,
                                                       amounts, CERT_FEE)
            assert (len(cert_good) > 0)
            mark_logs("Certificate is {}".format(cert_good), self.nodes,
                      DEBUG_MODE)
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(
                "Send certificate failed with reason {}".format(errorString),
                self.nodes, DEBUG_MODE)
            assert (False)

        mark_logs("Checking mempools alignement", self.nodes, DEBUG_MODE)
        self.sync_all()
        for i in range(1, NUMB_OF_NODES):
            assert_equal(sorted(self.nodes[0].getrawmempool()),
                         sorted(self.nodes[i].getrawmempool()))

        mark_logs("Check cert is in mempools", self.nodes, DEBUG_MODE)
        assert_equal(True, cert_good in self.nodes[0].getrawmempool())

        mark_logs("Node0 confims bwd transfer generating 1 block", self.nodes,
                  DEBUG_MODE)
        mined = self.nodes[0].generate(1)[0]
        self.sync_all()

        mark_logs("Check cert is not in mempool anymore", self.nodes,
                  DEBUG_MODE)
        assert_equal(False, cert_good in self.nodes[0].getrawmempool())

        mark_logs("Check block coinbase contains the certificate fee",
                  self.nodes, DEBUG_MODE)
        coinbase = self.nodes[0].getblock(mined, True)['tx'][0]
        decoded_coinbase = self.nodes[2].getrawtransaction(coinbase, 1)
        miner_quota = decoded_coinbase['vout'][0]['value']
        assert_equal(miner_quota, (Decimal('7.5') + CERT_FEE))

        mark_logs(
            "Checking that amount transferred by certificate reaches Node2 wallet and it is immature",
            self.nodes, DEBUG_MODE)
        res = self.nodes[2].gettransaction(cert_good)
        cert_net_amount = res['details'][0]['amount']
        assert_equal(cert_net_amount, bwt_amount)

        # Node0 sends a lot of small coins to Node3, who will use as input for certificate fee
        taddr3 = self.nodes[3].getnewaddress()
        small_amount = Decimal("0.0000123")
        for n in range(0, 30):
            self.nodes[0].sendtoaddress(taddr3, small_amount)

        self.sync_all()

        mark_logs("Node 0 generates 4 block", self.nodes, DEBUG_MODE)
        self.nodes[0].generate(4)
        self.sync_all()

        prev_epoch_block_hash = epoch_block_hash
        epoch_block_hash, epoch_number = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)
        mark_logs(
            "epoch_number = {}, epoch_block_hash = {}".format(
                epoch_number, epoch_block_hash), self.nodes, DEBUG_MODE)

        bal3 = self.nodes[3].getbalance()
        bwt_amount_2 = bal3 / 2

        amounts = [{"pubkeyhash": pkh_node2, "amount": bwt_amount_2}]

        #Create proof for WCert
        quality = 2
        proof = mcTest.create_test_proof("sc1", epoch_number, epoch_block_hash,
                                         prev_epoch_block_hash, quality,
                                         constant, [pkh_node2], [bwt_amount_2])

        mark_logs(
            "Node 3 performs a bwd transfer of {} coins to Node2 pkh".format(
                bwt_amount_2, pkh_node2), self.nodes, DEBUG_MODE)
        try:
            cert = self.nodes[3].send_certificate(scid, epoch_number, quality,
                                                  epoch_block_hash, proof,
                                                  amounts, CERT_FEE)
            assert (len(cert) > 0)
            mark_logs("Certificate is {}".format(cert), self.nodes, DEBUG_MODE)
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(
                "Send certificate failed with reason {}".format(errorString),
                self.nodes, DEBUG_MODE)
            assert (False)
    def run_test(self):
        self.init_nodes()

        ###########################
        # TRANSPARENT TX          #
        ###########################
        print("TESTING TRANSPARENT TX")

        # Arrange
        unspent = self.nodes[0].listunspent()[0]
        inputs = [{'txid': unspent['txid'], 'vout': unspent['vout']}]
        outputs = {
            self.nodes[0].getnewaddress(): unspent['amount'] - Decimal('0.001')
        }
        raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
        signed_tx = self.nodes[0].signrawtransaction(raw_tx)

        # Act
        r = requests.post(url=BASE_URL + "tx/send",
                          json={"rawtx": signed_tx['hex']})

        # Assert
        final_raw_tx = r.json()['txid']
        assert_equal(final_raw_tx is not None, True)
        print('SUCCESS - txid: {}'.format(final_raw_tx))

        self.nodes[0].generate(1)
        self.sync_all()

        ###########################
        # CREATE SC TX            #
        ###########################
        print("TESTING CREATE SC TX")

        # Arrange

        # 1. Generate enough blocks to create a side chain
        self.nodes[1].generate(MINIMAL_SC_VERSION_HEIGHT -
                               self.nodes[0].getblockcount())
        self.sync_all()

        # 2. Define side chain values
        cert_mc_test = CertTestUtils(self.options.tmpdir, self.options.srcdir)
        csw_mc_test = CSWTestUtils(self.options.tmpdir, self.options.srcdir)
        sc_address = "0000000000000000000000000000000000000000000000000000000000000abc"
        sc_epoch_len = 123
        sc_cr_amount = Decimal('10.00000000')
        vk = cert_mc_test.generate_params("sc1")
        csw_vk = csw_mc_test.generate_params("csw1")
        constant = generate_random_field_element_hex()
        sc_cr = [{
            "epoch_length": sc_epoch_len,
            "amount": sc_cr_amount,
            "address": sc_address,
            "wCertVk": vk,
            "wCeasedVk": csw_vk,
            "constant": constant,
            "version": 1
        }]

        # 3. Prepare a UTXO to fund the side chain
        txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(),
                                           sc_cr_amount)
        self.sync_all()
        self.nodes[0].generate(1)
        self.sync_all()
        decoded_tx = self.nodes[0].decoderawtransaction(
            self.nodes[0].gettransaction(txid)['hex'])
        vout = {}
        for outpoint in decoded_tx['vout']:
            if outpoint['value'] == sc_cr_amount:
                vout = outpoint
                break

        # 4. Prepare raw transaction
        inputs = [{'txid': txid, 'vout': vout['n']}]
        raw_tx = self.nodes[0].createrawtransaction(inputs, {}, [], sc_cr, [])
        sign_raw_tx = self.nodes[0].signrawtransaction(raw_tx)

        # Act
        r = requests.post(url=BASE_URL + "tx/send",
                          json={"rawtx": sign_raw_tx['hex']})

        # Assert
        final_raw_tx = r.json()['txid']
        decoded_tx = self.nodes[0].getrawtransaction(final_raw_tx, 1)
        scid = decoded_tx['vsc_ccout'][0]['scid']

        assert_equal(final_raw_tx is not None, True)
        assert_equal(scid is not None, True)
        print('SUCCESS - scid: {}'.format(scid))

        self.nodes[0].generate(1)
        self.sync_all()

        ###########################
        # SC FORWARD TRANSFER TX  #
        ###########################
        print("TESTING SC FORWARD TRANSFER TX")

        # Arrange
        inputs = []
        sc_ft_amount = Decimal('10.00000000')
        mc_return_address = self.nodes[0].getnewaddress()
        sc_ft = [{
            "address": sc_address,
            "amount": sc_ft_amount,
            "scid": scid,
            "mcReturnAddress": mc_return_address
        }]
        raw_tx = self.nodes[0].createrawtransaction(inputs, {}, [], [], sc_ft)
        funded_tx = self.nodes[0].fundrawtransaction(raw_tx)
        sign_raw_tx = self.nodes[0].signrawtransaction(funded_tx['hex'])

        # Act
        r = requests.post(url=BASE_URL + "tx/send",
                          json={"rawtx": sign_raw_tx['hex']})

        # Assert
        final_raw_tx = r.json()['txid']
        assert_equal(final_raw_tx is not None, True)
        print('SUCCESS - txid: {}'.format(final_raw_tx))

        self.nodes[0].generate(1)
        self.sync_all()

        ###########################
        # SC CERTIFICATE TX       #
        ###########################
        print("TESTING SC CERTIFICATE TX")

        # Arrange
        self.nodes[0].generate(sc_epoch_len)
        self.sync_all()
        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[0], sc_epoch_len)
        proof = cert_mc_test.create_test_proof("sc1", swap_bytes(scid),
                                               epoch_number, 0, Decimal('0'),
                                               Decimal('0'),
                                               epoch_cum_tree_hash, constant)

        utx, change = get_spendable(self.nodes[0], CERT_FEE)
        raw_inputs = [{'txid': utx['txid'], 'vout': utx['vout']}]
        raw_outs = {self.nodes[0].getnewaddress(): change}
        raw_bwt_outs = []
        raw_params = {
            "scid": scid,
            "quality": 0,
            "endEpochCumScTxCommTreeRoot": epoch_cum_tree_hash,
            "scProof": proof,
            "withdrawalEpochNumber": epoch_number
        }
        raw_cert = self.nodes[0].createrawcertificate(raw_inputs, raw_outs,
                                                      raw_bwt_outs, raw_params)
        signed_cert = self.nodes[0].signrawtransaction(raw_cert)

        # Act
        r = requests.post(url=BASE_URL + "tx/send",
                          json={"rawtx": signed_cert['hex']})

        # Assert
        final_raw_tx = r.json()['txid']
        assert_equal(final_raw_tx is not None, True)
        print('SUCCESS - txid: {}'.format(final_raw_tx))

        self.nodes[0].generate(1)
        self.sync_all()
示例#23
0
        except JSONRPCException, e:
            errorString = e.error['message']
            print "Send certificate failed with reason {}".format(errorString)
            assert (False)
        sync_mempools(self.nodes[0:3])

        mark_logs("              Check cert {} is in mempool".format(cert_bad),
                  self.nodes, DEBUG_MODE)
        assert_true(cert_bad in self.nodes[0].getrawmempool())
        print "Node0 Chain h = ", self.nodes[0].getblockcount()

        # Network part 2
        #------------------
        mark_logs("\nNTW part 2) Node3 sends a certificate", self.nodes,
                  DEBUG_MODE)
        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[3], sc_epoch_len)

        bt_amount_2 = Decimal("10.0")
        addr_node1 = self.nodes[1].getnewaddress()
        quality = 5

        proof = certMcTest.create_test_proof("sc1", scid_swapped, epoch_number,
                                             quality, MBTR_SC_FEE, FT_SC_FEE,
                                             epoch_cum_tree_hash, constant,
                                             [addr_node1], [bt_amount_2])

        amount_cert = [{"address": addr_node1, "amount": bt_amount_2}]
        try:
            cert = self.nodes[3].sc_send_certificate(scid, epoch_number,
                                                     quality,
                                                     epoch_cum_tree_hash,
    def run_test(self):
        '''
        ( 1) Create a SC
        ( 2) Advance to next epoch
        ( 3) Send a cert to SC with 2 bwt to Node1 at the same address
        ( 4) checks behavior of some rpc cmd with bwt maturity info
        '''

        creation_amount = Decimal("10.0")
        bwt_amount1 = Decimal("1.5")
        bwt_amount2 = Decimal("2.0")
        bwt_amount3 = Decimal("4.0")

        mark_logs("Node 0 generates {} block".format(MINIMAL_SC_HEIGHT),
                  self.nodes, DEBUG_MODE)
        self.nodes[0].generate(MINIMAL_SC_HEIGHT)
        self.sync_all()

        # generate wCertVk and constant
        mcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir)
        vk = mcTest.generate_params("sc1")
        constant = generate_random_field_element_hex()
        cmdInput = {
            'version': 0,
            'withdrawalEpochLength': EPOCH_LENGTH,
            'toaddress': "dada",
            'amount': creation_amount,
            'wCertVk': vk,
            'constant': constant
        }

        # Create a SC with a budget of 10 coins
        ret = self.nodes[0].sc_create(cmdInput)
        creating_tx = ret['txid']
        scid = ret['scid']
        scid_swapped = str(swap_bytes(scid))
        mark_logs(
            "Node 0 created the SC spending {} coins via tx {}.".format(
                creation_amount, creating_tx), self.nodes, DEBUG_MODE)
        self.sync_all()

        decoded_tx = self.nodes[1].getrawtransaction(creating_tx, 1)
        assert_equal(scid, decoded_tx['vsc_ccout'][0]['scid'])
        mark_logs("created SC id: {}".format(scid), self.nodes, DEBUG_MODE)

        mark_logs("Node0 confirms Sc creation generating 1 block", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        sc_creating_height = self.nodes[0].getblockcount()
        self.sync_all()

        mark_logs(
            "Node0 generates 4 more blocks to achieve end of withdrawal epochs",
            self.nodes, DEBUG_MODE)
        self.nodes[0].generate(4)
        self.sync_all()

        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)

        bal_without_bwt = self.nodes[1].getbalance()

        # node0 create a cert_1 for funding node1
        addr_node1 = self.nodes[1].getnewaddress()
        amounts = [{
            "address": addr_node1,
            "amount": bwt_amount1
        }, {
            "address": addr_node1,
            "amount": bwt_amount2
        }]
        mark_logs(
            "Node 0 sends a cert for scid {} with 2 bwd transfers of {} coins to Node1 address"
            .format(scid, bwt_amount1 + bwt_amount2,
                    addr_node1), self.nodes, DEBUG_MODE)
        try:
            # Create proof for WCert
            quality = 1
            proof = mcTest.create_test_proof("sc1", scid_swapped, epoch_number,
                                             quality, MBTR_SC_FEE, FT_SC_FEE,
                                             epoch_cum_tree_hash, constant,
                                             [addr_node1, addr_node1],
                                             [bwt_amount1, bwt_amount2])

            cert_1 = self.nodes[0].sc_send_certificate(
                scid, epoch_number, quality, epoch_cum_tree_hash, proof,
                amounts, FT_SC_FEE, MBTR_SC_FEE, CERT_FEE)
            mark_logs("==> certificate is {}".format(cert_1), self.nodes,
                      DEBUG_MODE)
            self.sync_all()
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(
                "Send certificate failed with reason {}".format(errorString),
                self.nodes, DEBUG_MODE)
            assert (False)
示例#25
0
            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(
            scid, self.nodes[0], EPOCH_LENGTH)
        self.sync_all()

        # -------------------------- end epoch

        mark_logs(
            "Node2 tries to send to Node1 spending immature backward transfers, expecting failure...",
            self.nodes, DEBUG_MODE)
        # vout 0 is the change, vout 1 is the bwt
        inputs = [{'txid': cert, 'vout': 1}]
        rawtx_amount = Decimal("3.99995")
        outputs = {self.nodes[1].getnewaddress(): rawtx_amount}
        rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
        sigRawtx = self.nodes[2].signrawtransaction(rawtx)
        try:
            rawtx = self.nodes[2].sendrawtransaction(sigRawtx['hex'])
class sc_cert_bt_immature_balances(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'
            ]] * NUMB_OF_NODES)

        for k in range(0, NUMB_OF_NODES - 1):
            connect_nodes_bi(self.nodes, k, k + 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):
        '''
        ( 1) Create a SC
        ( 2) Advance to next epoch
        ( 3) Send a cert to SC with 2 bwt to Node1 at the same address
        ( 4) checks behavior of some rpc cmd with bwt maturity info
        '''

        creation_amount = Decimal("10.0")
        bwt_amount1 = Decimal("1.5")
        bwt_amount2 = Decimal("2.0")
        bwt_amount3 = Decimal("4.0")

        mark_logs("Node 0 generates {} block".format(MINIMAL_SC_HEIGHT),
                  self.nodes, DEBUG_MODE)
        self.nodes[0].generate(MINIMAL_SC_HEIGHT)
        self.sync_all()

        # generate wCertVk and constant
        mcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir)
        vk = mcTest.generate_params("sc1")
        constant = generate_random_field_element_hex()
        cmdInput = {
            'version': 0,
            'withdrawalEpochLength': EPOCH_LENGTH,
            'toaddress': "dada",
            'amount': creation_amount,
            'wCertVk': vk,
            'constant': constant
        }

        # Create a SC with a budget of 10 coins
        ret = self.nodes[0].sc_create(cmdInput)
        creating_tx = ret['txid']
        scid = ret['scid']
        scid_swapped = str(swap_bytes(scid))
        mark_logs(
            "Node 0 created the SC spending {} coins via tx {}.".format(
                creation_amount, creating_tx), self.nodes, DEBUG_MODE)
        self.sync_all()

        decoded_tx = self.nodes[1].getrawtransaction(creating_tx, 1)
        assert_equal(scid, decoded_tx['vsc_ccout'][0]['scid'])
        mark_logs("created SC id: {}".format(scid), self.nodes, DEBUG_MODE)

        mark_logs("Node0 confirms Sc creation generating 1 block", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        sc_creating_height = self.nodes[0].getblockcount()
        self.sync_all()

        mark_logs(
            "Node0 generates 4 more blocks to achieve end of withdrawal epochs",
            self.nodes, DEBUG_MODE)
        self.nodes[0].generate(4)
        self.sync_all()

        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)

        bal_without_bwt = self.nodes[1].getbalance()

        # node0 create a cert_1 for funding node1
        addr_node1 = self.nodes[1].getnewaddress()
        amounts = [{
            "address": addr_node1,
            "amount": bwt_amount1
        }, {
            "address": addr_node1,
            "amount": bwt_amount2
        }]
        mark_logs(
            "Node 0 sends a cert for scid {} with 2 bwd transfers of {} coins to Node1 address"
            .format(scid, bwt_amount1 + bwt_amount2,
                    addr_node1), self.nodes, DEBUG_MODE)
        try:
            # Create proof for WCert
            quality = 1
            proof = mcTest.create_test_proof("sc1", scid_swapped, epoch_number,
                                             quality, MBTR_SC_FEE, FT_SC_FEE,
                                             epoch_cum_tree_hash, constant,
                                             [addr_node1, addr_node1],
                                             [bwt_amount1, bwt_amount2])

            cert_1 = self.nodes[0].sc_send_certificate(
                scid, epoch_number, quality, epoch_cum_tree_hash, proof,
                amounts, FT_SC_FEE, MBTR_SC_FEE, CERT_FEE)
            mark_logs("==> certificate is {}".format(cert_1), self.nodes,
                      DEBUG_MODE)
            self.sync_all()
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(
                "Send certificate failed with reason {}".format(errorString),
                self.nodes, DEBUG_MODE)
            assert (False)

        # start first epoch + 2*epocs + safe guard
        bwtMaturityHeight = (sc_creating_height - 1) + 2 * EPOCH_LENGTH + 2

        # get the taddr of Node1 where the bwt is send to
        bwt_address = self.nodes[0].getrawtransaction(
            cert_1, 1)['vout'][1]['scriptPubKey']['addresses'][0]

        # get account for bwt_address
        bwt_account = self.nodes[1].getaccount(bwt_address)

        # ------------------------------------------------------------------
        # IN MEMPOOL CERTIFICATE
        # ------------------------------------------------------------------

        # Check unspent transactions
        unspent_utxos = self.nodes[1].listunspent()
        for utxo in unspent_utxos:
            assert_false(utxo["txid"] == cert_1)

        # Check unconfirmed balance
        assert_equal(0, self.nodes[1].getunconfirmedbalance())

        mark_logs("Check cert is in mempool", self.nodes, DEBUG_MODE)
        assert_equal(True, cert_1 in self.nodes[1].getrawmempool())

        mark_logs(
            "Check the output of the listtxesbyaddress cmd is as expected when cert is unconfirmed",
            self.nodes, DEBUG_MODE)
        res = self.nodes[1].listtxesbyaddress(bwt_address)
        assert_equal(res[0]['scid'], scid)
        assert_equal(res[0]['vout'][1]['maturityHeight'], bwtMaturityHeight)

        mark_logs(
            "Check the there are immature outputs in the unconfirmed tx data when cert is unconfirmed",
            self.nodes, DEBUG_MODE)
        ud = self.nodes[1].getunconfirmedtxdata(bwt_address)
        assert_equal(
            ud['bwtImmatureOutput'], Decimal("0.0")
        )  # not bwt_amount1+bwt_amount2 because bwts in mempool are considered voided
        # unconf bwt do not contribute to unconfOutput
        assert_equal(ud['unconfirmedOutput'], Decimal("0.0"))

        ud = self.nodes[1].getunconfirmedtxdata(bwt_address)
        assert_equal(ud['bwtImmatureOutput'], Decimal("0.0"))
        assert_equal(ud['unconfirmedOutput'], Decimal("0.0"))

        balance = self.nodes[1].getreceivedbyaddress(bwt_address, 0)
        assert_equal(bal_without_bwt, balance)

        balance_by_account = self.nodes[1].getreceivedbyaccount(bwt_account)
        assert_equal(bal_without_bwt, balance_by_account)

        addr_found = False
        # select an address with an UTXO value large enough
        listaddressgroupings = self.nodes[1].listaddressgroupings()
        for groups in listaddressgroupings:
            for entry in groups:
                if entry[0] == bwt_address:
                    assert_equal(
                        0, entry[1],
                        "listaddressgroupings: BT output amount expected to be empty"
                    )
                    pprint.pprint(entry)
                    addr_found = True
                    break

        assert_true(
            addr_found,
            "listaddressgroupings: BT outputs for address expect to be found but empty"
        )

        mark_logs(
            "Check that there are no immature outputs in the mempool cert gettransaction details.",
            self.nodes, DEBUG_MODE)
        include_immature_bts = False
        details = self.nodes[1].gettransaction(cert_1, False,
                                               include_immature_bts)['details']
        assert_equal(
            0, len(details),
            "gettransaction: mempool cert BT outputs expected to be skipped in any case (not applicable)."
        )
        include_immature_bts = True
        details = self.nodes[1].gettransaction(cert_1, False,
                                               include_immature_bts)['details']
        assert_equal(
            0, len(details),
            "gettransaction: mempool cert BT outputs expected to be skipped in any case (not applicable)."
        )

        # ------------------------------------------------------------------
        # IN CHAIN CERTIFICATE
        # ------------------------------------------------------------------

        mark_logs(
            "Node0 mines cert and cert immature outputs appear the unconfirmed tx data",
            self.nodes, DEBUG_MODE)
        block_id = self.nodes[0].generate(1)
        self.sync_all()

        # Check unconfirmed balance
        assert_equal(0, self.nodes[1].getunconfirmedbalance())

        ud = self.nodes[0].getunconfirmedtxdata(bwt_address)
        assert_equal(ud['bwtImmatureOutput'], Decimal("0.0"))
        assert_equal(ud['unconfirmedOutput'], Decimal("0.0"))

        ud = self.nodes[1].getunconfirmedtxdata(bwt_address)
        assert_equal(ud['bwtImmatureOutput'], bwt_amount1 + bwt_amount2)
        assert_equal(ud['unconfirmedOutput'], Decimal("0.0"))

        balance = self.nodes[1].getreceivedbyaddress(bwt_address)
        assert_equal(bal_without_bwt, balance)

        balance_by_account = self.nodes[1].getreceivedbyaccount(bwt_account)
        assert_equal(bal_without_bwt, balance_by_account)

        # Check unconfirmed balance
        assert_equal(0, self.nodes[0].getunconfirmedbalance())

        list_received = self.nodes[1].listreceivedbyaddress()
        check_array_result(list_received, {"address": bwt_address},
                           {"txids": [cert_1, cert_1]})
        assert_equal(len(list_received), 1)

        list_received = self.nodes[1].listreceivedbyaccount()
        assert_equal(len(list_received), 1)

        include_immature_bts = False
        list_transactions = self.nodes[1].listtransactions(
            "*", 100, 0, False, "*", include_immature_bts)
        assert_equal(
            0, len(list_transactions),
            "listtransactions: no cert immature BTs expected to be accounted.")

        include_immature_bts = True
        list_transactions = self.nodes[1].listtransactions(
            "*", 100, 0, False, "*", include_immature_bts)
        check_array_result(list_transactions, {"txid": cert_1},
                           {"txid": cert_1})

        include_immature_bts = False
        list_sinceblock = self.nodes[1].listsinceblock(
            bytes_to_hex_str(block_id[0]), 1, False, include_immature_bts)
        assert_equal(2, len(list_sinceblock))
        assert_equal(
            0, len(list_sinceblock['transactions']),
            "listsinceblock: no cert immature BTs expected to be accounted.")

        include_immature_bts = True
        list_sinceblock = self.nodes[1].listsinceblock(
            bytes_to_hex_str(block_id[0]), 1, False, include_immature_bts)
        assert_equal(2, len(list_sinceblock))
        check_array_result(list_sinceblock['transactions'], {"txid": cert_1},
                           {"txid": cert_1})

        # Check unspent transactions
        unspent_utxos = self.nodes[1].listunspent()
        for utxo in unspent_utxos:
            assert_false(utxo["txid"] == cert_1)

        res = self.nodes[1].listtxesbyaddress(bwt_address)
        for entry in res:
            assert_equal(entry['scid'], scid)
            assert_equal(entry['txid'], cert_1)

        addr_found = False
        # select an address with an UTXO value large enough
        listaddressgroupings = self.nodes[1].listaddressgroupings()
        for groups in listaddressgroupings:
            for entry in groups:
                if entry[0] == bwt_address:
                    assert_equal(
                        0, entry[1],
                        "listaddressgroupings: BT output amount expected to be empty"
                    )
                    pprint.pprint(entry)
                    addr_found = True
                    break

        assert_true(
            addr_found,
            "listaddressgroupings: BT outputs for address expect to be found but empty"
        )

        mark_logs(
            "Check that there are no immature outputs in the inchain cert gettransaction details by default.",
            self.nodes, DEBUG_MODE)
        include_immature_bts = False
        details = self.nodes[1].gettransaction(cert_1, False,
                                               include_immature_bts)['details']
        assert_equal(
            0, len(details),
            "gettransaction: inchain cert BT immature outputs expected to be skipped because of flag = False."
        )

        mark_logs(
            "Check that there are 2 immature outputs in the inchain cert gettransaction with includeImmatureBTs=True.",
            self.nodes, DEBUG_MODE)
        include_immature_bts = True
        details = self.nodes[1].gettransaction(cert_1, False,
                                               include_immature_bts)['details']
        assert_equal(
            2, len(details),
            "gettransaction: inchain cert BT immature outputs expected to be include because of flag = True."
        )
        for detail in details:
            assert_equal(
                "immature", detail["category"],
                "gettransaction: different category for immature Bt expected.")

        # ------------------------------------------------------------------
        # MATURE CERTIFICATE BT OUTPUTS
        # ------------------------------------------------------------------

        mark_logs(
            "Node0 generates 4 more blocks to achieve end of withdrawal epochs",
            self.nodes, DEBUG_MODE)
        self.nodes[0].generate(4)
        self.sync_all()

        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)
        mark_logs(
            "epoch_number = {}, epoch_cum_tree_hash = {}".format(
                epoch_number, epoch_cum_tree_hash), self.nodes, DEBUG_MODE)

        # node0 create a cert_2 for funding node1
        amounts = [{"address": addr_node1, "amount": bwt_amount3}]
        mark_logs(
            "Node 0 sends a cert for scid {} with 1 bwd transfers of {} coins to Node1 address"
            .format(scid, bwt_amount3, addr_node1), self.nodes, DEBUG_MODE)
        try:
            # Create proof for WCert
            quality = 1
            proof = mcTest.create_test_proof("sc1", scid_swapped, epoch_number,
                                             quality, MBTR_SC_FEE, FT_SC_FEE,
                                             epoch_cum_tree_hash, constant,
                                             [addr_node1], [bwt_amount3])

            cert_2 = self.nodes[0].sc_send_certificate(
                scid, epoch_number, quality, epoch_cum_tree_hash, proof,
                amounts, FT_SC_FEE, MBTR_SC_FEE, CERT_FEE)
            mark_logs("==> certificate is {}".format(cert_2), self.nodes,
                      DEBUG_MODE)
            self.sync_all()
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(
                "Send certificate failed with reason {}".format(errorString),
                self.nodes, DEBUG_MODE)
            assert (False)
示例#27
0
    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)
示例#28
0
    def run_test(self):
        self.nodes[0].generate(110)
        self.sync_all()
        time.sleep(30)
        #### /block/:hash ####

        #Test with a simple block with only 1-transparent address
        tAddr1 = self.nodes[1].getnewaddress()
        tTxId = self.nodes[0].sendtoaddress(tAddr1,5.0)
        self.sync_all()
        block = self.nodes[0].generate(2)
        self.sync_all()
        blockRPC = self.nodes[0].getblock(block[0])
        r = requests.get(url = self.BASE_URL+"block/"+block[0], params = {})
        data = r.json()
        self.validate_full_block(data,blockRPC)
        assert_true(data['isMainChain'])
        assert_true('cert' not in data)
        self.nodes[0].generate(1)
        self.sync_all()

        tAddr = self.nodes[0].getnewaddress()
        self.nodes[0].sendtoaddress(tAddr,20.0)
        self.sync_all()
        
        #Test with a bt
        self.nodes[0].generate(MINIMAL_SC_HEIGHT)
        self.sync_all()

        sc_epoch = 100
        sc_cr_amount = Decimal('5.00000000')

        #generate wCertVk and constant
        mcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir)
        vk = mcTest.generate_params("sc1")
        constant = generate_random_field_element_hex()
        scAddress = "8aaddc9671dc5c8d33a3494df262883411935f4f54002fe283745fb394be508a"

        sc = self.nodes[0].sc_create({"withdrawalEpochLength":sc_epoch, "customData":"dada", "amount":sc_cr_amount, "wCertVk":vk, "constant": constant, "toaddress":scAddress})

        scTxid = sc["txid"]
        scid = sc["scid"]
        self.sync_all()
        self.nodes[0].generate(1)
        self.sync_all()
        scid = self.nodes[0].gettransaction(scTxid)['vsc_ccout'][0]['scid']
        assert_equal(len(self.nodes[0].getscinfo("*")['items']),1)
        assert_equal(self.nodes[0].getscinfo("*")['items'][0]['scid'],scid)

        self.nodes[0].generate(100)
        self.sync_all()

        endBlockHash = self.nodes[0].getblockhash(320)
        quality = 5
        bwt_amount = 2.0
        epoch_number, epoch_cum_tree_hash = get_epoch_data(scid, self.nodes[0], sc_epoch)

        #Generate proof
        proof = mcTest.create_test_proof("sc1", str(swap_bytes(scid)), epoch_number, quality, MBTR_SC_FEE, FT_SC_FEE, 
            epoch_cum_tree_hash, constant, [tAddr1], [bwt_amount])
        amounts_cert = [{"address": tAddr1, "amount": bwt_amount}]

        self.nodes[1].sc_send_certificate(scid, epoch_number, quality, epoch_cum_tree_hash, proof, amounts_cert, FT_SC_FEE, MBTR_SC_FEE, CERT_FEE)

        self.sync_all()
        certblock = self.nodes[0].generate(1)
        self.sync_all()
        blockRPC = self.nodes[0].getblock(certblock[0])

        r = requests.get(url = self.BASE_URL+"block/"+certblock[0], params = {})
        data = r.json()
        self.validate_full_block(data,blockRPC)
        assert_true(data['isMainChain'])

        #Test with an invalid hash
        invalidHash = "010857e2c8d072c0142aad2faeca8a856e438fe2d1fe963d78dba8d9e5f664b8"
        r = requests.get(url = self.BASE_URL+"block/"+invalidHash, params = {})
        assert_equal(r.text,"Not found")

#############################################################################################################################

        #### /block-index/:height ####

        r = requests.get(url = self.BASE_URL+"block-index/320", params = {})
        data = r.json()
        assert_equal(data['blockHash'],endBlockHash)

        #Test with an invalid height
        r = requests.get(url = self.BASE_URL+"block-index/800", params = {})
        assert_equal(r.text,"Block height out of range. Code:-8")

#############################################################################################################################

        #### /rawblock/:blockHash ####

        r = requests.get(url = self.BASE_URL+"rawblock/"+endBlockHash, params = {})
        data = r.json()
        rawblockRPC = self.nodes[0].getblock(endBlockHash,False)
        assert_equal(data['rawblock'],rawblockRPC)

        #Test with an invalid hash
        r = requests.get(url = self.BASE_URL+"rawblock/800", params = {})
        assert_equal(r.text,"Not found")

        #Test with an invalid hash
        r = requests.get(url = self.BASE_URL+"rawblock/"+invalidHash, params = {})
        assert_equal(r.status_code, 404)

#############################################################################################################################

        #### /blocks ####
        self.nodes[0].generate(100)
        self.sync_all()
        #Test the max number of block returned
        r = requests.get(url = self.BASE_URL+"blocks", params = {})
        data = r.json()
        assert_equal(data['length'],200)
        assert_equal(len(data['blocks']),200)
        assert_true(data['pagination']['more'])

        #Test all blocks returned
        for block in data['blocks']:
            blockRPC = self.nodes[0].getblock(block['hash'])
            self.validate_block(block,blockRPC)
示例#29
0
    def run_test(self):
        '''
        The test creates a sc, send funds to it and then sends a certificate to it,
        Then test that getrawtransaction decodes correctly tx and cert when possible. 
        '''

        # forward transfer amounts
        creation_amount = Decimal("0.5")
        fwt_amount = Decimal("50")
        bwt_amount = Decimal("50")

        # 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 {} block".format(MINIMAL_SC_HEIGHT),
                  self.nodes, DEBUG_MODE)
        self.nodes[0].generate(MINIMAL_SC_HEIGHT)
        self.sync_all()

        # SC creation
        #generate wCertVk and constant
        mcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir)
        vk_tag = "sc1"
        vk = mcTest.generate_params(vk_tag)
        constant = generate_random_field_element_hex()
        cmdInput = {
            "version": 0,
            "withdrawalEpochLength": EPOCH_LENGTH,
            "toaddress": "dada",
            "amount": creation_amount,
            "wCertVk": vk,
            "constant": constant,
        }

        ret = self.nodes[1].sc_create(cmdInput)

        creating_tx = ret['txid']
        scid = ret['scid']
        scid_swapped = str(swap_bytes(scid))
        mark_logs(
            "Node 1 created the SC spending {} coins via tx {}.".format(
                creation_amount, creating_tx), self.nodes, DEBUG_MODE)
        self.sync_all()

        decoded_tx_mempool = self.nodes[1].getrawtransaction(creating_tx, 1)
        assert_equal(scid, decoded_tx_mempool['vsc_ccout'][0]['scid'])

        decoded_tx_mempool_hex = self.nodes[1].getrawtransaction(creating_tx)
        dec = self.nodes[1].decoderawtransaction(decoded_tx_mempool_hex)
        assert_equal(creating_tx, dec['txid'])
        assert_equal(scid, dec['vsc_ccout'][0]['scid'])

        mark_logs("Node0 confirms Sc creation generating 1 block", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        sc_creating_height = self.nodes[0].getblockcount()
        self.sync_all()

        decoded_tx_notxindex = self.nodes[1].getrawtransaction(creating_tx, 1)
        assert_equal(decoded_tx_mempool['hex'], decoded_tx_notxindex['hex'])

        decoded_tx_txindex = self.nodes[2].getrawtransaction(creating_tx, 1)
        assert_equal(decoded_tx_mempool['hex'], decoded_tx_txindex['hex'])

        # Fwd Transfer to Sc
        mark_logs("Node0 sends fwd transfer", self.nodes, DEBUG_MODE)

        mc_return_address = self.nodes[0].getnewaddress()
        cmdInput = [{
            'toaddress': "abcd",
            'amount': fwt_amount,
            "scid": scid,
            'mcReturnAddress': mc_return_address
        }]
        fwd_tx = self.nodes[0].sc_send(cmdInput)

        self.sync_all()

        decoded_tx_mempool = self.nodes[1].getrawtransaction(fwd_tx, 1)
        assert_equal(scid, decoded_tx_mempool['vft_ccout'][0]['scid'])

        mark_logs("Node0 confirms fwd transfer generating 1 block", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        self.sync_all()

        decoded_tx_notxindex = self.nodes[1].getrawtransaction(fwd_tx, 1)
        assert_equal(decoded_tx_mempool['hex'], decoded_tx_notxindex['hex'])
        decoded_tx_txindex = self.nodes[2].getrawtransaction(fwd_tx, 1)
        assert_equal(decoded_tx_mempool['hex'], decoded_tx_txindex['hex'])

        mark_logs(
            "Node0 generating 3 more blocks to achieve end of withdrawal epoch",
            self.nodes, DEBUG_MODE)
        self.nodes[0].generate(3)
        self.sync_all()

        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)

        addr_node1 = self.nodes[1].getnewaddress()
        amount_cert_1 = [{"address": addr_node1, "amount": bwt_amount}]

        #Create proof for WCert
        quality = 0
        proof = mcTest.create_test_proof(vk_tag, scid_swapped, epoch_number,
                                         quality, MBTR_SC_FEE, FT_SC_FEE,
                                         epoch_cum_tree_hash, constant,
                                         [addr_node1], [bwt_amount])

        mark_logs(
            "Node 0 performs a bwd transfer of {} coins to Node1 address {}".
            format(amount_cert_1[0]["address"],
                   amount_cert_1[0]["amount"]), self.nodes, DEBUG_MODE)
        try:
            cert_epoch_0 = 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)
            mark_logs("Certificate is {}".format(cert_epoch_0), self.nodes,
                      DEBUG_MODE)
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(
                "Send certificate failed with reason {}".format(errorString),
                self.nodes, DEBUG_MODE)
            assert (False)
示例#30
0
    def run_test(self):
        logging.info("Generating initial blockchain")
        self.nodes[0].generate(1)
        sync_blocks(self.nodes)
        self.nodes[1].generate(1)
        sync_blocks(self.nodes)
        self.nodes[2].generate(1)
        sync_blocks(self.nodes)
        self.nodes[3].generate(100)
        sync_blocks(self.nodes)

        assert_equal(self.nodes[0].getbalance(), 11.4375)
        assert_equal(self.nodes[1].getbalance(), 11.4375)
        assert_equal(self.nodes[2].getbalance(), 11.4375)
        assert_equal(self.nodes[3].getbalance(), 0)

        logging.info("Creating transactions")
        # Five rounds of sending each other transactions.
        for i in range(5):
            self.do_one_round()

        logging.info("Backing up")
        tmpdir = self.options.tmpdir
        self.nodes[0].backupwallet("walletbak")
        self.nodes[0].dumpwallet("walletdump")
        self.nodes[1].backupwallet("walletbak")
        self.nodes[1].dumpwallet("walletdump")
        self.nodes[2].backupwallet("walletbak")
        self.nodes[2].dumpwallet("walletdump")

        # Verify dumpwallet cannot overwrite an existing file
        try:
            self.nodes[2].dumpwallet("walletdump")
            assert (False)
        except JSONRPCException as e:
            errorString = e.error['message']
            assert ("Cannot overwrite existing file" in errorString)

        logging.info("More transactions")
        for i in range(5):
            self.do_one_round()

        # Generate 101 more blocks, so any fees paid mature
        self.nodes[3].generate(101)
        self.sync_all()

        balance0 = self.nodes[0].getbalance()
        balance1 = self.nodes[1].getbalance()
        balance2 = self.nodes[2].getbalance()
        balance3 = self.nodes[3].getbalance()
        total = balance0 + balance1 + balance2 + balance3

        # At this point, there are 214 blocks (103 for setup, then 10 rounds, then 101.)
        # 114 are mature, so the sum of all wallets should be 100*11.4375 + 4 * 11 + 10*8.75 = 1275.25
        assert_equal(total, 1275.25)

        ##
        # Test restoring spender wallets from backups
        ##
        logging.info("Restoring using wallet.dat")
        self.stop_three()
        self.erase_three()

        # Start node2 with no chain
        shutil.rmtree(self.options.tmpdir + "/node2/regtest/blocks")
        shutil.rmtree(self.options.tmpdir + "/node2/regtest/chainstate")

        # Restore wallets from backup
        shutil.copyfile(tmpdir + "/node0/walletbak",
                        tmpdir + "/node0/regtest/wallet.dat")
        shutil.copyfile(tmpdir + "/node1/walletbak",
                        tmpdir + "/node1/regtest/wallet.dat")
        shutil.copyfile(tmpdir + "/node2/walletbak",
                        tmpdir + "/node2/regtest/wallet.dat")

        logging.info("Re-starting nodes")
        self.start_three()
        sync_blocks(self.nodes)

        assert_equal(self.nodes[0].getbalance(), balance0)
        assert_equal(self.nodes[1].getbalance(), balance1)
        assert_equal(self.nodes[2].getbalance(), balance2)

        logging.info("Restoring using dumped wallet")
        self.stop_three()
        self.erase_three()

        #start node2 with no chain
        shutil.rmtree(self.options.tmpdir + "/node2/regtest/blocks")
        shutil.rmtree(self.options.tmpdir + "/node2/regtest/chainstate")

        self.start_three()

        assert_equal(self.nodes[0].getbalance(), 0)
        assert_equal(self.nodes[1].getbalance(), 0)
        assert_equal(self.nodes[2].getbalance(), 0)

        self.nodes[0].importwallet(tmpdir + "/node0/walletdump")
        self.nodes[1].importwallet(tmpdir + "/node1/walletdump")
        self.nodes[2].importwallet(tmpdir + "/node2/walletdump")

        sync_blocks(self.nodes)

        assert_equal(self.nodes[0].getbalance(), balance0)
        assert_equal(self.nodes[1].getbalance(), balance1)
        assert_equal(self.nodes[2].getbalance(), balance2)

        # reach sidechain fork
        nb = int(self.nodes[0].getblockcount())
        nb_to_gen = MINIMAL_SC_HEIGHT - nb
        if nb_to_gen > 0:
            mark_logs("Node 0 generates {} block".format(nb_to_gen),
                      self.nodes, DEBUG_MODE)
            self.nodes[0].generate(nb_to_gen)
            self.sync_all()

        safe_guard_size = EPOCH_LENGTH // 5
        if safe_guard_size < 2:
            safe_guard_size = 2

        creation_amount = Decimal("1.0")
        bwt_amount1 = Decimal("0.10")
        bwt_amount2 = Decimal("0.20")
        bwt_amount3 = Decimal("0.40")

        prev_epoch_hash = self.nodes[0].getbestblockhash()

        #generate wCertVk and constant
        mcTest = CertTestUtils(self.options.tmpdir, self.options.srcdir)
        vk = mcTest.generate_params("sc1")
        constant = generate_random_field_element_hex()

        # do a shielded transaction for testing zaddresses in backup
        mark_logs("node0 shields it coinbase", self.nodes, DEBUG_MODE)
        zaddr0 = self.nodes[0].z_getnewaddress()
        res = self.nodes[0].z_shieldcoinbase("*", zaddr0)
        wait_and_assert_operationid_status(self.nodes[0], res['opid'])
        self.sync_all()

        self.nodes[0].generate(1)
        self.sync_all()

        mark_logs("node0 z_send to node1", self.nodes, DEBUG_MODE)
        zaddr1 = self.nodes[1].z_getnewaddress()
        opid = self.nodes[0].z_sendmany(zaddr0, [{
            "address": zaddr1,
            "amount": Decimal("1.234")
        }])
        wait_and_assert_operationid_status(self.nodes[0], opid)
        self.sync_all()

        # Create a SC
        cmdInput = {
            'version': 0,
            'withdrawalEpochLength': EPOCH_LENGTH,
            'toaddress': "dada",
            'amount': creation_amount,
            'wCertVk': vk,
            'constant': constant
        }

        ret = self.nodes[0].sc_create(cmdInput)
        scid = ret['scid']
        scid_swapped = str(swap_bytes(scid))
        mark_logs("created SC id: {}".format(scid), self.nodes, DEBUG_MODE)
        self.sync_all()

        mark_logs("Node0 confirms Sc creation generating 1 block", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        sc_creating_height = self.nodes[0].getblockcount()
        self.sync_all()

        mark_logs(
            "Node0 generates {} more blocks to achieve end of withdrawal epochs"
            .format(EPOCH_LENGTH - 1), self.nodes, DEBUG_MODE)
        self.nodes[0].generate(EPOCH_LENGTH - 1)
        self.sync_all()

        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[0], EPOCH_LENGTH)

        n1_initial_balance = self.nodes[1].getbalance()

        # node0 create a cert_1 for funding node1

        # skip default address, just to use a brand new one
        self.nodes[1].getnewaddress()

        addr_node1 = self.nodes[1].getnewaddress()
        amounts = [{
            "address": addr_node1,
            "amount": bwt_amount1
        }, {
            "address": addr_node1,
            "amount": bwt_amount2
        }]
        mark_logs(
            "Node 0 sends a cert for scid {} with 2 bwd transfers of {} coins to Node1 address"
            .format(scid, bwt_amount1 + bwt_amount2,
                    addr_node1), self.nodes, DEBUG_MODE)
        try:
            #Create proof for WCert
            quality = 1
            proof = mcTest.create_test_proof("sc1", scid_swapped, epoch_number,
                                             quality, MBTR_SC_FEE, FT_SC_FEE,
                                             epoch_cum_tree_hash, constant,
                                             [addr_node1, addr_node1],
                                             [bwt_amount1, bwt_amount2])

            cert_1 = self.nodes[0].sc_send_certificate(
                scid, epoch_number, quality, epoch_cum_tree_hash, proof,
                amounts, FT_SC_FEE, MBTR_SC_FEE, CERT_FEE)
            mark_logs("==> certificate is {}".format(cert_1), self.nodes,
                      DEBUG_MODE)
            self.sync_all()
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(
                "Send certificate failed with reason {}".format(errorString),
                self.nodes, DEBUG_MODE)
            assert (False)