Ejemplo n.º 1
0
def test_add_side_chain(db, alt_db):
    """"
    Local: L0, L1, L2
    add
    Remote: R0, R1
    """
    k, v, k2, v2 = accounts()
    # Remote: mine one block
    chainR = Chain({v: {"balance": utils.denoms.ether * 1}}, difficulty=1)
    tx0 = get_transaction(nonce=0)
    R1 = mine_next_block(chainR, transactions=[tx0])
    assert tx0.hash in [x.hash for x in R1.transactions]

    # Local: mine two blocks
    chainL = Chain({v: {"balance": utils.denoms.ether * 1}}, difficulty=1)
    tx0 = get_transaction(nonce=0)
    L1 = mine_next_block(chainL, transactions=[tx0])
    tx1 = get_transaction(nonce=1)
    L2 = mine_next_block(chainL, transactions=[tx1])

    # receive serialized remote blocks, newest first
    rlp_blocks = [rlp.encode(R1)]
    for rlp_block in rlp_blocks:
        block = rlp.decode(rlp_block, Block)
        chainL.add_block(block)

    assert L2.hash in chainL
    assert chainL.head == L2
Ejemplo n.º 2
0
def test_add_longer_side_chain(db, alt_db):
    """"
    Local: L0, L1, L2
    Remote: R0, R1, R2, R3
    """
    k, v, k2, v2 = accounts()
    # Remote: mine three blocks
    chainR = Chain({v: {"balance": utils.denoms.ether * 1}}, difficulty=1)
    remote_blocks = []
    for i in range(3):
        tx = get_transaction(nonce=i)
        blk = mine_next_block(chainR, transactions=[tx])
        remote_blocks.append(blk)
    # Local: mine two blocks
    chainL = Chain({v: {"balance": utils.denoms.ether * 1}}, difficulty=1)
    tx0 = get_transaction(nonce=0)
    L1 = mine_next_block(chainL, transactions=[tx0])
    tx1 = get_transaction(nonce=1)
    L2 = mine_next_block(chainL, transactions=[tx1])

    # receive serialized remote blocks, newest first
    rlp_blocks = [rlp.encode(x) for x in remote_blocks]
    for rlp_block in rlp_blocks:
        block = rlp.decode(rlp_block, Block)
        chainL.add_block(block)

    assert chainL.head == remote_blocks[-1]
Ejemplo n.º 3
0
def test_process_time_queue():
    """
    Test Chain.process_time_queue
    """
    # Arrange testing data blk0
    k, v, k2, v2 = accounts()
    chain = Chain({}, difficulty=1)
    blk0 = mine_on_chain(chain, coinbase=decode_hex('0' * 40))
    hash0 = chain.head.hash
    blk1 = mine_on_chain(chain, coinbase=decode_hex('0' * 40))
    hash1 = chain.head.hash

    # Act on chain2
    chain2 = Chain({}, difficulty=1)
    chain2.time_queue.insert(0, blk0)
    assert len(chain2.time_queue) == 1

    # Not reach time threshold, process_time_queue doesn't call add_block
    chain2.process_time_queue(new_time=0)
    assert len(chain2.time_queue) == 1
    assert chain2.head.hash != chain.head.hash

    # Reach time threshold, process_time_queue calls add_block
    chain2.process_time_queue(new_time=time.time() + 10)
    assert len(chain2.time_queue) == 0
    assert chain2.head.hash == hash0

    # If new_time is None, use time.time()
    chain2.time_queue.insert(1, blk1)
    chain2.process_time_queue()
    assert len(chain2.time_queue) == 0
    assert chain2.head.hash == hash1
