def createGenesisCoinbase(signblockpubkey):
    genesis_coinbase = CTransaction()
    coinbaseinput = CTxIn(outpoint=COutPoint(0, 0), nSequence=0xffffffff)
    coinbaseinput.scriptSig=CScript([hex_str_to_bytes(signblockpubkey)])
    genesis_coinbase.vin.append(coinbaseinput)
    coinbaseoutput = CTxOut()
    coinbaseoutput.nValue = 50 * COIN
    coinbaseoutput.scriptPubKey = CScript([OP_DUP, OP_HASH160, hex_str_to_bytes(signblockpubkey),OP_EQUALVERIFY, OP_CHECKSIG])
    genesis_coinbase.vout.append(coinbaseoutput)
    genesis_coinbase.calc_sha256()
    return genesis_coinbase
Пример #2
0
    def run_test(self):
        # Add p2p connection to node0
        node0 = self.nodes[0]  # convenience reference to the node
        node0.add_p2p_connection(P2PDataStore())

        n0_addr = node0.getnewaddress()
        n0_pubk = hex_str_to_bytes(node0.getaddressinfo(n0_addr)["pubkey"])
        
        node1 = self.nodes[1]
        n1_addr = node1.getnewaddress()

        # Generate the first block and let node0 get 50 BTC from the coinbase transaction as the initial funding
        best_block = node0.getblock(node0.getbestblockhash())
        tip = int(node0.getbestblockhash(), 16)
        height = best_block["height"] + 1
        block_time = best_block["time"] + 1
        self.log.info("Create a new block using the coinbase of the node0.")

        block1 = create_block(tip, create_coinbase(height, n0_pubk), block_time)
        block1.solve()
        node0.p2p.send_blocks_and_test([block1], node0, success=True, timeout=60)
        self.log.info("Mature the block, make the mined BTC usable.")
        node0.generatetoaddress(100, node0.get_deterministic_priv_key().address) # generate 100 more blocks.
        assert(node0.getbalance() == 50)   # node0 get the reward as a miner

        # craft a new transaction, which double spend the coinbase tx of node0 in block1
        tx2_raw = node0.createrawtransaction(
            inputs = [{"txid": block1.vtx[0].hash, "vout": 0}, {"txid": block1.vtx[0].hash, "vout": 0}],
            outputs = {n1_addr: 100}
        )

        tx2_sig = node0.signrawtransactionwithwallet(tx2_raw)
        assert_equal(tx2_sig["complete"], True)
        tx2_hex = tx2_sig["hex"]
        tct2 = CTransaction()
        tct2.deserialize(BytesIO(hex_str_to_bytes(tx2_hex)))

        best_block = node0.getblock(node0.getbestblockhash())
        tip = int(node0.getbestblockhash(), 16)
        height = best_block["height"] + 1
        block_time = best_block["time"] + 1
        block2 = create_block(tip, create_coinbase(height), block_time)
        block2.vtx.extend([tct2])
        block2.hashMerkleRoot = block2.calc_merkle_root()
        block2.solve()
        node0.p2p.send_blocks_and_test([block2], node0, success=True, timeout=60)

        # check the balances
        assert(node0.getbalance() == 0)
        assert(node1.getbalance() == 100)
        self.log.info("Successfully double spend the 50 BTCs.")
Пример #3
0
    def mine_msg_txn_incorrectly(self, tip_height, tip_hash):
        nonce = 0
        op_return_data = self.create_op_return_data(tip_height, tip_hash,
                                                    nonce)

        tx = CTransaction()
        tx.vin.append(CTxIn(COutPoint(0, 0xfffffffe), b"", 0xffffffff))
        tx.vout.append(CTxOut(0, CScript([OP_RETURN, op_return_data])))
        tx.nLockTime = self.tx_time
        tx.mine()
        tx.rehash()

        self.tx_time += 1
        lower_bound = get_target(tx)
        upper_bound = uint256_from_str(
            hex_str_to_bytes(
                "00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
            )[::-1])

        while tx.sha256s ^ 0x8000000000000000000000000000000000000000000000000000000000000000 <= lower_bound or \
            tx.sha256s ^ 0x8000000000000000000000000000000000000000000000000000000000000000 > upper_bound:
            nonce += 1
            op_return_data[-4:] = struct.pack("<I", nonce)
            tx.vout[0] = CTxOut(0, CScript([OP_RETURN, op_return_data]))
            tx.mine()

        tx.rehash()
        return tx
