def run_test(self):
        '''
        Create a SC, advance two epochs and then let it cease.
        Create two transactions, each one containing a CSW with
        an input value covering the whole sidechain balance.
        Even though the first CSW transaction is still in mempool,
        the second one should be rejected.
        '''

        # prepare some coins
        self.nodes[0].generate(MINIMAL_SC_HEIGHT)
        self.sync_all()

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

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

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

        sc_cr = []
        sc_cr.append({
            "version": 0,
            "epoch_length": sc_epoch_len,
            "amount": sc_cr_amount,
            "address": sc_address,
            "wCertVk": vk,
            "wCeasedVk": cswVk,
            "constant": constant
        })

        rawtx = self.nodes[0].createrawtransaction([], {}, [], sc_cr)
        funded_tx = self.nodes[0].fundrawtransaction(rawtx)
        sigRawtx = self.nodes[0].signrawtransaction(funded_tx['hex'])
        finalRawtx = self.nodes[0].sendrawtransaction(sigRawtx['hex'])
        self.sync_all()

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

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

        # mine one block for having last cert in chain
        mark_logs("\nNode0 generates 1 block confirming last cert", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        self.sync_all()

        mark_logs("Let SC cease... ", self.nodes, DEBUG_MODE)

        nbl = int(sc_epoch_len * 1.5)
        mark_logs("Node0 generates {} blocks".format(nbl), self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(nbl)
        self.sync_all()

        # check it is really ceased
        ret = self.nodes[0].getscinfo(scid, False, False)['items'][0]
        assert_equal(ret['state'], "CEASED")

        # and has the expected balance
        sc_bal = self.nodes[0].getscinfo(scid, False,
                                         False)['items'][0]['balance']
        assert_equal(sc_bal, sc_cr_amount)

        mark_logs("\nCreate a CSW withdrawing 90% of the sc balance... ",
                  self.nodes, DEBUG_MODE)

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

        sc_csw_amount = sc_bal * Decimal("0.9")
        null1 = generate_random_field_element_hex()
        actCertData = self.nodes[0].getactivecertdatahash(scid)['certDataHash']
        print "Active Cert Data Hash: -------> ", actCertData

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

        scid_swapped = swap_bytes(scid)
        sc_proof1 = cswMcTest.create_test_proof("sc1", sc_csw_amount,
                                                str(scid_swapped), null1,
                                                csw_mc_address,
                                                ceasingCumScTxCommTree,
                                                actCertData, constant)

        sc_csws = [{
            "amount": sc_csw_amount,
            "senderAddress": csw_mc_address,
            "scId": scid,
            "epoch": 0,
            "nullifier": null1,
            "activeCertData": actCertData,
            "ceasingCumScTxCommTree": ceasingCumScTxCommTree,
            "scProof": sc_proof1
        }]

        # recipient MC address
        taddr_2 = self.nodes[2].getnewaddress()
        sc_csw_tx_outs = {taddr_2: 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")
        finalRawtx = self.nodes[0].sendrawtransaction(sigRawtx['hex'])
        mark_logs(
            "sent csw 1 {} retrieving {} coins on Node2 behalf".format(
                finalRawtx, sc_csws[0]['amount']), self.nodes, DEBUG_MODE)
        self.sync_all()

        mark_logs("Check csw is in mempool...", self.nodes, DEBUG_MODE)
        assert_true(finalRawtx in self.nodes[2].getrawmempool())

        mark_logs(
            "\nCreate a second CSW withdrawing 90% of the sc balance (should be rejected)... ",
            self.nodes, DEBUG_MODE)

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

        sc_csw_amount = sc_bal * Decimal("0.9")
        null1 = generate_random_field_element_hex()

        sc_proof1 = cswMcTest.create_test_proof("sc1", sc_csw_amount,
                                                str(scid_swapped), null1,
                                                csw_mc_address,
                                                ceasingCumScTxCommTree,
                                                actCertData, constant)

        sc_csws = [{
            "amount": sc_csw_amount,
            "senderAddress": csw_mc_address,
            "scId": scid,
            "epoch": 0,
            "nullifier": null1,
            "activeCertData": actCertData,
            "ceasingCumScTxCommTree": ceasingCumScTxCommTree,
            "scProof": sc_proof1
        }]

        # recipient MC address
        taddr_2 = self.nodes[2].getnewaddress()
        sc_csw_tx_outs = {taddr_2: 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")

        try:
            finalRawtx = self.nodes[0].sendrawtransaction(sigRawtx['hex'])
            assert (False)
        except JSONRPCException, e:
            error_string = e.error['message']
            mark_logs(
                "Failed sending csw 2 {} retrieving {} coins on Node2 behalf, error message: {}"
                .format(finalRawtx, sc_csws[0]['amount'],
                        error_string), self.nodes, DEBUG_MODE)
            assert_true("bad-sc-tx-not-applicable" in error_string)
示例#2
0
    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)
示例#3
0
    def run_test(self):
        '''
        Create a SC, advance two epochs and then let it cease.
        Test CSW txes and related in/outputs verifying that nullifiers are properly handled also
        when blocks are disconnected.
        Split the network and test CSW conflicts handling on network rejoining.
        Restare the network and check DB integrity.
        Finally create a second SC, advance 1 epoch only and verify that no CSW can be accepted (max is 2 certs)
        '''

        # prepare some coins
        self.nodes[0].generate(MINIMAL_SC_HEIGHT)
        self.sync_all()
        prev_epoch_hash = self.nodes[0].getbestblockhash()

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

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

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

        sc_cr = []
        sc_cr.append({
            "version": 0,
            "epoch_length": sc_epoch_len,
            "amount": sc_cr_amount,
            "address": sc_address,
            "wCertVk": vk,
            "wCeasedVk": cswVk,
            "constant": constant
        })

        rawtx = self.nodes[0].createrawtransaction([], {}, [], sc_cr)
        funded_tx = self.nodes[0].fundrawtransaction(rawtx)
        sigRawtx = self.nodes[0].signrawtransaction(funded_tx['hex'])
        finalRawtx = self.nodes[0].sendrawtransaction(sigRawtx['hex'])
        self.sync_all()

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

        # advance two epochs
        mark_logs("\nLet 2 epochs pass by...".format(sc_epoch_len), 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)

        # mine one block for having last cert in chain
        mark_logs("\nNode0 generates 1 block confirming last cert", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        self.sync_all()

        # check we have cert data hash for the last active certificate
        mark_logs("\nCheck we have expected cert data hashes", self.nodes,
                  DEBUG_MODE)
        try:
            assert_true(
                self.nodes[0].getactivecertdatahash(scid)['certDataHash'])
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs("{}".format(errorString), self.nodes, DEBUG_MODE)
            assert (False)
    def run_test(self):
        def get_spendable(nodeIdx, min_amount):
            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

        '''
        Create a SC, advance two epochs and then let it cease.
        Test CSW creation with the use of the cmd fundrawtransaction in different scenarios
        '''

        # prepare some coins
        self.nodes[0].generate(MINIMAL_SC_HEIGHT)
        self.sync_all()
        prev_epoch_hash = self.nodes[0].getbestblockhash()

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

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

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

        sc_cr = []
        sc_cr.append({
            "version": 0,
            "epoch_length": sc_epoch_len,
            "amount": sc_cr_amount,
            "address": sc_address,
            "wCertVk": vk,
            "wCeasedVk": cswVk,
            "constant": constant
        })

        rawtx = self.nodes[0].createrawtransaction([], {}, [], sc_cr)
        funded_tx = self.nodes[0].fundrawtransaction(rawtx)
        sigRawtx = self.nodes[0].signrawtransaction(funded_tx['hex'])
        finalRawtx = self.nodes[0].sendrawtransaction(sigRawtx['hex'])
        self.sync_all()

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

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

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

        mark_logs("Let SC cease... ", self.nodes, DEBUG_MODE)

        nbl = int(sc_epoch_len * 1.5)
        mark_logs("Node0 generates {} blocks".format(nbl), self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(nbl)
        self.sync_all()
        print

        # check it is really ceased
        ret = self.nodes[0].getscinfo(scid, False, False)['items'][0]
        assert_equal(ret['state'], "CEASED")

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

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

        actCertData = self.nodes[0].getactivecertdatahash(scid)['certDataHash']
        ceasingCumScTxCommTree = self.nodes[0].getceasingcumsccommtreehash(
            scid)['ceasingCumScTxCommTree']

        scid_swapped = swap_bytes(scid)
        sc_csw_amount = sc_bal / 8

        # recipient MC address
        taddr_2 = self.nodes[2].getnewaddress()
        sc_csw_tx_outs = {taddr_2: sc_csw_amount}

        vtxCsw = []

        # --------------------------------------------------------------------
        # 1)  One csw input covering exacltly the output
        mark_logs("One csw input covering exacltly the output...", self.nodes,
                  DEBUG_MODE)

        null1 = generate_random_field_element_hex()

        sc_proof = cswMcTest.create_test_proof("sc1", sc_csw_amount,
                                               str(scid_swapped), null1,
                                               csw_mc_address,
                                               ceasingCumScTxCommTree,
                                               actCertData, constant)

        sc_csws = [{
            "amount": sc_csw_amount,
            "senderAddress": csw_mc_address,
            "scId": scid,
            "epoch": 0,
            "nullifier": null1,
            "activeCertData": actCertData,
            "ceasingCumScTxCommTree": ceasingCumScTxCommTree,
            "scProof": sc_proof
        }]

        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")
        finalRawtx = self.nodes[0].sendrawtransaction(sigRawtx['hex'])
        mark_logs("tx = {}".format(finalRawtx), self.nodes, DEBUG_MODE)
        vtxCsw.append(finalRawtx)
        print
        self.sync_all()

        decoded_tx = self.nodes[1].getrawtransaction(finalRawtx, 1)
        #pprint.pprint(decoded_tx)

        # vin  - size(1): utxo for paying the fee
        # vout - size(2): recipient of the funds + sender change
        # vcsw_ccin - size(1): CSW funds
        assert_equal(1, len(decoded_tx['vin']))
        assert_equal(2, len(decoded_tx['vout']))
        assert_equal(1, len(decoded_tx['vcsw_ccin']))

        assert_true(finalRawtx in self.nodes[2].getrawmempool())

        # --------------------------------------------------------------------
        # 2)  One csw input covering half the output
        mark_logs("One csw input covering half the output...", self.nodes,
                  DEBUG_MODE)

        null2 = generate_random_field_element_hex()

        sc_proof = cswMcTest.create_test_proof("sc1", sc_csw_amount,
                                               str(scid_swapped), null2,
                                               csw_mc_address,
                                               ceasingCumScTxCommTree,
                                               actCertData, constant)

        sc_csws = [{
            "amount": sc_csw_amount,
            "senderAddress": csw_mc_address,
            "scId": scid,
            "epoch": 0,
            "nullifier": null2,
            "activeCertData": actCertData,
            "ceasingCumScTxCommTree": ceasingCumScTxCommTree,
            "scProof": sc_proof
        }]

        # recipient MC address
        sc_csw_tx_outs = {taddr_2: sc_csw_amount * 2}

        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")
        finalRawtx = self.nodes[0].sendrawtransaction(sigRawtx['hex'])
        mark_logs("tx = {}".format(finalRawtx), self.nodes, DEBUG_MODE)
        vtxCsw.append(finalRawtx)
        print
        self.sync_all()

        decoded_tx = self.nodes[1].getrawtransaction(finalRawtx, 1)
        #pprint.pprint(decoded_tx)
        # vin  - size(1): utxo for covering the reminder and paying the fee
        # vout - size(2): recipient of the funds + sender change
        # vcsw_ccin - size(1): CSW funds
        assert_equal(1, len(decoded_tx['vin']))
        assert_equal(2, len(decoded_tx['vout']))
        assert_equal(1, len(decoded_tx['vcsw_ccin']))

        assert_true(finalRawtx in self.nodes[2].getrawmempool())

        # ---------------------------------------------------------------------------------------------------------
        # 3)  One csw input covering half the output, an utxo as input for a small amount and one output as preset change
        mark_logs(
            "One csw input covering half the output, an utxo as input for a small amount and one output as preset change...",
            self.nodes, DEBUG_MODE)

        null3 = generate_random_field_element_hex()

        sc_proof = cswMcTest.create_test_proof("sc1", sc_csw_amount,
                                               str(scid_swapped), null3,
                                               csw_mc_address,
                                               ceasingCumScTxCommTree,
                                               actCertData, constant)

        sc_csws = [{
            "amount": sc_csw_amount,
            "senderAddress": csw_mc_address,
            "scId": scid,
            "epoch": 0,
            "nullifier": null3,
            "activeCertData": actCertData,
            "ceasingCumScTxCommTree": ceasingCumScTxCommTree,
            "scProof": sc_proof
        }]

        # recipient MC address
        taddr_2 = self.nodes[2].getnewaddress()
        sc_csw_tx_outs = {taddr_2: sc_csw_amount * 2}

        utx, change = get_spendable(0, Decimal("0.0001"))
        #pprint.pprint(utx)
        #print "Change = ", change
        raw_inputs = [{'txid': utx['txid'], 'vout': utx['vout']}]
        raw_outs = {
            self.nodes[0].getnewaddress(): change,
            taddr_2: sc_csw_amount * Decimal('1.1')
        }

        rawtx = self.nodes[0].createrawtransaction(raw_inputs, raw_outs,
                                                   sc_csws)
        funded_tx = self.nodes[0].fundrawtransaction(rawtx)
        sigRawtx = self.nodes[0].signrawtransaction(funded_tx['hex'], None,
                                                    None, "NONE")
        finalRawtx = self.nodes[0].sendrawtransaction(sigRawtx['hex'])
        mark_logs("tx = {}".format(finalRawtx), self.nodes, DEBUG_MODE)
        vtxCsw.append(finalRawtx)
        print
        self.sync_all()

        decoded_tx = self.nodes[1].getrawtransaction(finalRawtx, 1)
        #pprint.pprint(decoded_tx)
        # vin  - size(2): utxo that was set and one for covering the reminder and paying the fee
        # vout - size(3): recipient of the funds + preset change + sender change
        # vcsw_ccin - size(1): CSW funds
        assert_equal(2, len(decoded_tx['vin']))
        assert_equal(3, len(decoded_tx['vout']))
        assert_equal(1, len(decoded_tx['vcsw_ccin']))

        assert_true(finalRawtx in self.nodes[2].getrawmempool())

        # ---------------------------------------------------------------------------------------------------------
        # 4)  One csw input covering all of the output but a small amount to be used as fee. No call to fundrawtransaction
        mark_logs(
            "One csw input covering all of the output but a small amount to be used as fee. No call to fundrawtransaction...",
            self.nodes, DEBUG_MODE)

        null4 = generate_random_field_element_hex()

        sc_proof = cswMcTest.create_test_proof("sc1", sc_csw_amount,
                                               str(scid_swapped), null4,
                                               csw_mc_address,
                                               ceasingCumScTxCommTree,
                                               actCertData, constant)

        sc_csws = [{
            "amount": sc_csw_amount,
            "senderAddress": csw_mc_address,
            "scId": scid,
            "epoch": 0,
            "nullifier": null4,
            "activeCertData": actCertData,
            "ceasingCumScTxCommTree": ceasingCumScTxCommTree,
            "scProof": sc_proof
        }]

        # recipient MC address
        taddr_2 = self.nodes[2].getnewaddress()
        sc_csw_tx_outs = {taddr_2: (sc_csw_amount - Decimal("0.0001"))}

        rawtx = self.nodes[0].createrawtransaction([], sc_csw_tx_outs, sc_csws)
        sigRawtx = self.nodes[0].signrawtransaction(rawtx, None, None, "NONE")
        finalRawtx = self.nodes[0].sendrawtransaction(sigRawtx['hex'])
        mark_logs("tx = {}".format(finalRawtx), self.nodes, DEBUG_MODE)
        vtxCsw.append(finalRawtx)
        print
        self.sync_all()

        decoded_tx = self.nodes[1].getrawtransaction(finalRawtx, 1)
        #pprint.pprint(decoded_tx)
        # vin  - size(0): no utxo here
        # vout - size(1): recipient of the funds
        # vcsw_ccin - size(1): CSW funds
        assert_equal(0, len(decoded_tx['vin']))
        assert_equal(1, len(decoded_tx['vout']))
        assert_equal(1, len(decoded_tx['vcsw_ccin']))

        assert_true(finalRawtx in self.nodes[2].getrawmempool())

        # mine a block for clearing the mempool, we must not cross the limit for csw inputs to a SC
        mark_logs("\nNode0 generates 1 block", self.nodes, DEBUG_MODE)
        bl = self.nodes[0].generate(1)[-1]
        self.sync_all()

        mark_logs("Check all the txes have been included in the block...",
                  self.nodes, DEBUG_MODE)
        blockTxList = self.nodes[0].getblock(bl, True)['tx']
        for entry in vtxCsw:
            assert_true(entry in blockTxList)

        assert_true(len(self.nodes[2].getrawmempool()) == 0)
        vtxCsw = []

        # ---------------------------------------------------------------------------------------------------------
        # 5)  Two csw inputs and a sc creation, csws covering only part of the ccoutput
        mark_logs(
            "Two csw inputs and a sc creation, csws covering only part of the ccoutput...",
            self.nodes, DEBUG_MODE)

        cr_amount = Decimal("8.0")
        sc_address = "fade"
        vk2 = certMcTest.generate_params("sc2")
        constant2 = generate_random_field_element_hex()

        sc_cr = [{
            "version": 0,
            "epoch_length": EPOCH_LENGTH,
            "amount": cr_amount,
            "address": sc_address,
            "wCertVk": vk2,
            "constant": constant2
        }]

        sc_ft = []

        null5 = generate_random_field_element_hex()
        null6 = generate_random_field_element_hex()

        sc_proof_a = cswMcTest.create_test_proof("sc1", sc_csw_amount,
                                                 str(scid_swapped), null5,
                                                 csw_mc_address,
                                                 ceasingCumScTxCommTree,
                                                 actCertData, constant)

        sc_proof_b = cswMcTest.create_test_proof("sc1", sc_csw_amount,
                                                 str(scid_swapped), null6,
                                                 csw_mc_address,
                                                 ceasingCumScTxCommTree,
                                                 actCertData, constant)

        sc_csws = [{
            "amount": sc_csw_amount,
            "senderAddress": csw_mc_address,
            "scId": scid,
            "epoch": 0,
            "nullifier": null5,
            "activeCertData": actCertData,
            "ceasingCumScTxCommTree": ceasingCumScTxCommTree,
            "scProof": sc_proof_a
        }, {
            "amount": sc_csw_amount,
            "senderAddress": csw_mc_address,
            "scId": scid,
            "epoch": 0,
            "nullifier": null6,
            "activeCertData": actCertData,
            "ceasingCumScTxCommTree": ceasingCumScTxCommTree,
            "scProof": sc_proof_b
        }]

        rawtx = self.nodes[1].createrawtransaction([], {}, sc_csws, sc_cr,
                                                   sc_ft)
        funded_tx = self.nodes[0].fundrawtransaction(rawtx)
        sigRawtx = self.nodes[0].signrawtransaction(funded_tx['hex'], None,
                                                    None, "NONE")
        finalRawtx = self.nodes[0].sendrawtransaction(sigRawtx['hex'])
        mark_logs("tx = {}".format(finalRawtx), self.nodes, DEBUG_MODE)
        vtxCsw.append(finalRawtx)
        print
        self.sync_all()

        decoded_tx = self.nodes[1].getrawtransaction(finalRawtx, 1)
        #pprint.pprint(decoded_tx)
        # vin  - size(1): utxo for paying the fee
        # vout - size(1): sender change
        # vccout - size(1): creation output
        # vcsw_ccin - size(2): CSW funds
        assert_equal(1, len(decoded_tx['vin']))
        assert_equal(1, len(decoded_tx['vout']))
        assert_equal(1, len(decoded_tx['vsc_ccout']))
        assert_equal(2, len(decoded_tx['vcsw_ccin']))

        assert_true(finalRawtx in self.nodes[2].getrawmempool())

        scid2 = decoded_tx['vsc_ccout'][0]['scid']

        # ---------------------------------------------------------------------------------------------------------
        # 6)  Two csw inputs and a fw transfer to the latest created sc, csws spending more input than necessary
        mark_logs(
            "Two csw inputs and a fw transfer to the latest created sc, csws spending more input than necessary...",
            self.nodes, DEBUG_MODE)

        sc_address = "fade"

        sc_cr = []

        sc_ft_amount = Decimal('1.0')
        mc_return_address = self.nodes[0].getnewaddress()
        sc_ft = [{
            "address": sc_address,
            "amount": sc_ft_amount,
            "scid": scid2,
            "mcReturnAddress": mc_return_address
        }]

        null7 = generate_random_field_element_hex()
        null8 = generate_random_field_element_hex()

        sc_proof_a = cswMcTest.create_test_proof("sc1", sc_csw_amount,
                                                 str(scid_swapped), null7,
                                                 csw_mc_address,
                                                 ceasingCumScTxCommTree,
                                                 actCertData, constant)

        sc_proof_b = cswMcTest.create_test_proof("sc1", sc_csw_amount,
                                                 str(scid_swapped), null8,
                                                 csw_mc_address,
                                                 ceasingCumScTxCommTree,
                                                 actCertData, constant)

        sc_csws = [{
            "amount": sc_csw_amount,
            "senderAddress": csw_mc_address,
            "scId": scid,
            "epoch": 0,
            "nullifier": null7,
            "activeCertData": actCertData,
            "ceasingCumScTxCommTree": ceasingCumScTxCommTree,
            "scProof": sc_proof_a
        }, {
            "amount": sc_csw_amount,
            "senderAddress": csw_mc_address,
            "scId": scid,
            "epoch": 0,
            "nullifier": null8,
            "activeCertData": actCertData,
            "ceasingCumScTxCommTree": ceasingCumScTxCommTree,
            "scProof": sc_proof_b
        }]

        rawtx = self.nodes[0].createrawtransaction([], {}, sc_csws, sc_cr,
                                                   sc_ft)
        funded_tx = self.nodes[0].fundrawtransaction(rawtx)
        sigRawtx = self.nodes[0].signrawtransaction(funded_tx['hex'], None,
                                                    None, "NONE")
        #pprint.pprint(self.nodes[0].decoderawtransaction(sigRawtx['hex']))
        #raw_input("______________")
        finalRawtx = self.nodes[0].sendrawtransaction(sigRawtx['hex'])
        mark_logs("tx = {}".format(finalRawtx), self.nodes, DEBUG_MODE)
        vtxCsw.append(finalRawtx)
        print
        self.sync_all()

        decoded_tx = self.nodes[1].getrawtransaction(finalRawtx, 1)
        #pprint.pprint(decoded_tx)
        # vin  - size(0): no utxo needed
        # vout - size(1): recipient of sender change
        # vccout - size(1): fwt output
        # vcsw_ccin - size(2): CSW funds
        assert_equal(0, len(decoded_tx['vin']))
        assert_equal(1, len(decoded_tx['vout']))
        assert_equal(1, len(decoded_tx['vft_ccout']))
        assert_equal(2, len(decoded_tx['vcsw_ccin']))

        assert_true(finalRawtx in self.nodes[2].getrawmempool())

        mark_logs("\nNode0 generates 1 block confirming txes with csw",
                  self.nodes, DEBUG_MODE)
        bl = self.nodes[0].generate(1)[-1]
        self.sync_all()

        mark_logs("Check all the txes have been included in the block...",
                  self.nodes, DEBUG_MODE)
        blockTxList = self.nodes[0].getblock(bl, True)['tx']
        for entry in vtxCsw:
            assert_true(entry in blockTxList)

        assert_true(len(self.nodes[2].getrawmempool()) == 0)
示例#5
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)
示例#6
0
        creating_tx = ret['txid']
        mark_logs(
            "Node 0 created SC spending {} coins via tx1 {}.".format(
                sc_cr_amount, creating_tx), self.nodes, DEBUG_MODE)
        self.sync_all()
        scid2 = self.nodes[0].getrawtransaction(creating_tx,
                                                1)['vsc_ccout'][0]['scid']
        mark_logs("==> created SC ids {}".format(scid2), self.nodes,
                  DEBUG_MODE)

        # advance two epochs and cease it
        mark_logs("\nLet 2 epochs pass by...".format(sc_epoch_len), self.nodes,
                  DEBUG_MODE)

        cert, epoch_number = advance_epoch(certMcTest, self.nodes[0],
                                           self.sync_all, scid2, "sc2",
                                           constant2, 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, scid2, "sc2",
                                           constant2, sc_epoch_len)

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

        mark_logs("Let SC cease... ".format(scid2), self.nodes, DEBUG_MODE)
示例#7
0
        # not include FT and McBTR, which are free and with a low priority
        flood_mempool()
        self.sync_all()

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

        mark_logs("Node 1 generates " + str(EPOCH_LENGTH-2) + " blocks", self.nodes, DEBUG_MODE)
        self.nodes[1].generate(EPOCH_LENGTH-2)
        self.sync_all()

        ftScFee   = FT_SC_FEES[4]
        mbtrScFee = MBTR_SC_FEES[4]

        cert, epoch_number = advance_epoch(
            mcTest, self.nodes[1], self.sync_all, scid, "sc1", constant, EPOCH_LENGTH,
            quality, CERT_FEE, ftScFee, mbtrScFee, generateNumBlocks=0)

        self.sync_all()

        mark_logs("cert={}, epoch={}, ftScFee={}, mbtrScFee={}".format(cert, epoch_number, ftScFee, mbtrScFee), self.nodes, DEBUG_MODE)
        assert_true(cert in self.nodes[1].getrawmempool(True))

        ret = self.nodes[1].prioritisetransaction(cert, prio_delta, fee_delta )
        self.sync_all()

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

        scFeesList = self.nodes[0].getscinfo(scid)['items'][0]['scFees']
示例#8
0
    def run_test(self):
        print "Mining blocks..."
        self.nodes[0].generate(105)
        self.sync_all()

        chain_height = self.nodes[1].getblockcount()
        assert_equal(chain_height, 105)
        assert_equal(self.nodes[1].getbalance(), 0)
        assert_equal(self.nodes[2].getbalance(), 0)

        node0utxos = self.nodes[0].listunspent(1)
        tx1 = self.nodes[0].createrawtransaction(
            [node0utxos.pop()], {self.nodes[1].getnewaddress(): 11.4375})
        txid1 = self.nodes[0].sendrawtransaction(
            self.nodes[0].signrawtransaction(tx1)["hex"])
        tx2 = self.nodes[0].createrawtransaction(
            [node0utxos.pop()], {self.nodes[1].getnewaddress(): 11.4375})
        txid2 = self.nodes[0].sendrawtransaction(
            self.nodes[0].signrawtransaction(tx2)["hex"])
        assert_raises(JSONRPCException, self.nodes[0].gettxoutproof, [txid1])

        self.nodes[0].generate(1)
        blockhash = self.nodes[0].getblockhash(chain_height + 1)
        self.sync_all()

        txlist = []
        blocktxn = self.nodes[0].getblock(blockhash, True)["tx"]
        txlist.append(blocktxn[1])
        txlist.append(blocktxn[2])

        assert_equal(
            self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid1
                                                                        ])),
            [txid1])
        assert_equal(
            self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof(
                [txid1, txid2])), txlist)
        assert_equal(
            self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof(
                [txid1, txid2], blockhash)), txlist)

        txin_spent = self.nodes[1].listunspent(1).pop()
        tx3 = self.nodes[1].createrawtransaction(
            [txin_spent], {self.nodes[0].getnewaddress(): 11.4375})
        self.nodes[0].sendrawtransaction(
            self.nodes[1].signrawtransaction(tx3)["hex"])
        self.nodes[0].generate(1)
        self.sync_all()

        txid_spent = txin_spent["txid"]
        txid_unspent = txid1 if txin_spent["txid"] != txid1 else txid2

        # We cant find the block from a fully-spent tx
        assert_raises(JSONRPCException, self.nodes[2].gettxoutproof,
                      [txid_spent])
        # ...but we can if we specify the block
        assert_equal(
            self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof(
                [txid_spent], blockhash)), [txid_spent])
        # ...or if the first tx is not fully-spent
        assert_equal(
            self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof(
                [txid_unspent])), [txid_unspent])
        try:
            assert_equal(
                self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof(
                    [txid1, txid2])), txlist)
        except JSONRPCException:
            assert_equal(
                self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof(
                    [txid2, txid1])), txlist)
        # ...or if we have a -txindex
        assert_equal(
            self.nodes[2].verifytxoutproof(self.nodes[3].gettxoutproof(
                [txid_spent])), [txid_spent])

        # send funds to node 2, it will use them for sending a certificate
        tx0 = self.nodes[0].createrawtransaction(
            [node0utxos.pop()], {self.nodes[2].getnewaddress(): 11.4375})
        self.nodes[0].sendrawtransaction(
            self.nodes[0].signrawtransaction(tx0)["hex"])

        # reach sc fork and create a SC
        self.nodes[0].generate(MINIMAL_SC_HEIGHT - 105)
        self.sync_all()
        prev_epoch_hash = self.nodes[0].getbestblockhash()

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

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

        # generate wCertVk and constant
        certVk = certMcTest.generate_params("sc")
        cswVk = cswMcTest.generate_params("sc")
        constant1 = generate_random_field_element_hex()

        sc_cr = []
        sc_cr.append({
            "version": 0,
            "epoch_length": sc_epoch_len,
            "amount": sc_cr_amount,
            "address": sc_address,
            "wCertVk": certVk,
            "wCeasedVk": cswVk,
            "constant": constant1
        })

        rawtx = self.nodes[0].createrawtransaction([], {}, [], sc_cr)
        funded_tx = self.nodes[0].fundrawtransaction(rawtx)
        sigRawtx = self.nodes[0].signrawtransaction(funded_tx['hex'])
        finalRawtx = self.nodes[0].sendrawtransaction(sigRawtx['hex'])
        self.sync_all()

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

        # advance 1 epoch
        mark_logs("\nLet 1 epochs pass by...", self.nodes, DEBUG_MODE)
        q = 1
        cert_fee = Decimal("0.0")

        cert, epoch_number = advance_epoch(certMcTest, self.nodes[2],
                                           self.sync_all, scid, "sc",
                                           constant1, sc_epoch_len, q,
                                           cert_fee)

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

        assert_raises(JSONRPCException, self.nodes[0].gettxoutproof, [cert])

        # send some coin for having a tx in the next block as well
        t_addr1 = self.nodes[1].getnewaddress()
        tx = self.nodes[0].sendtoaddress(t_addr1, 0.1)
        self.sync_all()

        # mine one block for having last cert and tx in chain
        mark_logs("\nNode0 generates 1 block confirming last cert and tx",
                  self.nodes, DEBUG_MODE)
        bl_hash = self.nodes[0].generate(1)[-1]
        self.sync_all()

        proof1 = self.nodes[1].gettxoutproof([cert])
        proof2 = self.nodes[2].gettxoutproof([tx, cert])

        assert_equal(self.nodes[2].verifytxoutproof(proof1), [cert])
        assert_equal(self.nodes[2].verifytxoutproof(proof2), [tx, cert])

        # spend cert change: since there are no bwts in the cert, it will be fully spent
        tx = self.nodes[2].sendtoaddress(t_addr1, 0.1)
        self.sync_all()

        mark_logs("\nNode0 generates 1 block confirming last tx", self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(1)
        self.sync_all()

        # We cant find the block from a fully-spent cert
        assert_raises(JSONRPCException, self.nodes[0].gettxoutproof, [cert])
        # ...but we can if we specify the block
        proof = self.nodes[0].gettxoutproof([cert], bl_hash)
        # ...or if we have a -txindex
        proof = self.nodes[3].gettxoutproof([cert])

        assert_equal(self.nodes[0].verifytxoutproof(proof), [cert])
        try:
            ret = self.nodes[0].sc_create(cmdInput)
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs(errorString, self.nodes, DEBUG_MODE)
            assert_true(False)

        scid2 = ret['scid']
        mark_logs("scid2={}".format(scid2), self.nodes, DEBUG_MODE)
        self.sync_all()

        # 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, scid1, "sc1",
                                           constant1, EPOCH_LENGTH)

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

        cert, epoch_number = advance_epoch(
            certMcTest,
            self.nodes[0],
            self.sync_all,
            scid2,
            "sc2",
            constant2,
            EPOCH_LENGTH,
            generateNumBlocks=0)  # do not generate
    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 a certificate to keep the sidechain alive and then generates two blocks.
        The other network part generates one block, theny sends a CSW.
        When the network is joined, verify that the SC is alive and that the CSW transaction has been
        removed from 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)
        cswMcTest = CSWTestUtils(self.options.tmpdir, self.options.srcdir)

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

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

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

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

        #============================================================================================
        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 "------------------"

        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
        scid_swapped = str(swap_bytes(scid))

        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)