Ejemplo n.º 4
0
def test_reward_uncles(db):
    """
    B0 B1 B2
    B0 Uncle

    We raise the block's coinbase account by Rb, the block reward,
    and also add uncle and nephew rewards
    """
    k, v, k2, v2 = accounts()
    chain = Chain({}, difficulty=1)
    blk0 = mine_on_chain(chain, coinbase=decode_hex('0' * 40))
    local_coinbase = decode_hex('1' * 40)
    uncle_coinbase = decode_hex('2' * 40)
    # Mine the uncle
    uncle = mine_on_chain(chain, blk0, coinbase=uncle_coinbase)
    assert chain.state.get_balance(
        uncle_coinbase) == 1 * chain.env.config['BLOCK_REWARD']
    # Mine the first block in the "intended main chain"
    blk1 = mine_on_chain(chain, blk0, coinbase=local_coinbase)
    # next block should reward uncles
    blk2 = mine_on_chain(chain, blk1, coinbase=local_coinbase)
    # print [x.hash for x in chain.get_chain()], [blk0.hash, uncle.hash,
    # blk1.hash, blk2.hash]
    assert blk1.hash in chain
    assert uncle.header.hash in [u.hash for u in blk2.uncles]
    assert chain.head == blk2
    assert chain.get_chain() == [blk0, blk1, blk2]
    assert chain.state.get_balance(local_coinbase) == \
        2 * chain.env.config['BLOCK_REWARD'] + \
        chain.env.config['NEPHEW_REWARD']
    assert chain.state.get_balance(
        uncle_coinbase) == chain.env.config['BLOCK_REWARD'] * 7 // 8
Ejemplo n.º 5
0
def test_block_serialization_with_transaction_empty_genesis(db):
    k, v, k2, v2 = accounts()
    chain = Chain({}, difficulty=1)
    tx = get_transaction(gasprice=10)  # must fail, as there is no balance
    a_blk2 = mine_next_block(chain, transactions=[tx])
    assert tx.hash not in [x.hash for x in a_blk2.transactions]
    assert len(a_blk2.transactions) == 0
Ejemplo n.º 6
0
def test_mining(db):
    chain = Chain({}, difficulty=1)
    assert chain.state.block_number == 0
    assert chain.state.block_difficulty == 1
    for i in range(2):
        blk = mine_next_block(chain)
        assert blk.number == i + 1
Ejemplo n.º 7
0
def test_invalid_transaction(db):
    k, v, k2, v2 = accounts()
    chain = Chain({v2: {"balance": utils.denoms.ether * 1}}, difficulty=1)
    tx = get_transaction()
    blk = mine_next_block(chain, transactions=[tx])
    assert chain.state.get_balance(v) == 0
    assert chain.state.get_balance(v2) == utils.denoms.ether * 1
    assert tx not in blk.transactions
Ejemplo n.º 8
0
def test_mine_block_with_transaction3(db):
    k, v, k2, v2 = accounts()
    chain = Chain({v: {"balance": utils.denoms.ether * 1}}, difficulty=1)
    tx = get_transaction()
    blk = mine_next_block(chain, transactions=[tx])
    assert tx in blk.transactions
    assert chain.state.get_balance(v) == utils.denoms.finney * 990
    assert chain.state.get_balance(v2) == utils.denoms.finney * 10
Ejemplo n.º 9
0
def test_transaction(db):
    k, v, k2, v2 = accounts()
    chain = Chain({v: {"balance": utils.denoms.ether * 1}}, difficulty=1)
    blk = mine_next_block(chain)
    tx = get_transaction()
    assert tx not in blk.transactions
    messages.apply_transaction(chain.state, tx)
    assert chain.state.get_balance(v) == utils.denoms.finney * 990
    assert chain.state.get_balance(v2) == utils.denoms.finney * 10
Ejemplo n.º 10
0
def test_transfer(db):
    k, v, k2, v2 = accounts()
    chain = Chain({v: {"balance": utils.denoms.ether * 1}}, difficulty=1)
    b_v = chain.state.get_balance(v)
    b_v2 = chain.state.get_balance(v2)
    value = 42
    success = chain.state.transfer_value(v, v2, value)
    assert success
    assert chain.state.get_balance(v) == b_v - value
    assert chain.state.get_balance(v2) == b_v2 + value
