Exemple #1
0
 def __init__(self, genesis, key, network, env, time_offset=5):
     # Create a chain object
     self.chain = Chain(genesis, env=env)
     # Use the validator's time as the chain's time
     self.chain.time = lambda: self.get_timestamp()
     # My private key
     self.key = key
     # My address
     self.address = privtoaddr(key)
     # My randao
     self.randao = RandaoManager(sha3(self.key))
     # Pointer to the test p2p network
     self.network = network
     # Record of objects already received and processed
     self.received_objects = {}
     # The minimum eligible timestamp given a particular number of skips
     self.next_skip_count = 0
     self.next_skip_timestamp = 0
     # This validator's indices in the state
     self.indices = None
     # Is this validator active?
     self.active = False
     # Code that verifies signatures from this validator
     self.validation_code = generate_validation_code(privtoaddr(key))
     # Parents that this validator has already built a block on
     self.used_parents = {}
     # This validator's clock offset (for testing purposes)
     self.time_offset = random.randrange(time_offset) - (time_offset // 2)
     # Determine the epoch length
     self.epoch_length = self.call_casper('getEpochLength')
     # Give this validator a unique ID
     self.id = len(ids)
     ids.append(self.id)
     self.find_my_indices()
     self.cached_head = self.chain.head_hash
Exemple #2
0
def generate_genesis(path=None, num_participants=1):
    privkeys = [
        utils.sha3(utils.to_string(i)) for i in range(num_participants)
    ]
    addrs = [utils.privtoaddr(k) for k in privkeys]
    deposit_sizes = [i * 500 + 500 for i in range(num_participants)]
    randaos = [RandaoManager(utils.sha3(k)) for k in privkeys]

    validators = [(generate_validation_code(a), ds * 10**18, r.get(9999), a)
                  for a, ds, r in zip(addrs, deposit_sizes, randaos)]
    s = make_casper_genesis(validators=validators,
                            alloc={a: {
                                'balance': 10**18
                            }
                                   for a in addrs},
                            timestamp=int(time.time()),
                            epoch_length=100)
    genesis_hash = apply_const_message(
        s,
        sender=casper_config['METROPOLIS_ENTRY_POINT'],
        to=casper_config['METROPOLIS_BLOCKHASH_STORE'],
        data=utils.encode_int32(0))
    genesis_number = call_casper(s, 'getBlockNumber')
    print('genesis block hash: %s' % utils.encode_hex(genesis_hash))
    print('genesis block number: %d' % genesis_number)
    print('%d validators: %r' %
          (num_participants, [utils.encode_hex(a) for a in addrs]))

    snapshot = s.to_snapshot()
    header = s.prev_headers[0]
    genesis = {
        "nonce": "0x" + utils.encode_hex(header.nonce),
        "difficulty": utils.int_to_hex(header.difficulty),
        "mixhash": "0x" + utils.encode_hex(header.mixhash),
        "coinbase": "0x" + utils.encode_hex(header.coinbase),
        "timestamp": utils.int_to_hex(header.timestamp),
        "parentHash": "0x" + utils.encode_hex(header.prevhash),
        "extraData": "0x" + utils.encode_hex(header.extra_data),
        "gasLimit": utils.int_to_hex(header.gas_limit),
        "alloc": snapshot["alloc"]
    }

    if path:
        with open(path, 'w') as f:
            json.dump(genesis,
                      f,
                      sort_keys=False,
                      indent=4,
                      separators=(',', ': '))
        print('casper genesis generated')
    else:
        return genesis
Exemple #3
0
 def __init__(self, genesis, key, network, env, time_offset=5):
     # Create a chain object
     self.chain = Chain(genesis, env=env)
     # Create a transaction queue
     self.txqueue = TransactionQueue()
     # Use the validator's time as the chain's time
     self.chain.time = lambda: self.get_timestamp()
     # My private key
     self.key = key
     # My address
     self.address = privtoaddr(key)
     # My randao
     self.randao = RandaoManager(sha3(self.key))
     # Pointer to the test p2p network
     self.network = network
     # Record of objects already received and processed
     self.received_objects = {}
     # The minimum eligible timestamp given a particular number of skips
     self.next_skip_count = 0
     self.next_skip_timestamp = 0
     # Is this validator active?
     self.active = False
     # Code that verifies signatures from this validator
     self.validation_code = generate_validation_code(privtoaddr(key))
     # Validation code hash
     self.vchash = sha3(self.validation_code)
     # Parents that this validator has already built a block on
     self.used_parents = {}
     # This validator's clock offset (for testing purposes)
     self.time_offset = random.randrange(time_offset) - (time_offset // 2)
     # Determine the epoch length
     self.epoch_length = self.call_casper('getEpochLength')
     # My minimum gas price
     self.mingasprice = 20 * 10**9
     # Give this validator a unique ID
     self.id = len(ids)
     ids.append(self.id)
     self.update_activity_status()
     self.cached_head = self.chain.head_hash
Exemple #4
0
from ethereum.config import default_config, Env
import copy
import time
import rlp

# config_string = ':info,eth.vm.log:trace,eth.vm.op:trace,eth.vm.stack:trace,eth.vm.exit:trace,eth.pb.msg:trace,eth.pb.tx:debug'
config_string = ':info,eth.vm.log:trace'
configure_logging(config_string=config_string)

NUM_PARTICIPANTS = 10
BLOCK_MAKING_PPB = 10

print('Initializing privkeys, addresses and randaos for validators')
privkeys = [utils.sha3(str(i)) for i in range(NUM_PARTICIPANTS)]
addrs = [utils.privtoaddr(k) for k in privkeys]
randaos = [RandaoManager(utils.sha3(str(i))) for i in range(NUM_PARTICIPANTS)]
deposit_sizes = [i * 500 + 500 for i in range(NUM_PARTICIPANTS)]
vcodes = [generate_validation_code(a) for a in addrs]
vchashes = [utils.sha3(c) for c in vcodes]
assert len(privkeys) == len(addrs) == len(randaos) == len(deposit_sizes) == len(vcodes) == len(vchashes) == NUM_PARTICIPANTS

# Creating casper contract translator
ct = get_casper_ct()
assert ct
print('Constructing genesis')
s = make_casper_genesis(validators=[(generate_validation_code(a), ds * 10**18, r.get(9999), a)
                                    for a, ds, r in zip(addrs, deposit_sizes, randaos)][:-1],
                        alloc={a: {'balance': 10**18} for a in addrs},
                        timestamp=int(time.time() - 99999),
                        epoch_length=100)
print('Genesis constructed successfully')
Exemple #5
0
    get_hash_without_ed_code, make_casper_genesis
from ethereum.utils import sha3, privtoaddr
from ethereum.transactions import Transaction
from ethereum.state_transition import apply_transaction

from ethereum.slogging import LogRecorder, configure_logging, set_level
# config_string = ':info,eth.vm.log:trace,eth.vm.op:trace,eth.vm.stack:trace,eth.vm.exit:trace,eth.pb.msg:trace,eth.pb.tx:debug'
config_string = ':info,eth.vm.log:trace'
configure_logging(config_string=config_string)

n = networksim.NetworkSimulator(latency=150)
n.time = 2
print 'Generating keys'
keys = [sha3(str(i)) for i in range(20)]
print 'Initializing randaos'
randaos = [RandaoManager(sha3(k)) for k in keys]
deposit_sizes = [128] * 15 + [256] * 5

print 'Creating genesis state'
s = make_casper_genesis(
    validators=[(generate_validation_code(privtoaddr(k)), ds * 10**18,
                 r.get(9999))
                for k, ds, r in zip(keys, deposit_sizes, randaos)],
    alloc={privtoaddr(k): {
        'balance': 10**18
    }
           for k in keys},
    timestamp=2,
    epoch_length=50)
g = s.to_snapshot()
print 'Genesis state created'
Exemple #6
0
class Validator():
    def __init__(self, genesis, key, network, env, time_offset=5):
        # Create a chain object
        self.chain = Chain(genesis, env=env)
        # Create a transaction queue
        self.txqueue = TransactionQueue()
        # Use the validator's time as the chain's time
        self.chain.time = lambda: self.get_timestamp()
        # My private key
        self.key = key
        # My address
        self.address = privtoaddr(key)
        # My randao
        self.randao = RandaoManager(sha3(self.key))
        # Pointer to the test p2p network
        self.network = network
        # Record of objects already received and processed
        self.received_objects = {}
        # The minimum eligible timestamp given a particular number of skips
        self.next_skip_count = 0
        self.next_skip_timestamp = 0
        # Is this validator active?
        self.active = False
        # Code that verifies signatures from this validator
        self.validation_code = generate_validation_code(privtoaddr(key))
        # Validation code hash
        self.vchash = sha3(self.validation_code)
        # Parents that this validator has already built a block on
        self.used_parents = {}
        # This validator's clock offset (for testing purposes)
        self.time_offset = random.randrange(time_offset) - (time_offset // 2)
        # Determine the epoch length
        self.epoch_length = self.call_casper('getEpochLength')
        # My minimum gas price
        self.mingasprice = 20 * 10**9
        # Give this validator a unique ID
        self.id = len(ids)
        ids.append(self.id)
        self.update_activity_status()
        self.cached_head = self.chain.head_hash

    def call_casper(self, fun, args=[]):
        return call_casper(self.chain.state, fun, args)

    def update_activity_status(self):
        start_epoch = self.call_casper('getStartEpoch', [self.vchash])
        now_epoch = self.call_casper('getEpoch')
        end_epoch = self.call_casper('getEndEpoch', [self.vchash])
        if start_epoch <= now_epoch < end_epoch:
            self.active = True
            self.next_skip_count = 0
            self.next_skip_timestamp = get_timestamp(self.chain,
                                                     self.next_skip_count)
            print 'In current validator set'
        else:
            self.active = False

    def get_timestamp(self):
        return int(self.network.time * 0.01) + self.time_offset

    def on_receive(self, obj):
        if isinstance(obj, list):
            for _obj in obj:
                self.on_receive(_obj)
            return
        if obj.hash in self.received_objects:
            return
        if isinstance(obj, Block):
            print 'Receiving block', obj
            assert obj.hash not in self.chain
            block_success = self.chain.add_block(obj)
            self.network.broadcast(self, obj)
            self.network.broadcast(self, ChildRequest(obj.header.hash))
            self.update_head()
        elif isinstance(obj, Transaction):
            print 'Receiving transaction', obj
            if obj.gasprice >= self.mingasprice:
                self.txqueue.add_transaction(obj)
                print 'Added transaction, txqueue size %d' % len(
                    self.txqueue.txs)
                self.network.broadcast(self, obj)
            else:
                print 'Gasprice too low'
        self.received_objects[obj.hash] = True
        for x in self.chain.get_chain():
            assert x.hash in self.received_objects

    def tick(self):
        # Try to create a block
        # Conditions:
        # (i) you are an active validator,
        # (ii) you have not yet made a block with this parent
        if self.active and self.chain.head_hash not in self.used_parents:
            t = self.get_timestamp()
            # Is it early enough to create the block?
            if t >= self.next_skip_timestamp and (
                    not self.chain.head
                    or t > self.chain.head.header.timestamp):
                # Wrong validator; in this case, just wait for the next skip count
                if not check_skips(self.chain, self.vchash,
                                   self.next_skip_count):
                    self.next_skip_count += 1
                    self.next_skip_timestamp = get_timestamp(
                        self.chain, self.next_skip_count)
                    # print 'Incrementing proposed timestamp for block %d to %d' % \
                    #     (self.chain.head.header.number + 1 if self.chain.head else 0, self.next_skip_timestamp)
                    return
                self.used_parents[self.chain.head_hash] = True
                # Simulated 15% chance of validator failure to make a block
                if random.random() > 0.999:
                    print 'Simulating validator failure, block %d not created' % (
                        self.chain.head.header.number +
                        1 if self.chain.head else 0)
                    return
                # Make the block
                s1 = self.chain.state.trie.root_hash
                pre_dunkle_count = self.call_casper('getTotalDunklesIncluded')
                dunkle_txs = get_dunkle_candidates(self.chain,
                                                   self.chain.state)
                blk = make_head_candidate(self.chain, self.txqueue)
                randao = self.randao.get_parent(
                    self.call_casper('getRandao', [self.vchash]))
                blk = sign_block(blk, self.key, randao, self.vchash,
                                 self.next_skip_count)
                # Make sure it's valid
                global global_block_counter
                global_block_counter += 1
                for dtx in dunkle_txs:
                    assert dtx in blk.transactions, (dtx, blk.transactions)
                print 'made block with timestamp %d and %d dunkles' % (
                    blk.timestamp, len(dunkle_txs))
                s2 = self.chain.state.trie.root_hash
                assert s1 == s2
                assert blk.timestamp >= self.next_skip_timestamp
                assert self.chain.add_block(blk)
                self.update_head()
                post_dunkle_count = self.call_casper('getTotalDunklesIncluded')
                assert post_dunkle_count - pre_dunkle_count == len(dunkle_txs)
                self.received_objects[blk.hash] = True
                print 'Validator %d making block %d (%s)' % (
                    self.id, blk.header.number,
                    blk.header.hash[:8].encode('hex'))
                self.network.broadcast(self, blk)
        # Sometimes we received blocks too early or out of order;
        # run an occasional loop that processes these
        if random.random() < 0.02:
            self.chain.process_time_queue()
            self.chain.process_parent_queue()
            self.update_head()

    def update_head(self):
        if self.cached_head == self.chain.head_hash:
            return
        self.cached_head = self.chain.head_hash
        if self.chain.state.block_number % self.epoch_length == 0:
            self.update_activity_status()
        if self.active:
            self.next_skip_count = 0
            self.next_skip_timestamp = get_timestamp(self.chain,
                                                     self.next_skip_count)
        print 'Head changed: %s, will attempt creating a block at %d' % (
            self.chain.head_hash.encode('hex'), self.next_skip_timestamp)

    def withdraw(self, gasprice=20 * 10**9):
        sigdata = make_withdrawal_signature(self.key)
        txdata = casper_ct.encode('startWithdrawal', [self.vchash, sigdata])
        tx = Transaction(self.chain.state.get_nonce(self.address), gasprice,
                         650000, self.chain.config['CASPER_ADDR'], 0,
                         txdata).sign(self.key)
        self.txqueue.add_transaction(tx, force=True)
        self.network.broadcast(self, tx)
        print 'Withdrawing!'

    def deposit(self, gasprice=20 * 10**9):
        assert value * 10**18 >= self.chain.state.get_balance(
            self.address) + gasprice * 1000000
        tx = Transaction(
            self.chain.state.get_nonce(self.address) * 10**18, gasprice,
            1000000, casper_config['CASPER_ADDR'], value * 10**18,
            ct.encode('deposit', [self.validation_code,
                                  self.randao.get(9999)]))
Exemple #7
0
class Validator():
    def __init__(self, genesis, key, network, env, time_offset=5):
        # Create a chain object
        self.chain = Chain(genesis, env=env)
        # Create a transaction queue
        self.txqueue = TransactionQueue()
        # Use the validator's time as the chain's time
        self.chain.time = lambda: self.get_timestamp()
        # My private key
        self.key = key
        # My address
        self.address = privtoaddr(key)
        # My randao
        self.randao = RandaoManager(sha3(self.key))
        # Pointer to the test p2p network
        self.network = network
        # Record of objects already received and processed
        self.received_objects = {}
        # The minimum eligible timestamp given a particular number of skips
        self.next_skip_count = 0
        self.next_skip_timestamp = 0
        # Is this validator active?
        self.active = False
        # Code that verifies signatures from this validator
        self.validation_code = generate_validation_code(privtoaddr(key))
        # Validation code hash
        self.vchash = sha3(self.validation_code)
        # Parents that this validator has already built a block on
        self.used_parents = {}
        # This validator's clock offset (for testing purposes)
        self.time_offset = random.randrange(time_offset) - (time_offset // 2)
        # Determine the epoch length
        self.epoch_length = self.call_casper('getEpochLength')
        # My minimum gas price
        self.mingasprice = 20 * 10**9
        # Give this validator a unique ID
        self.id = len(ids)
        ids.append(self.id)
        self.update_activity_status()
        self.cached_head = self.chain.head_hash

    def call_casper(self, fun, args=[]):
        return call_casper(self.chain.state, fun, args)

    def update_activity_status(self):
        start_epoch = self.call_casper('getStartEpoch', [self.vchash])
        now_epoch = self.call_casper('getEpoch')
        end_epoch = self.call_casper('getEndEpoch', [self.vchash])
        if start_epoch <= now_epoch < end_epoch:
            self.active = True
            self.next_skip_count = 0
            self.next_skip_timestamp = get_timestamp(self.chain, self.next_skip_count)
            print 'In current validator set'
        else:
            self.active = False

    def get_timestamp(self):
        return int(self.network.time * 0.01) + self.time_offset

    def on_receive(self, obj):
        if isinstance(obj, list):
            for _obj in obj:
                self.on_receive(_obj)
            return
        if obj.hash in self.received_objects:
            return
        if isinstance(obj, Block):
            print 'Receiving block', obj
            assert obj.hash not in self.chain
            block_success = self.chain.add_block(obj)
            self.network.broadcast(self, obj)
            self.network.broadcast(self, ChildRequest(obj.header.hash))
            self.update_head()
        elif isinstance(obj, Transaction):
            print 'Receiving transaction', obj
            if obj.gasprice >= self.mingasprice:
                self.txqueue.add_transaction(obj)
                print 'Added transaction, txqueue size %d' % len(self.txqueue.txs)
                self.network.broadcast(self, obj)
            else:
                print 'Gasprice too low'
        self.received_objects[obj.hash] = True
        for x in self.chain.get_chain():
            assert x.hash in self.received_objects

    def tick(self):
        # Try to create a block
        # Conditions:
        # (i) you are an active validator,
        # (ii) you have not yet made a block with this parent
        if self.active and self.chain.head_hash not in self.used_parents:
            t = self.get_timestamp()
            # Is it early enough to create the block?
            if t >= self.next_skip_timestamp and (not self.chain.head or t > self.chain.head.header.timestamp):
                # Wrong validator; in this case, just wait for the next skip count
                if not check_skips(self.chain, self.vchash, self.next_skip_count):
                    self.next_skip_count += 1
                    self.next_skip_timestamp = get_timestamp(self.chain, self.next_skip_count)
                    # print 'Incrementing proposed timestamp for block %d to %d' % \
                    #     (self.chain.head.header.number + 1 if self.chain.head else 0, self.next_skip_timestamp)
                    return
                self.used_parents[self.chain.head_hash] = True
                # Simulated 15% chance of validator failure to make a block
                if random.random() > 0.999:
                    print 'Simulating validator failure, block %d not created' % (self.chain.head.header.number + 1 if self.chain.head else 0)
                    return
                # Make the block
                s1 = self.chain.state.trie.root_hash
                pre_dunkle_count = self.call_casper('getTotalDunklesIncluded')
                dunkle_txs = get_dunkle_candidates(self.chain, self.chain.state)
                blk = make_head_candidate(self.chain, self.txqueue)
                randao = self.randao.get_parent(self.call_casper('getRandao', [self.vchash]))
                blk = sign_block(blk, self.key, randao, self.vchash, self.next_skip_count)
                # Make sure it's valid
                global global_block_counter
                global_block_counter += 1
                for dtx in dunkle_txs:
                    assert dtx in blk.transactions, (dtx, blk.transactions)
                print 'made block with timestamp %d and %d dunkles' % (blk.timestamp, len(dunkle_txs))
                s2 = self.chain.state.trie.root_hash
                assert s1 == s2
                assert blk.timestamp >= self.next_skip_timestamp
                assert self.chain.add_block(blk)
                self.update_head()
                post_dunkle_count = self.call_casper('getTotalDunklesIncluded')
                assert post_dunkle_count - pre_dunkle_count == len(dunkle_txs)
                self.received_objects[blk.hash] = True
                print 'Validator %d making block %d (%s)' % (self.id, blk.header.number, blk.header.hash[:8].encode('hex'))
                self.network.broadcast(self, blk)
        # Sometimes we received blocks too early or out of order;
        # run an occasional loop that processes these
        if random.random() < 0.02:
            self.chain.process_time_queue()
            self.chain.process_parent_queue()
            self.update_head()

    def update_head(self):
        if self.cached_head == self.chain.head_hash:
            return
        self.cached_head = self.chain.head_hash
        if self.chain.state.block_number % self.epoch_length == 0:
            self.update_activity_status()
        if self.active:
            self.next_skip_count = 0
            self.next_skip_timestamp = get_timestamp(self.chain, self.next_skip_count)
        print 'Head changed: %s, will attempt creating a block at %d' % (self.chain.head_hash.encode('hex'), self.next_skip_timestamp)

    def withdraw(self, gasprice=20 * 10**9):
        sigdata = make_withdrawal_signature(self.key)
        txdata = casper_ct.encode('startWithdrawal', [self.vchash, sigdata])
        tx = Transaction(self.chain.state.get_nonce(self.address), gasprice, 650000, self.chain.config['CASPER_ADDR'], 0, txdata).sign(self.key)
        self.txqueue.add_transaction(tx, force=True)
        self.network.broadcast(self, tx)
        print 'Withdrawing!'

    def deposit(self, gasprice=20 * 10**9):
        assert value * 10**18 >= self.chain.state.get_balance(self.address) + gasprice * 1000000
        tx = Transaction(self.chain.state.get_nonce(self.address) * 10**18, gasprice, 1000000,
                         casper_config['CASPER_ADDR'], value * 10**18,
                         ct.encode('deposit', [self.validation_code, self.randao.get(9999)]))