示例#11
0
    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_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
        }]

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

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

        # Arrange
        # Validate previous cert
        advance_epoch(cert_mc_test, self.nodes[0], self.sync_all, scid, "sc1", constant, sc_epoch_len)
        # Making SC ceased
        self.nodes[0].generate(int(sc_epoch_len * 1.25))
        self.sync_all()
        sc_csw_amount = sc_ft_amount / 5
        sc_csws, sc_csw_tx_outs = self.generate_sc_csw_and_csw_tx_out(sc_csw_amount, "csw1", scid, constant, csw_mc_test)
        raw_tx = self.nodes[0].createrawtransaction([], sc_csw_tx_outs, sc_csws, [], [])
        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']
        assert_equal(final_raw_tx is not None, True)
        print('SUCCESS - txid: {}'.format(final_raw_tx))
        self.sync_all()
示例#12
0
    def run_test(self):
        '''
        Create two SCs, advance two epochs and then let them cease.
        Test some CSW txes, verifying that active cert data is correctly handled
        Also, the SC creation constant has not been instantiated, therefore cert and csw proof verification
        is tested without using such constant as (optional) parameter.
        Restart the network and check DB integrity.
        '''

        # prepare some coins
        self.nodes[0].generate(MINIMAL_SC_HEIGHT)
        self.sync_all()
        prev_epoch_hash = self.nodes[0].getbestblockhash()

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

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

        # generate wCertVk and constant
        vk1 = certMcTest.generate_params("sc1", "cert_no_const")
        vk2 = certMcTest.generate_params("sc2")
        cswVk1 = cswMcTest.generate_params("sc1", "csw_no_const")
        cswVk2 = cswMcTest.generate_params("sc2")
        constant1 = None
        constant2 = generate_random_field_element_hex()

        sc_cr = []
        sc_cr.append({
            "version": 0,
            "epoch_length": sc_epoch_len,
            "amount": sc_cr_amount,
            "address": sc_address,
            "wCertVk": vk1,
            "wCeasedVk": cswVk1,
            "constant": constant1
        })

        sc_cr.append({
            "version": 0,
            "epoch_length": sc_epoch_len,
            "amount": sc_cr_amount,
            "address": sc_address,
            "wCertVk": vk2,
            "wCeasedVk": cswVk2,
            "constant": constant2
        })

        rawtx = self.nodes[0].createrawtransaction([], {}, [], sc_cr)
        funded_tx = self.nodes[0].fundrawtransaction(rawtx)
        sigRawtx = self.nodes[0].signrawtransaction(funded_tx['hex'])
        finalRawtx = self.nodes[0].sendrawtransaction(sigRawtx['hex'])
        self.sync_all()

        decoded_tx = self.nodes[2].getrawtransaction(finalRawtx, 1)
        scid1 = decoded_tx['vsc_ccout'][0]['scid']
        scid2 = decoded_tx['vsc_ccout'][1]['scid']
        mark_logs("created SC1 id: {}".format(scid1), self.nodes, DEBUG_MODE)
        mark_logs("created SC2 id: {}".format(scid2), self.nodes, DEBUG_MODE)
        print

        # 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, scid1, "sc1",
                                           constant1, sc_epoch_len)

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

        cert, epoch_number = advance_epoch(
            certMcTest,
            self.nodes[0],
            self.sync_all,
            scid2,
            "sc2",
            constant2,
            sc_epoch_len,
            generateNumBlocks=0)  # do not generate

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

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

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

        cert, epoch_number = advance_epoch(
            certMcTest,
            self.nodes[0],
            self.sync_all,
            scid2,
            "sc2",
            constant2,
            sc_epoch_len,
            generateNumBlocks=0)  # do not generate

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

        # mine one block for having last cert in chain
        mark_logs("\nNode0 generates 1 block confirming last certs",
                  self.nodes, DEBUG_MODE)
        self.nodes[0].generate(1)
        self.sync_all()

        mark_logs("Let both SCs cease... ".format(scid1), self.nodes,
                  DEBUG_MODE)

        nbl = int(sc_epoch_len * 1.5)
        mark_logs("Node0 generates {} blocks".format(nbl), self.nodes,
                  DEBUG_MODE)
        self.nodes[0].generate(nbl)
        self.sync_all()

        # check they are really ceased
        ret = self.nodes[0].getscinfo(scid1, False, False)['items'][0]
        assert_equal(ret['state'], "CEASED")
        ret = self.nodes[0].getscinfo(scid2, False, False)['items'][0]
        assert_equal(ret['state'], "CEASED")

        # and have the expected balance
        sc_bal1 = self.nodes[0].getscinfo(scid1, False,
                                          False)['items'][0]['balance']
        sc_bal2 = self.nodes[0].getscinfo(scid2, False,
                                          False)['items'][0]['balance']

        assert_equal(sc_bal1, sc_cr_amount)
        assert_equal(sc_bal2, sc_cr_amount)

        # create a tx with 3 CSW for sc1 and 1 CSW for sc2
        mark_logs(
            "\nCreate 3 CSWs in a tx withdrawing half the sc balance... ",
            self.nodes, DEBUG_MODE)

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

        sc_csw_amount = (sc_bal1 / 2) / 3
        null_1_1 = generate_random_field_element_hex()
        null_1_2 = generate_random_field_element_hex()
        null_1_3 = generate_random_field_element_hex()
        null_2_1 = generate_random_field_element_hex()

        actCertData1 = self.nodes[0].getactivecertdatahash(
            scid1)['certDataHash']
        actCertData2 = self.nodes[0].getactivecertdatahash(
            scid2)['certDataHash']

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

        scid1_swapped = swap_bytes(scid1)
        sc_proof1_1 = cswMcTest.create_test_proof("sc1", sc_csw_amount,
                                                  str(scid1_swapped), null_1_1,
                                                  csw_mc_address,
                                                  ceasingCumScTxCommTree1,
                                                  actCertData1, constant1)

        sc_proof1_2 = cswMcTest.create_test_proof("sc1", sc_csw_amount,
                                                  str(scid1_swapped), null_1_2,
                                                  csw_mc_address,
                                                  ceasingCumScTxCommTree1,
                                                  actCertData1, constant1)

        sc_proof1_3 = cswMcTest.create_test_proof("sc1", sc_csw_amount,
                                                  str(scid1_swapped), null_1_3,
                                                  csw_mc_address,
                                                  ceasingCumScTxCommTree1,
                                                  actCertData1, constant1)

        scid2_swapped = swap_bytes(scid2)
        sc_proof2 = cswMcTest.create_test_proof("sc2", sc_csw_amount,
                                                str(scid2_swapped), null_2_1,
                                                csw_mc_address,
                                                ceasingCumScTxCommTree2,
                                                actCertData2, constant2)
        #print "sc_proof1 =", sc_proof1
        #print "sc_proof2 =", sc_proof2

        sc_csws = [{
            "amount": sc_csw_amount,
            "senderAddress": csw_mc_address,
            "scId": scid1,
            "epoch": 0,
            "nullifier": null_1_1,
            "activeCertData": actCertData1,
            "ceasingCumScTxCommTree": ceasingCumScTxCommTree1,
            "scProof": sc_proof1_1
        }, {
            "amount": sc_csw_amount,
            "senderAddress": csw_mc_address,
            "scId": scid1,
            "epoch": 0,
            "nullifier": null_1_2,
            "activeCertData": actCertData1,
            "ceasingCumScTxCommTree": ceasingCumScTxCommTree1,
            "scProof": sc_proof1_2
        }, {
            "amount": sc_csw_amount,
            "senderAddress": csw_mc_address,
            "scId": scid1,
            "epoch": 0,
            "nullifier": null_1_3,
            "activeCertData": actCertData1,
            "ceasingCumScTxCommTree": ceasingCumScTxCommTree1,
            "scProof": sc_proof1_3
        }, {
            "amount": sc_csw_amount,
            "senderAddress": csw_mc_address,
            "scId": scid2,
            "epoch": 0,
            "nullifier": null_2_1,
            "activeCertData": actCertData2,
            "ceasingCumScTxCommTree": ceasingCumScTxCommTree2,
            "scProof": sc_proof2
        }]

        # recipient MC address
        taddr_2 = self.nodes[2].getnewaddress()
        sc_csw_tx_outs = {taddr_2: Decimal(sc_csw_amount * 4)}

        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")
        finalRawtx = self.nodes[0].sendrawtransaction(sigRawtx['hex'])
        mark_logs("sent csw tx {}".format(finalRawtx), self.nodes, DEBUG_MODE)
        self.sync_all()

        decoded_tx = self.nodes[1].getrawtransaction(finalRawtx, 1)

        # vin  - size(1): utxo for paying the fee
        # vout - size(2): recipient of the funds (the same recipient for all the 4 csws) + sender change
        # vcsw_ccin - size(4): CSW funds
        assert_equal(1, len(decoded_tx['vin']))
        assert_equal(2, len(decoded_tx['vout']))
        assert_equal(4, len(decoded_tx['vcsw_ccin']))

        mark_logs("Check tx is in mempool...", self.nodes, DEBUG_MODE)
        assert_true(finalRawtx in self.nodes[2].getrawmempool())

        mark_logs("\nNode0 generates 1 block confirming CSW", self.nodes,
                  DEBUG_MODE)
        bl = self.nodes[0].generate(1)[-1]
        self.sync_all()

        mark_logs("Check tx is in block just mined...", self.nodes, DEBUG_MODE)
        assert_true(finalRawtx in self.nodes[0].getblock(bl, True)['tx'])

        mark_logs("Check nullifiers for both sc ids are in MC...", self.nodes,
                  DEBUG_MODE)
        assert_true(
            self.nodes[0].checkcswnullifier(scid1, null_1_1)['data'] == 'true')
        assert_true(
            self.nodes[0].checkcswnullifier(scid1, null_1_2)['data'] == 'true')
        assert_true(
            self.nodes[0].checkcswnullifier(scid1, null_1_3)['data'] == 'true')
        assert_true(
            self.nodes[0].checkcswnullifier(scid2, null_2_1)['data'] == 'true')

        mark_logs("now create a tx with a csw having a wrong act cert data...",
                  self.nodes, DEBUG_MODE)

        null_1_4 = generate_random_field_element_hex()
        wrong_act_cert_data = generate_random_field_element_hex()
        sc_proof1_4 = cswMcTest.create_test_proof("sc1", sc_csw_amount,
                                                  str(scid1_swapped), null_1_4,
                                                  csw_mc_address,
                                                  ceasingCumScTxCommTree1,
                                                  wrong_act_cert_data,
                                                  constant1)

        sc_csws = [{
            "amount": sc_csw_amount,
            "senderAddress": csw_mc_address,
            "scId": scid1,
            "epoch": 0,
            "nullifier": null_1_4,
            "activeCertData": wrong_act_cert_data,
            "ceasingCumScTxCommTree": ceasingCumScTxCommTree1,
            "scProof": sc_proof1_4
        }]

        # recipient MC address
        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")
        try:
            self.nodes[0].sendrawtransaction(sigRawtx['hex'])
            assert (False)
        except JSONRPCException, e:
            errorString = e.error['message']
            mark_logs("Send csw failed with reason {}".format(errorString),
                      self.nodes, DEBUG_MODE)
    def run_test(self):
        '''
        Verify that the async proof verifier for sidechain proofs works as expected.
        '''

        # Prepare some coins
        self.nodes[0].generate(MINIMAL_SC_HEIGHT / 2 + 1)
        self.sync_all()

        # Generate some coins on node 2
        self.nodes[2].generate(MINIMAL_SC_HEIGHT / 2 + 1)
        self.sync_all()

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

        cert_mc_test = CertTestUtils(self.options.tmpdir, self.options.srcdir)
        csw_mc_test = CSWTestUtils(self.options.tmpdir, self.options.srcdir)

        # generate wCertVk and constant
        vk = cert_mc_test.generate_params("sc")
        csw_vk = csw_mc_test.generate_params("sc")
        constant = generate_random_field_element_hex()

        sc_cr = []
        sc_cr.append({
            "version": 0,
            "epoch_length": sc_epoch_len,
            "amount": sc_cr_amount,
            "address": sc_address,
            "wCertVk": vk,
            "wCeasedVk": csw_vk,
            "constant": constant
        })

        rawtx = self.nodes[0].createrawtransaction([], {}, [], sc_cr)
        funded_tx = self.nodes[0].fundrawtransaction(rawtx)
        sig_raw_tx = self.nodes[0].signrawtransaction(funded_tx['hex'])
        final_raw_tx = self.nodes[0].sendrawtransaction(sig_raw_tx['hex'])
        self.sync_all()

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

        # Advance one epoch
        mark_logs("\nLet 1 epoch pass by...", self.nodes, DEBUG_MODE)

        cert1, epoch_number = advance_epoch(cert_mc_test, self.nodes[0],
                                            self.sync_all, scid, "sc",
                                            constant, sc_epoch_len)

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

        # Check that the certificate is in the mempool
        mark_logs("Check certificate is in mempool...", self.nodes, DEBUG_MODE)
        assert_true(cert1 in self.nodes[0].getrawmempool())
        assert_true(cert1 in self.nodes[1].getrawmempool())

        # Generate blocks to reach the next epoch
        mark_logs("\nLet another epoch pass by...", self.nodes, DEBUG_MODE)
        self.nodes[0].generate(sc_epoch_len)
        self.sync_all()

        # Check that the certificate is not in the mempool anymore
        mark_logs("Check certificate is not in mempool anymore...", self.nodes,
                  DEBUG_MODE)
        assert_false(cert1 in self.nodes[0].getrawmempool())
        assert_false(cert1 in self.nodes[1].getrawmempool())

        epoch_number, epoch_cum_tree_hash = get_epoch_data(
            scid, self.nodes[0], sc_epoch_len)
        cert_quality = 1
        cert_fee = Decimal("0.00001")
        ft_fee = 0
        mbtr_fee = 0

        # Manually create a certificate with invalid proof to test the ban mechanism
        # mark_logs("\nTest the node ban mechanism by sending a certificate with invalid proof", self.nodes, DEBUG_MODE)

        # Create an invalid proof by providing the wrong epoch_number
        proof = cert_mc_test.create_test_proof("sc", scid_swapped,
                                               epoch_number + 1, cert_quality,
                                               mbtr_fee, ft_fee,
                                               epoch_cum_tree_hash, constant,
                                               [], [])

        try:
            # The send_certificate call must be ok since the proof verification is disabled on node 2
            invalid_cert = self.nodes[2].sc_send_certificate(
                scid, epoch_number, cert_quality, epoch_cum_tree_hash, proof,
                [], ft_fee, mbtr_fee, cert_fee)
        except JSONRPCException, e:
            error_string = e.error['message']
            print "Send certificate failed with reason {}".format(error_string)
            assert (False)