Ejemplo n.º 11
0
def test_mine_block_with_transaction2(db):
    k, v, k2, v2 = accounts()
    chain = Chain({v: {"balance": utils.denoms.ether * 1}}, difficulty=1)
    genesis_hash = chain.state.prev_headers[0].hash
    tx = get_transaction()
    blk2 = mine_next_block(chain, coinbase=v, transactions=[tx])
    assert tx in blk2.transactions
    assert tx in blk2.transactions
    assert chain.get_block(blk2.hash) == blk2
    assert tx.gasprice == 0
    assert chain.state.get_balance(
        v) == chain.env.config['BLOCK_REWARD'] + chain.mk_poststate_of_blockhash(genesis_hash).get_balance(v) - tx.value
Ejemplo n.º 12
0
def test_genesis_chain(db):
    k, v, k2, v2 = accounts()
    chain = Chain({v: {"balance": utils.denoms.ether * 1}}, difficulty=1)
    blk = mine_on_chain(chain)
    print('blook', blk)

    assert chain.has_block(blk.hash)
    assert blk.hash in chain
    assert chain.get_block(blk.hash) == blk
    assert chain.head == blk
    assert chain.get_children(blk) == []
    assert chain.get_chain() == [blk]
    assert chain.get_block_by_number(1)
    assert not chain.get_block_by_number(2)
    assert chain.get_block_by_number(1) == blk
Ejemplo n.º 13
0
def test_genesis_from_state_snapshot():
    """
    Test if Chain could be initilaized from State snapshot
    """
    # Customize a state
    k, v, k2, v2 = accounts()
    alloc = {v: {"balance": utils.denoms.ether * 1}}
    state = mk_basic_state(alloc, None)
    state.block_difficulty = 1

    # Initialize another chain from state.to_snapshot()
    genesis = state.to_snapshot()
    new_chain = Chain(genesis=genesis)
    assert new_chain.state.trie.root_hash == state.trie.root_hash
    assert new_chain.state.block_difficulty == state.block_difficulty
    assert new_chain.head.number == state.block_number
Ejemplo n.º 14
0
def test_mine_block(db):
    k, v, k2, v2 = accounts()
    chain = Chain({v: {"balance": utils.denoms.ether * 1}}, difficulty=1)
    genesis_hash = chain.state.prev_headers[0].hash
    blk2 = mine_next_block(chain, coinbase=v)
    blk3 = mine_next_block(chain, coinbase=v)
    blk4 = mine_next_block(chain, coinbase=v)
    blk5 = mine_next_block(chain, coinbase=v)
    assert chain.state.get_balance(
        v) == chain.env.config['BLOCK_REWARD'] + chain.mk_poststate_of_blockhash(blk4.hash).get_balance(v)
    assert chain.state.get_balance(
        v) == chain.env.config['BLOCK_REWARD'] * 2 + chain.mk_poststate_of_blockhash(blk3.hash).get_balance(v)
    assert chain.state.get_balance(
        v) == chain.env.config['BLOCK_REWARD'] * 3 + chain.mk_poststate_of_blockhash(blk2.hash).get_balance(v)
    assert chain.state.get_balance(
        v) == chain.env.config['BLOCK_REWARD'] * 4 + chain.mk_poststate_of_blockhash(genesis_hash).get_balance(v)
    assert blk2.prevhash == genesis_hash