def createIncorectGenesisBlock(genesis_coinbase, signblockprivkey, signblockpubkey):
    genesis = CBlock()
    genesis.nTime = int(time.time() + 600)
    genesis.hashPrevBlock = 0
    genesis.vtx.append(genesis_coinbase)
    genesis.hashMerkleRoot = genesis.calc_merkle_root()
    genesis.hashImMerkleRoot = genesis.calc_immutable_merkle_root()
    genesis.xfieldType = 1
    genesis.xfield = hex_str_to_bytes(signblockpubkey)
    genesis.solve(signblockprivkey)
    return genesis
Пример #5
0
def get_target(txn):
    block_subsidy = 5000000000
    txn_cost = get_txn_cost(txn)

    ratio = block_subsidy // txn_cost
    block_target = uint256_from_str(
        hex_str_to_bytes(
            "0000000000ffff00000000000000000000000000000000000000000000000000")
        [::-1])

    target = block_target * ratio * TARGET_MULTIPLIER
    return target
    def run_test(self):
        self.stop_node(0)
        shutil.rmtree(self.nodes[0].datadir)

        initialize_datadir(self.options.tmpdir, 0)

        self.log.info("Test with no genesis file")
        self.nodes[0].assert_start_raises_init_error([], 'ReadGenesisBlock: unable to read genesis file', match=ErrorMatch.PARTIAL_REGEX)

        self.log.info("Phase 1: Tests using genesis block")
        self.log.info("Test correct genesis file")
        self.writeGenesisBlockToFile(self.nodes[0].datadir)
        self.start_node(0)
        self.stop_node(0)

        self.log.info("Restart with correct genesis file")
        self.start_node(0)
        self.stop_node(0)

        self.log.info("Test incorrect genesis block - No Coinbase")
        genesis_coinbase = createGenesisCoinbase(self.signblockpubkey)
        genesis_coinbase.vin[0].prevout.hash = 111111
        genesis = createIncorectGenesisBlock(genesis_coinbase, self.signblockprivkey, self.signblockpubkey)

        writeIncorrectGenesisBlockToFile(self.nodes[0].datadir, genesis)
        self.nodes[0].assert_start_raises_init_error([], 'ReadGenesisBlock: invalid genesis block', match=ErrorMatch.PARTIAL_REGEX)

        self.log.info("Test incorrect genesis block - Incorrect height")
        genesis_coinbase_height = createGenesisCoinbase(self.signblockpubkey)
        genesis_coinbase_height.vin[0].prevout.n = 10
        genesis = createIncorectGenesisBlock(genesis_coinbase_height, self.signblockprivkey, self.signblockpubkey)

        writeIncorrectGenesisBlockToFile(self.nodes[0].datadir, genesis)
        self.nodes[0].assert_start_raises_init_error([], 'ReadGenesisBlock: invalid height in genesis block', match=ErrorMatch.PARTIAL_REGEX)

        self.log.info("Test incorrect genesis block - Multiple transactions")
        genesis_coinbase = createGenesisCoinbase(self.signblockpubkey)
        genesis = createIncorectGenesisBlock(genesis_coinbase, self.signblockprivkey, self.signblockpubkey)
        genesis.vtx.append(CTransaction())
        genesis.hashMerkleRoot = genesis.calc_merkle_root()
        genesis.hashImMerkleRoot = genesis.calc_immutable_merkle_root()
        genesis.solve(self.signblockprivkey)

        writeIncorrectGenesisBlockToFile(self.nodes[0].datadir, genesis)
        self.nodes[0].assert_start_raises_init_error([], 'ReadGenesisBlock: invalid genesis block', match=ErrorMatch.PARTIAL_REGEX)

        self.log.info("Test incorrect genesis block - No proof")
        genesis = createIncorectGenesisBlock(genesis_coinbase, self.signblockprivkey, self.signblockpubkey)
        genesis.proof.clear()

        writeIncorrectGenesisBlockToFile(self.nodes[0].datadir, genesis)
        self.nodes[0].assert_start_raises_init_error([], 'ReadGenesisBlock: invalid genesis block', match=ErrorMatch.PARTIAL_REGEX)

        self.log.info("Test incorrect genesis block - Insufficient Proof")
        genesis = createIncorectGenesisBlock(genesis_coinbase, self.signblockprivkey, self.signblockpubkey)
        genesis.proof = genesis.proof[:-1]

        writeIncorrectGenesisBlockToFile(self.nodes[0].datadir, genesis)
        self.nodes[0].assert_start_raises_init_error([], 'ReadGenesisBlock: invalid genesis block', match=ErrorMatch.PARTIAL_REGEX)

        self.log.info("Test incorrect genesis block - Incorrect xfieldType")
        genesis_coinbase = createGenesisCoinbase(self.signblockpubkey)
        genesis = CBlock()
        genesis.nTime = int(time.time() + 600)
        genesis.hashPrevBlock = 0
        genesis.vtx.append(genesis_coinbase)
        genesis.hashMerkleRoot = genesis.calc_merkle_root()
        genesis.hashImMerkleRoot = genesis.calc_immutable_merkle_root()
        genesis.xfieldType = 0
        genesis.xfield = hex_str_to_bytes(self.signblockpubkey)
        genesis.solve(self.signblockprivkey)

        writeIncorrectGenesisBlockToFile(self.nodes[0].datadir, genesis)
        self.nodes[0].assert_start_raises_init_error([], 'ReadGenesisBlock: invalid xfieldType in genesis block', match=ErrorMatch.PARTIAL_REGEX)

        self.log.info("Test incorrect genesis block - Incorrect xfield")
        genesis_coinbase = createGenesisCoinbase(self.signblockpubkey)
        genesis = CBlock()
        genesis.nTime = int(time.time() + 600)
        genesis.hashPrevBlock = 0
        genesis.vtx.append(genesis_coinbase)
        genesis.hashMerkleRoot = genesis.calc_merkle_root()
        genesis.hashImMerkleRoot = genesis.calc_immutable_merkle_root()
        genesis.xfieldType = 1
        genesis.xfield = hex_str_to_bytes(self.signblockpubkey[:32])
        genesis.solve(self.signblockprivkey)

        writeIncorrectGenesisBlockToFile(self.nodes[0].datadir, genesis)
        self.nodes[0].assert_start_raises_init_error([], 'Aggregate Public Key for Signed Block is invalid', match=ErrorMatch.PARTIAL_REGEX)

        self.log.info("Test incorrect genesis block - No hashMerkleRoot")
        genesis_coinbase = createGenesisCoinbase(self.signblockpubkey)
        genesis = CBlock()
        genesis.nTime = int(time.time() + 600)
        genesis.hashPrevBlock = 0
        genesis.vtx.append(genesis_coinbase)
        genesis.xfieldType = 1
        genesis.xfield = hex_str_to_bytes(self.signblockpubkey)
        # not populating hashMerkleRoot and hashImMerkleRoot
        genesis.solve(self.signblockprivkey)

        writeIncorrectGenesisBlockToFile(self.nodes[0].datadir, genesis)
        self.nodes[0].assert_start_raises_init_error([], 'ReadGenesisBlock: invalid MerkleRoot in genesis block', match=ErrorMatch.PARTIAL_REGEX)

        self.log.info("Test incorrect genesis block - No hashImMerkleRoot")
        genesis_coinbase = createGenesisCoinbase(self.signblockpubkey)
        genesis = CBlock()
        genesis.nTime = int(time.time() + 600)
        genesis.hashPrevBlock = 0
        genesis.vtx.append(genesis_coinbase)
        genesis.hashMerkleRoot = genesis.calc_merkle_root()
        genesis.xfieldType = 1
        genesis.xfield = hex_str_to_bytes(self.signblockpubkey)
        # not populating hashImMerkleRoot
        genesis.solve(self.signblockprivkey)

        writeIncorrectGenesisBlockToFile(self.nodes[0].datadir, genesis)
        self.nodes[0].assert_start_raises_init_error([], 'ReadGenesisBlock: invalid MerkleRoot in genesis block', match=ErrorMatch.PARTIAL_REGEX)

        self.log.info("Phase 2: Tests using genesis.dat file")
        self.log.info("Test new genesis file")
        self.genesisBlock = None
        self.writeGenesisBlockToFile(self.nodes[0].datadir, nTime=int(time.time()))
        #different genesis file
        self.nodes[0].assert_start_raises_init_error([], 'Error: Incorrect or no genesis block found.', match=ErrorMatch.PARTIAL_REGEX)

        datadir = self.nodes[0].datadir
        genesisFile = os.path.join(datadir, "genesis.dat")

        self.log.info("Test incorrect genesis file - append 2 bytes")
        self.writeGenesisBlockToFile(self.nodes[0].datadir)
        with open(genesisFile, 'a', encoding='utf8') as f:
            f.write("abcd")
        self.nodes[0].assert_start_raises_init_error([], 'ReadGenesisBlock: invalid genesis file', match=ErrorMatch.PARTIAL_REGEX)
        os.remove(genesisFile)

        self.log.info("Test incorrect genesis file - append many bytes")
        self.writeGenesisBlockToFile(self.nodes[0].datadir)
        with open(genesisFile, 'a', encoding='utf8') as f:
            s = "".join([str(i) for i in range(0,16) for j in range(0, 100)])
            f.write(s)
        self.nodes[0].assert_start_raises_init_error([], 'ReadGenesisBlock: invalid genesis file', match=ErrorMatch.PARTIAL_REGEX)
        os.remove(genesisFile)

        self.log.info("Test incorrect genesis file - replace 2 bytes")
        self.writeGenesisBlockToFile(self.nodes[0].datadir)
        with open(genesisFile, 'r+', encoding='utf8') as f:
            content = f.readline()
            clen = len(content)
            content = content[:500] + "0000" + content[504:]
            assert(len(content) == clen)
            f.write(content)
        self.nodes[0].assert_start_raises_init_error([], 'ReadGenesisBlock: invalid genesis file', match=ErrorMatch.PARTIAL_REGEX)
        os.remove(genesisFile)

        self.log.info("Test incorrect genesis file - insert 2 bytes")
        content = ""
        self.writeGenesisBlockToFile(self.nodes[0].datadir)
        with open(genesisFile, 'r+', encoding='utf8') as f:
            content = f.readline()
            clen = len(content)
            content = content[:550] + "1111" + content[550:]
            assert(len(content) == clen + 4)
            f.write(content)
        self.nodes[0].assert_start_raises_init_error([], 'ReadGenesisBlock: invalid genesis file', match=ErrorMatch.PARTIAL_REGEX)
        os.remove(genesisFile)

        self.log.info("Test incorrect genesis file - remove 2 bytes")
        content = ""
        self.writeGenesisBlockToFile(self.nodes[0].datadir)
        with open(genesisFile, 'r+', encoding='utf8') as f:
            content = f.readline()
            clen = len(content)
            content = content[:100] + content[104:]
            assert(len(content) == clen - 4)
            f.write(content)
        self.nodes[0].assert_start_raises_init_error([], 'ReadGenesisBlock: invalid genesis file', match=ErrorMatch.PARTIAL_REGEX)
        os.remove(genesisFile)

        self.log.info("Test incorrect genesis file - truncate file")
        self.writeGenesisBlockToFile(self.nodes[0].datadir)
        with open(genesisFile, 'r+', encoding='utf8') as f:
            f.truncate(500)
        self.nodes[0].assert_start_raises_init_error([], 'CDataStream::read().*end of data', match=ErrorMatch.PARTIAL_REGEX)

        self.log.info("Phase 3: Edit genesis file after sarting the blockchain")
        self.stop_node(0)
        shutil.rmtree(self.nodes[0].datadir)
        initialize_datadir(self.options.tmpdir, 0)

        self.log.info("Starting node")
        self.writeGenesisBlockToFile(self.nodes[0].datadir)
        self.start_node(0)
        self.nodes[0].add_p2p_connection(P2PInterface())

        self.log.info("Generating 10 blocks")
        blocks = self.nodes[0].generate(10, self.signblockprivkey_wif)
        self.sync_all([self.nodes[0:1]])
        assert_equal(self.nodes[0].getbestblockhash(), blocks[-1])
        self.stop_node(0)
        shutil.copytree(self.nodes[0].datadir, os.path.join(self.options.tmpdir, "backup")) 

        self.log.info("Creating corrupt genesis file")
        with open(genesisFile, 'r+', encoding='utf8') as f:
            content = f.readline()
            clen = len(content)
            content = content[:500] + "0000" + content[504:]
            assert(len(content) == clen)
            f.write(content)
        self.nodes[0].assert_start_raises_init_error([])

        self.log.info("Starting node again")
        self.genesisBlock = None
        self.writeGenesisBlockToFile(self.nodes[0].datadir)
        self.nodes[0].assert_start_raises_init_error([], 'Error: Incorrect or no genesis block found.', match=ErrorMatch.PARTIAL_REGEX)

        self.log.info("Recovering original blockchain")
        shutil.rmtree(self.nodes[0].datadir)
        shutil.copytree(os.path.join(self.options.tmpdir, "backup"), self.nodes[0].datadir)
        self.start_node(0)
        self.nodes[0].add_p2p_connection(P2PInterface())
        self.sync_all([self.nodes[0:1]])

        assert_equal(self.nodes[0].getbestblockhash(), blocks[-1])
        self.log.info("Blockchain intact!")
Пример #7
0
 def set_test_params(self):
     self.setup_clean_chain = True
     self.num_nodes = 1
     self.extra_args = [["-whitelist=127.0.0.1"]]
     self.signKey = Schnorr()
     self.signKey.set_secretbytes(hex_str_to_bytes(self.signblockprivkey))