Ejemplo n.º 15
0
def test_simple_chain(db):
    k, v, k2, v2 = accounts()
    chain = Chain({v: {"balance": utils.denoms.ether * 1}}, difficulty=1)
    tx = get_transaction()
    blk2 = mine_next_block(chain, transactions=[tx])
    blk3 = mine_next_block(chain)

    assert blk2.hash in chain
    assert blk3.hash in chain
    assert chain.has_block(blk2.hash)
    assert chain.has_block(blk3.hash)
    assert chain.get_block(blk2.hash) == blk2
    assert chain.get_block(blk3.hash) == blk3
    assert chain.head == blk3
    assert chain.get_children(blk2) == [blk3]

    assert chain.get_chain() == [blk2, blk3]

    assert chain.get_block_by_number(1) == blk2
    assert chain.get_block_by_number(2) == blk3
    assert not chain.get_block_by_number(3)
    assert chain.get_tx_position(tx.hash) == (blk2.number, 0)
Ejemplo n.º 16
0
def test_prevhash(db):
    chain = Chain({}, difficulty=1)
    L1 = mine_on_chain(chain)
    assert chain.state.get_block_hash(0) != b'\x00' * 32
    assert chain.state.get_block_hash(1) != b'\x00' * 32
    assert chain.state.get_block_hash(2) == b'\x00' * 32
Ejemplo n.º 17
0
    def __init__(self, app):
        self.config = app.config
        sce = self.config['eth']
        if int(sce['pruning']) >= 0:
            self.db = RefcountDB(app.services.db)
            if "I am not pruning" in self.db.db:
                raise RuntimeError(
                    "The database in '{}' was initialized as non-pruning. "
                    "Can not enable pruning now.".format(
                        self.config['data_dir']))
            self.db.ttl = int(sce['pruning'])
            self.db.db.put("I am pruning", "1")
        else:
            self.db = app.services.db
            if "I am pruning" in self.db:
                raise RuntimeError(
                    "The database in '{}' was initialized as pruning. "
                    "Can not disable pruning now".format(
                        self.config['data_dir']))
            self.db.put("I am not pruning", "1")

        if 'network_id' in self.db:
            db_network_id = self.db.get(b'network_id')
            if db_network_id != to_string(sce['network_id']):
                raise RuntimeError(
                    "The database in '{}' was initialized with network id {} and can not be used "
                    "when connecting to network id {}. Please choose a different data directory."
                    .format(self.config['data_dir'], db_network_id,
                            sce['network_id']))

        else:
            self.db.put(b'network_id', to_string(sce['network_id']))
            self.db.commit()

        assert self.db is not None

        super(ChainService, self).__init__(app)
        log.info('initializing chain')
        coinbase = app.services.accounts.coinbase
        env = Env(self.db, sce['block'])

        genesis_data = sce.get('genesis_data', {})
        if not genesis_data:
            genesis_data = mk_genesis_data(env)
        self.chain = Chain(env=env,
                           genesis=genesis_data,
                           coinbase=coinbase,
                           new_head_cb=self._on_new_head)
        header = self.chain.state.prev_headers[0]
        log.info('chain at', number=header.number)
        if 'genesis_hash' in sce:
            assert sce['genesis_hash'] == self.chain.genesis.hex_hash, \
                "Genesis hash mismatch.\n  Expected: %s\n  Got: %s" % (
                    sce['genesis_hash'], self.chain.genesis.hex_hash)

        self.dao_challenges = dict()
        self.synchronizer = Synchronizer(self, force_sync=None)

        self.block_queue = Queue(maxsize=self.block_queue_size)
        # When the transaction_queue is modified, we must set
        # self._head_candidate_needs_updating to True in order to force the
        # head candidate to be updated.
        self.transaction_queue = TransactionQueue()
        self._head_candidate_needs_updating = True
        # Initialize a new head candidate.
        _ = self.head_candidate
        self.min_gasprice = 20 * 10**9  # TODO: better be an option to validator service?
        self.add_blocks_lock = False
        self.add_transaction_lock = gevent.lock.Semaphore()
        self.broadcast_filter = DuplicatesFilter()
        self.on_new_head_cbs = []
        self.newblock_processing_times = deque(maxlen=1000)
        gevent.spawn_later(self.process_time_queue_period,
                           self.process_time_queue)