Exemple #1
0
        config['tdm_IP'], config['tdm_RPC'], block))
    j = json.loads(ret.text)
    return j


if __name__ == '__main__':
    block = {}
    while True:
        latest = tendermint_latest_block()
        for blk in range(last_block + 1, latest + 1):
            print('blk', blk)
            tdm_block = get_tendermint_block(blk)
            apphash = tdm_block['result']['block_meta']['header']['app_hash']
            sedes = CountableList(
                List([
                    rlp.sedes.binary, rlp.sedes.big_endian_int,
                    rlp.sedes.big_endian_int, rlp.sedes.binary,
                    rlp.sedes.binary
                ]))
            d = rlp.decode(bytes.fromhex(apphash), sedes)
            for i in d:
                block[i[1]] = Block(i[0], i[1], bool(i[2]), i[3], i[4])
                plasma_latest_block = i[1]
            txs = tdm_block['result']['block']['data']['txs']
            for tx in txs:
                decoded_tx = base64.b64decode(tx).decode()
                if decoded_tx[0] == '1':
                    decoded_tx = decoded_tx[1:]
                    sig = decoded_tx[:130]
                    blkNum = int(decoded_tx[130:], 16)
                    block[blkNum].add_signature(sig)
                # block[i[1]].submit()
Exemple #2
0
class Blocks(rlp.Serializable):
    fields = [
        ("reqid", big_endian_int),
        ("blocks", CountableList(Block)),
    ]
Exemple #3
0
class CompactBlock(rlp.Serializable):
    fields = [
        ("block_header", BlockHeader),
        ("nonce", big_endian_int),
        ("tx_short_ids", CountableList(big_endian_int)),
    ]
Exemple #4
0
 def serialize(cls, obj):
     return CountableList(Transaction).serialize(obj.transactions)
Exemple #5
0
class BlockHeaders(rlp.Serializable):
    fields = [
        ("reqid", big_endian_int),
        ("headers", CountableList(BlockHeader)),
    ]
Exemple #6
0
class Hello(rlp.Serializable):
    fields = [("network_id", big_endian_int),
              ("capabilities", CountableList(Capability)),
              ("node_endpoint", NodeEndpoint)]
Exemple #7
0
class BaseBeaconBlock(rlp.Serializable):
    fields = [
        # Slot number
        ('slot', uint64),
        # Proposer RANDAO reveal
        ('randao_reveal', hash32),
        # Recent PoW receipt root
        ('candidate_pow_receipt_root', hash32),
        # Skip list of previous beacon block hashes
        # i'th item is the most recent ancestor whose slot is a multiple of 2**i for i = 0, ..., 31
        ('ancestor_hashes', CountableList(hash32)),
        # State root
        ('state_root', hash32),
        # Attestations
        ('attestations', CountableList(AttestationRecord)),
        # Specials (e.g. logouts, penalties)
        ('specials', CountableList(SpecialRecord)),
        # Proposer signature
        ('proposer_signature', CountableList(uint256)),
    ]

    def __init__(self,
                 slot: int,
                 randao_reveal: Hash32,
                 candidate_pow_receipt_root: Hash32,
                 ancestor_hashes: Sequence[Hash32],
                 state_root: Hash32,
                 attestations: Sequence[AttestationRecord],
                 specials: Sequence[SpecialRecord],
                 proposer_signature: Sequence[int] = None) -> None:
        if proposer_signature is None:
            proposer_signature = (0, 0)
        super().__init__(
            slot=slot,
            randao_reveal=randao_reveal,
            candidate_pow_receipt_root=candidate_pow_receipt_root,
            ancestor_hashes=ancestor_hashes,
            state_root=state_root,
            attestations=attestations,
            specials=specials,
            proposer_signature=proposer_signature,
        )

    def __repr__(self) -> str:
        return '<Block #{0} {1}>'.format(
            self.slot,
            encode_hex(self.hash)[2:10],
        )

    _hash = None

    @property
    def hash(self) -> Hash32:
        if self._hash is None:
            self._hash = blake(rlp.encode(self))
        return self._hash

    @property
    def num_attestations(self) -> int:
        return len(self.attestations)

    @property
    def parent_hash(self) -> Hash32:
        if not self.ancestor_hashes:
            return None
        else:
            return self.ancestor_hashes[0]
class MimbleBlock(rlp.Serializable):
    blknum = 0
    diff_tx = None

    fields = [
        ('transaction_set', CountableList(MimbleTx)),
    ]

    def __init__(self, blknum=0):
        self.blknum = blknum

    def add_tx(self, tx):
        if (self.diff_tx == None):
            self.diff_tx = tx
        else:
            self.diff_tx = self.diff_tx.combine(tx)

    def get_total_commitment(self):
        commitment = NullPoint

        if (self.diff_tx != None):
            for i in range(0, len(self.diff_tx.inputs)):
                commitment = add(commitment, self.diff_tx.inputs[i].commitment)

            commitment = neg(commitment)

            for i in range(0, len(self.diff_tx.outputs)):
                commitment = add(commitment, self.diff_tx.outputs[i].commitment)

        return commitment

    def get_total_signature(self):
        if (self.diff_tx != None):
            pub_key = Schnorr.recover_multiple(self.diff_tx.sigs)
        else:
            pub_key = NullPoint

        return pub_key

    def get_bulletproofs(self):
        if (self.diff_tx != None):
            bp = []
            for i in range(0, len(self.diff_tx.outputs)):
                bp = bp + [self.diff_tx.outputs[i].bp]

            return bp
        else:
            return None

    def verify(self, verifyBP=True):
        import time

        t0, t1, t2 = 0, 0, 0
        if (self.diff_tx != None):
            ms = time.time()
            if (not self.diff_tx.verify()): return False
            t0 = time.time() - ms

            if (verifyBP):
                bp = self.get_bulletproofs()

                if (bp == None): return False
                if (len(bp) != len(self.diff_tx.outputs)): return False

                print("Verifying " + str(len(bp)) + " bulletproofs...", end="")
                ms = time.time()
                if (bp != None and not BulletProof.VerifyMulti(bp)): return False
                t1 = time.time() - ms
                t2 = t1 / len(bp)               
                print("Done!")
                
        print("verify() => " + str(t0+t1) + "s (" + str(t2) + "s per bulletproof)")
        return True
                
    def print(self):
        print("MimbleBlock:")
        print("Block Number: " + str(self.blknum))
        if (self.diff_tx != None):
            print("Total Commitment: " + hex(CompressPoint(self.get_total_commitment())))
            print("Multisignature: " + hex(CompressPoint(self.get_total_signature())))
            print("Diff Tx:")
            self.diff_tx.print()
        else:
            print("No Transactions")
class MimbleTx(rlp.Serializable):

    fields = [
        ('inputs', CountableList(TxOutput)),
        ('outputs', CountableList(TxOutput)),
        ('sig', CountableList(Schnorr)),
        ('offset', big_endian_int)
    ]

    def __init__(self, inputs, outputs, sigs, offset=0):
        self.inputs = inputs
        self.outputs = outputs
        self.sigs = sigs
        self.offset = offset

    def verify(self):
        #Add up commitments
        commitment = NullPoint
        for i in range(0, len(self.inputs)):
            commitment = add(commitment, self.inputs[i].commitment)

        commitment = neg(commitment)

        for i in range(0, len(self.outputs)):
            commitment = add(commitment, self.outputs[i].commitment)

        #Add up Schnorr public keys, see if remainder is signed (x known s.t. remainder = x*)
        remainder = add(Schnorr.recover_multiple(self.sigs), multiply(G, self.offset))

        if (not eq(commitment, remainder)):
            return False

        return True

    def combine(tx1, tx2):
        #Naively combine tx's
        inp12 = tx1.inputs + tx2.inputs
        out12 = tx1.outputs + tx2.outputs
        sigs12 = tx1.sigs + tx2.sigs
        off12 = sAdd(tx1.offset, tx2.offset)

        #Remove common inputs and outputs (cut-through)
        i = 0
        while i < len(inp12):
            j = 0
            while j < len(out12):
                if (eq(inp12[i].commitment, out12[j].commitment)):
                    inp12 = inp12[:i] + inp12[i+1:]
                    out12 = out12[:j] + out12[j+1:]
                    i -= 1
                    j -= 1

                j += 1
            i += 1

        #Return new Tx
        return MimbleTx(inp12, out12, sigs12, off12)

    def create_random(input_count, output_count, createBP=True, max_value=1000):
        import time
        (v_in, v_out, bf_in, bf_out, off, rem) = GetRandomTxValues(input_count, output_count, max_value=max_value)
        inputs1 = TxOutput.Create(v_in, bf_in)

        if (createBP):
            print("Creating " + str(output_count) + " bulletproofs...", end="")
            ms = time.time()
            
        outputs1 = TxOutput.Create(v_out, bf_out, createBP=createBP)

        if (createBP):
            t0 = time.time() - ms
            print("Done!")
            print("create() => " + str(t0) + "s (" + str(t0 / output_count) + "s per bulletproof)")
            
        sigs1 = [Schnorr.sign(rem)]
        tx = MimbleTx(inputs1, outputs1, sigs1, off)
        return tx
    
    def create_known(v_in, bf_in, v_out, bf_out, createBP=True):
        import time
        #Calculate remainder
        inputs1 = TxOutput.Create(v_in, bf_in)

        if (createBP):
            print("Creating " + str(len(bf_out)) + " bulletproofs...", end="")
            ms = time.time()
            
        outputs1 = TxOutput.Create(v_out, bf_out, createBP=createBP)

        off = getRandom()
        rem = sSub(vSum(bf_out), sAdd(vSum(bf_in), off))

        if (createBP):
            t0 = time.time() - ms
            print("Done!")
            print("create() => " + str(t0) + "s (" + str(t0 / len(bf_out)) + "s per bulletproof)")
                  
        sig1 = [Schnorr.sign(rem)]
        tx = MimbleTx(inputs1, outputs1, sig1, off)
        return tx
    
    def print(self, detailed=False):
        print("Inputs: " + str(len(self.inputs)))
        if (detailed):
            for i in range(0, len(self.inputs)):
                print("\t" + str(i) + ": " + hex(CompressPoint(self.inputs[i].commitment)))
            
        print("Outputs: " + str(len(self.outputs)))
        if (detailed):
            for i in range(0, len(self.outputs)):
                print("\t" + str(i) + ": " + hex(CompressPoint(self.outputs[i].commitment)))
            
        print("Sigs: " + str(len(self.sigs)))
        if (detailed):
            for i in range(0, len(self.sigs)):
                print("Sig " + str(i) + ":")
                print("\tR: "+ hex(CompressPoint(self.sigs[i].R)))
                print("\ts: "+ hex(CompressPoint(self.sigs[i].s)))
                
        print("Sig Offset: " + hex(self.offset))
Exemple #10
0
class AccountAccesses(rlp.Serializable):
    fields = [
        ('account', address),
        ('storage_keys', CountableList(BigEndianInt(32))),
    ]
Exemple #11
0
class SpuriousDragonBlock(HomesteadBlock):
    transaction_class = SpuriousDragonTransaction
    fields = [('header', BlockHeader),
              ('transactions', CountableList(transaction_class)),
              ('uncles', CountableList(BlockHeader))]
Exemple #12
0
class AccessListTransaction(rlp.Serializable, SignedTransactionMethods, SignedTransactionAPI):
    _type_id = ACCESS_LIST_TRANSACTION_TYPE
    fields = [
        ('chain_id', big_endian_int),
        ('nonce', big_endian_int),
        ('gas_price', big_endian_int),
        ('gas', big_endian_int),
        ('to', address),
        ('value', big_endian_int),
        ('data', binary),
        ('access_list', CountableList(AccountAccesses)),
        ('y_parity', big_endian_int),
        ('r', big_endian_int),
        ('s', big_endian_int),
    ]

    def get_sender(self) -> Address:
        return extract_transaction_sender(self)

    def get_message_for_signing(self) -> bytes:
        unsigned = UnsignedAccessListTransaction(
            self.chain_id,
            self.nonce,
            self.gas_price,
            self.gas,
            self.to,
            self.value,
            self.data,
            self.access_list,
        )
        payload = rlp.encode(unsigned)
        return self._type_byte + payload

    def check_signature_validity(self) -> None:
        validate_transaction_signature(self)

    @cached_property
    def _type_byte(self) -> bytes:
        return to_bytes(self._type_id)

    @cached_property
    def hash(self) -> Hash32:
        raise NotImplementedError("Call hash() on the TypedTransaction instead")

    def get_intrinsic_gas(self) -> int:
        core_gas = calculate_intrinsic_gas(ISTANBUL_TX_GAS_SCHEDULE, self)

        num_addresses = len(self.access_list)
        preload_address_costs = ACCESS_LIST_ADDRESS_COST_EIP_2930 * num_addresses

        num_slots = sum(len(slots) for _, slots in self.access_list)
        preload_slot_costs = ACCESS_LIST_STORAGE_KEY_COST_EIP_2930 * num_slots

        return core_gas + preload_address_costs + preload_slot_costs

    def encode(self) -> bytes:
        return rlp.encode(self)

    def make_receipt(
            self,
            status: bytes,
            gas_used: int,
            log_entries: Tuple[Tuple[bytes, Tuple[int, ...], bytes], ...]) -> ReceiptAPI:

        logs = [
            Log(address, topics, data)
            for address, topics, data
            in log_entries
        ]
        # TypedTransaction is responsible for wrapping this into a TypedReceipt
        return Receipt(
            state_root=status,
            gas_used=gas_used,
            logs=logs,
        )

    # Old transactions are treated as setting both max-fees as the gas price
    @property
    def max_priority_fee_per_gas(self) -> int:
        return self.gas_price

    @property
    def max_fee_per_gas(self) -> int:
        return self.gas_price
Exemple #13
0
class ArrowGlacierBlock(LondonBlock):
    transaction_builder: Type[
        TransactionBuilderAPI] = ArrowGlacierTransactionBuilder
    fields = [('header', ArrowGlacierBlockHeader),
              ('transactions', CountableList(transaction_builder)),
              ('uncles', CountableList(LondonBackwardsHeader))]
Exemple #14
0
class BaseBeaconBlock(rlp.Serializable, Configurable, ABC):
    block_body_class = BaseBeaconBlockBody

    fields = [
        #
        # Header
        #
        ('slot', uint64),
        ('parent_root', hash32),
        ('state_root', hash32),
        ('randao_reveal', hash32),
        ('candidate_pow_receipt_root', hash32),
        ('signature', CountableList(uint384)),

        #
        # Body
        #
        ('body', block_body_class),
    ]

    def __init__(self,
                 slot: SlotNumber,
                 parent_root: Hash32,
                 state_root: Hash32,
                 randao_reveal: Hash32,
                 candidate_pow_receipt_root: Hash32,
                 body: BaseBeaconBlockBody,
                 signature: BLSSignature = EMPTY_SIGNATURE) -> None:
        super().__init__(
            slot=slot,
            parent_root=parent_root,
            state_root=state_root,
            randao_reveal=randao_reveal,
            candidate_pow_receipt_root=candidate_pow_receipt_root,
            signature=signature,
            body=body,
        )

    def __repr__(self) -> str:
        return '<Block #{0} {1}>'.format(
            self.slot,
            encode_hex(self.root)[2:10],
        )

    _hash = None

    @property
    def hash(self) -> Hash32:
        if self._hash is None:
            self._hash = hash_eth2(rlp.encode(self))
        return self._hash

    @property
    def root(self) -> Hash32:
        # Alias of `hash`.
        # Using flat hash, might change to SSZ tree hash.
        return self.hash

    @property
    def num_attestations(self) -> int:
        return len(self.body.attestations)

    @property
    def block_without_signature_root(self) -> Hash32:
        return self.copy(signature=EMPTY_SIGNATURE).root

    @classmethod
    @abstractmethod
    def from_root(cls, root: Hash32,
                  chaindb: 'BaseBeaconChainDB') -> 'BaseBeaconBlock':
        """
        Return the block denoted by the given block root.
        """
        raise NotImplementedError("Must be implemented by subclasses")
Exemple #15
0
class GetBlockTxn(rlp.Serializable):
    fields = [
        ("reqid", big_endian_int),
        ("block_hash", hash32),
        ("indexes", CountableList(big_endian_int)),
    ]
Exemple #16
0
class BeaconState(rlp.Serializable):
    """
    Note: using RLP until we have standardized serialization format.
    """
    fields = [
        # Misc
        ('slot', uint64),
        ('genesis_time', uint64),
        ('fork', Fork),  # For versioning hard forks

        # Validator registry
        ('validator_registry', CountableList(ValidatorRecord)),
        ('validator_balances', CountableList(uint64)),
        ('validator_registry_update_slot', uint64),
        ('validator_registry_exit_count', uint64),
        ('validator_registry_delta_chain_tip',
         hash32),  # For light clients to easily track delta

        # Randomness and committees
        ('latest_randao_mixes', CountableList(hash32)),
        ('latest_vdf_outputs', CountableList(hash32)),

        # TODO Remove `persistent_committee_reassignments`
        ('persistent_committees', CountableList(CountableList(uint24))),
        ('persistent_committee_reassignments',
         CountableList(ShardReassignmentRecord)),
        ('previous_epoch_start_shard', uint64),
        ('current_epoch_start_shard', uint64),
        ('previous_epoch_calculation_slot', uint64),
        ('current_epoch_calculation_slot', uint64),
        ('previous_epoch_randao_mix', hash32),
        ('current_epoch_randao_mix', hash32),

        # Custody challenges
        ('custody_challenges', CountableList(CustodyChallenge)),

        # Finality
        ('previous_justified_slot', uint64),
        ('justified_slot', uint64),

        # Note: justification_bitfield is meant to be defined as an integer type,
        # so its bit operation in Python and is easier to specify and implement.
        ('justification_bitfield', uint64),
        ('finalized_slot', uint64),

        # Recent state
        ('latest_crosslinks', CountableList(CrosslinkRecord)),
        ('latest_block_roots', CountableList(hash32)
         ),  # Needed to process attestations, older to newer  # noqa: E501
        ('latest_penalized_balances', CountableList(uint64)
         ),  # Balances penalized at every withdrawal period  # noqa: E501
        ('latest_attestations', CountableList(PendingAttestationRecord)),
        (
            'batched_block_roots', CountableList(Hash32)
        ),  # allow for a log-sized Merkle proof from any block to any historical block root"  # noqa: E501

        # Ethereum 1.0 chain
        ('latest_eth1_data', Eth1Data),
        ('eth1_data_votes', CountableList(Eth1DataVote)),
    ]

    def __init__(
            self,
            *,
            # Misc
            slot: SlotNumber,
            genesis_time: Timestamp,
            fork: Fork,
            # Validator registry
            validator_registry: Sequence[ValidatorRecord],
            validator_balances: Sequence[Gwei],
            validator_registry_update_slot: SlotNumber,
            validator_registry_exit_count: int,
            validator_registry_delta_chain_tip: Hash32,
            # Randomness and committees
            latest_randao_mixes: Sequence[Hash32],
            latest_vdf_outputs: Sequence[Hash32],
            persistent_committees: Sequence[Sequence[ValidatorIndex]],
            persistent_committee_reassignments: Sequence[
                ShardReassignmentRecord],
            previous_epoch_start_shard: ShardNumber,
            current_epoch_start_shard: ShardNumber,
            previous_epoch_calculation_slot: SlotNumber,
            current_epoch_calculation_slot: SlotNumber,
            previous_epoch_randao_mix: Hash32,
            current_epoch_randao_mix: Hash32,
            # Custody challenges
            custody_challenges: Sequence[CustodyChallenge],
            # Finality
            previous_justified_slot: SlotNumber,
            justified_slot: SlotNumber,
            justification_bitfield: int,
            finalized_slot: SlotNumber,
            # Recent state
            latest_crosslinks: Sequence[CrosslinkRecord],
            latest_block_roots: Sequence[Hash32],
            latest_penalized_balances: Sequence[Gwei],
            batched_block_roots: Sequence[Hash32],
            latest_attestations: Sequence[PendingAttestationRecord],
            # Ethereum 1.0 chain
            latest_eth1_data: Eth1Data,
            eth1_data_votes: Sequence[Eth1DataVote]) -> None:
        if len(validator_registry) != len(validator_balances):
            raise ValueError(
                "The length of validator_registry and validator_balances should be the same."
            )
        super().__init__(
            # Misc
            slot=slot,
            genesis_time=genesis_time,
            fork=fork,
            # Validator registry
            validator_registry=validator_registry,
            validator_balances=validator_balances,
            validator_registry_update_slot=validator_registry_update_slot,
            validator_registry_exit_count=validator_registry_exit_count,
            validator_registry_delta_chain_tip=
            validator_registry_delta_chain_tip,
            # Randomness and committees
            latest_randao_mixes=latest_randao_mixes,
            latest_vdf_outputs=latest_vdf_outputs,
            persistent_committees=persistent_committees,
            persistent_committee_reassignments=
            persistent_committee_reassignments,
            previous_epoch_start_shard=previous_epoch_start_shard,
            current_epoch_start_shard=current_epoch_start_shard,
            previous_epoch_calculation_slot=previous_epoch_calculation_slot,
            current_epoch_calculation_slot=current_epoch_calculation_slot,
            previous_epoch_randao_mix=previous_epoch_randao_mix,
            current_epoch_randao_mix=current_epoch_randao_mix,
            # Proof of Custody
            custody_challenges=custody_challenges,
            # Finality
            previous_justified_slot=previous_justified_slot,
            justified_slot=justified_slot,
            justification_bitfield=justification_bitfield,
            finalized_slot=finalized_slot,
            # Recent state
            latest_crosslinks=latest_crosslinks,
            latest_block_roots=latest_block_roots,
            latest_penalized_balances=latest_penalized_balances,
            latest_attestations=latest_attestations,
            batched_block_roots=batched_block_roots,
            # Ethereum 1.0 chain
            latest_eth1_data=latest_eth1_data,
            eth1_data_votes=eth1_data_votes,
        )

    def __repr__(self) -> str:
        return 'BeaconState #{0}>'.format(encode_hex(self.root)[2:10], )

    _hash = None

    @property
    def hash(self) -> Hash32:
        if self._hash is None:
            self._hash = hash_eth2(rlp.encode(self))
        return self._hash

    @property
    def root(self) -> Hash32:
        # Alias of `hash`.
        # Using flat hash, might change to SSZ tree hash.
        return self.hash

    @property
    def num_validators(self) -> int:
        return len(self.validator_registry)

    @property
    def num_crosslinks(self) -> int:
        return len(self.latest_crosslinks)

    @classmethod
    def create_filled_state(
        cls,
        *,
        genesis_start_shard: ShardNumber,
        genesis_slot: SlotNumber,
        shard_count: int,
        latest_block_roots_length: int,
        latest_randao_mixes_length: int,
        latest_penalized_exit_length: int,
        activated_genesis_validators: Sequence[ValidatorRecord] = (),
        genesis_balances: Sequence[Gwei] = ()
    ) -> 'BeaconState':
        return cls(
            # Misc
            slot=genesis_slot,
            genesis_time=Timestamp(0),
            fork=Fork(
                previous_version=0,
                current_version=0,
                slot=genesis_slot,
            ),

            # Validator registry
            validator_registry=activated_genesis_validators,
            validator_balances=genesis_balances,
            validator_registry_update_slot=genesis_slot,
            validator_registry_exit_count=0,
            validator_registry_delta_chain_tip=ZERO_HASH32,

            # Randomness and committees
            latest_randao_mixes=tuple(
                ZERO_HASH32 for _ in range(latest_randao_mixes_length)),
            latest_vdf_outputs=(),
            persistent_committees=(),
            persistent_committee_reassignments=(),
            previous_epoch_start_shard=genesis_start_shard,
            current_epoch_start_shard=genesis_start_shard,
            previous_epoch_calculation_slot=genesis_slot,
            current_epoch_calculation_slot=genesis_slot,
            previous_epoch_randao_mix=ZERO_HASH32,
            current_epoch_randao_mix=ZERO_HASH32,

            # Custody challenges
            custody_challenges=(),

            # Finality
            previous_justified_slot=genesis_slot,
            justified_slot=genesis_slot,
            justification_bitfield=genesis_slot,
            finalized_slot=genesis_slot,

            # Recent state
            latest_crosslinks=tuple(
                CrosslinkRecord(
                    slot=genesis_slot,
                    shard_block_root=ZERO_HASH32,
                ) for _ in range(shard_count)),
            latest_block_roots=tuple(
                ZERO_HASH32 for _ in range(latest_block_roots_length)),
            latest_penalized_balances=(Gwei(0), ) *
            latest_penalized_exit_length,
            latest_attestations=(),
            batched_block_roots=(),

            # Ethereum 1.0 chain data
            latest_eth1_data=Eth1Data.create_empty_data(),
            eth1_data_votes=(),
        )

    def update_validator_registry(self, validator_index: ValidatorIndex,
                                  validator: ValidatorRecord) -> 'BeaconState':
        """
        Replace ``self.validator_registry[validator_index]`` with ``validator``.
        """
        if validator_index >= self.num_validators or validator_index < 0:
            raise IndexError("Incorrect validator index")

        validator_registry = list(self.validator_registry)
        validator_registry[validator_index] = validator

        updated_state = self.copy(
            validator_registry=tuple(validator_registry), )
        return updated_state

    def update_validator_balance(self, validator_index: ValidatorIndex,
                                 balance: Gwei) -> 'BeaconState':
        """
        Update the balance of validator of the given ``validator_index``.
        """
        if validator_index >= self.num_validators or validator_index < 0:
            raise IndexError("Incorrect validator index")

        validator_balances = list(self.validator_balances)
        validator_balances[validator_index] = balance

        updated_state = self.copy(
            validator_balances=tuple(validator_balances), )
        return updated_state

    def update_validator(self, validator_index: ValidatorIndex,
                         validator: ValidatorRecord,
                         balance: Gwei) -> 'BeaconState':
        """
        Update the ``ValidatorRecord`` and balance of validator of the given ``validator_index``.
        """
        state = self.update_validator_registry(validator_index, validator)
        state = state.update_validator_balance(validator_index, balance)
        return state
Exemple #17
0
class GetBlockTxnResponse(rlp.Serializable):
    fields = [("reqid", big_endian_int), ("block_hash", hash32),
              ("block_txn", CountableList(Transaction))]
Exemple #18
0
class BlockBody(rlp.Serializable):
    fields = [('transactions', CountableList(Transaction)),
              ('uncles', CountableList(BlockHeader))]
Exemple #19
0
class Log(rlp.Serializable):
    fields = [('address', Binary.fixed_length(20, allow_empty=True)),
              ('topics', CountableList(BigEndianInt(32))), ('data', Binary())]
Exemple #20
0
class FrontierBlock(BaseBlock):
    fields = [('header', BlockHeader),
              ('transactions', CountableList(FrontierTransaction)),
              ('uncles', CountableList(BlockHeader))]

    db = None
    bloom_filter = None

    def __init__(self, header, db, transactions=None, uncles=None):
        self.db = db

        if transactions is None:
            transactions = []
        if uncles is None:
            uncles = []

        self.bloom_filter = BloomFilter(header.bloom)
        self.transaction_db = Trie(db=self.db,
                                   root_hash=header.transaction_root)
        self.receipt_db = Trie(db=self.db, root_hash=header.receipt_root)

        super(FrontierBlock, self).__init__(
            header=header,
            transactions=transactions,
            uncles=uncles,
        )
        # TODO: should perform block validation at this point?

    def validate_gas_limit(self):
        gas_limit = self.header.gas_limit
        if gas_limit < GAS_LIMIT_MINIMUM:
            raise ValidationError("Gas limit {0} is below minimum {1}".format(
                gas_limit, GAS_LIMIT_MINIMUM))
        if gas_limit > GAS_LIMIT_MAXIMUM:
            raise ValidationError("Gas limit {0} is above maximum {1}".format(
                gas_limit, GAS_LIMIT_MAXIMUM))
        parent_gas_limit = self.get_parent_header().gas_limit
        diff = gas_limit - parent_gas_limit
        if diff > (parent_gas_limit // GAS_LIMIT_ADJUSTMENT_FACTOR):
            raise ValidationError(
                "Gas limit {0} difference to parent {1} is too big {2}".format(
                    gas_limit, parent_gas_limit, diff))

    def validate(self):
        if not self.is_genesis:
            parent_header = self.get_parent_header()

            self.validate_gas_limit()
            validate_length_lte(self.header.extra_data, 32)

            # timestamp
            if self.header.timestamp < parent_header.timestamp:
                raise ValidationError(
                    "`timestamp` is before the parent block's timestamp.\n"
                    "- block  : {0}\n"
                    "- parent : {1}. ".format(
                        self.header.timestamp,
                        parent_header.timestamp,
                    ))
            elif self.header.timestamp == parent_header.timestamp:
                raise ValidationError(
                    "`timestamp` is equal to the parent block's timestamp\n"
                    "- block : {0}\n"
                    "- parent: {1}. ".format(
                        self.header.timestamp,
                        parent_header.timestamp,
                    ))

        # XXX: Should these and some other checks be moved into
        # VM.validate_block(), as they apply to all block flavours?
        if len(self.uncles) > MAX_UNCLES:
            raise ValidationError(
                "Blocks may have a maximum of {0} uncles.  Found "
                "{1}.".format(MAX_UNCLES, len(self.uncles)))

        for uncle in self.uncles:
            self.validate_uncle(uncle)

        if self.header.state_root not in self.db:
            raise ValidationError("`state_root` was not found in the db.\n"
                                  "- state_root: {0}".format(
                                      self.header.state_root, ))
        local_uncle_hash = keccak(rlp.encode(self.uncles))
        if local_uncle_hash != self.header.uncles_hash:
            raise ValidationError(
                "`uncles_hash` and block `uncles` do not match.\n"
                " - num_uncles       : {0}\n"
                " - block uncle_hash : {1}\n"
                " - header uncle_hash: {2}".format(
                    len(self.uncles),
                    local_uncle_hash,
                    self.header.uncle_hash,
                ))

        super(FrontierBlock, self).validate()

    def validate_uncle(self, uncle):
        if uncle.block_number >= self.number:
            raise ValidationError(
                "Uncle number ({0}) is higher than block number ({1})".format(
                    uncle.block_number, self.number))
        try:
            uncle_parent = self.db.get(uncle.parent_hash)
        except KeyError:
            raise ValidationError("Uncle ancestor not found: {0}".format(
                uncle.parent_hash))
        parent_header = rlp.decode(uncle_parent, sedes=BlockHeader)
        if uncle.block_number != parent_header.block_number + 1:
            raise ValidationError(
                "Uncle number ({0}) is not one above ancestor's number ({1})".
                format(uncle.block_number, parent_header.block_number))
        if uncle.timestamp < parent_header.timestamp:
            raise ValidationError(
                "Uncle timestamp ({0}) is before ancestor's timestamp ({1})".
                format(uncle.timestamp, parent_header.timestamp))
        if uncle.gas_used > uncle.gas_limit:
            raise ValidationError(
                "Uncle's gas usage ({0}) is above the limit ({1})".format(
                    uncle.gas_used, uncle.gas_limit))

    #
    # Helpers
    #
    @property
    def number(self):
        return self.header.block_number

    @property
    def hash(self):
        return self.header.hash

    def get_parent_header(self):
        parent_header = rlp.decode(
            self.db.get(self.header.parent_hash),
            sedes=BlockHeader,
        )
        return parent_header

    #
    # Transaction class for this block class
    #
    transaction_class = FrontierTransaction

    @classmethod
    def get_transaction_class(cls):
        return cls.transaction_class

    #
    # Gas Usage API
    #
    def get_cumulative_gas_used(self):
        """
        Note return value of this function can be cached based on
        `self.receipt_db.root_hash`
        """
        if len(self.transactions):
            return self.receipts[-1].gas_used
        else:
            return 0

    #
    # Receipts API
    #
    @property
    def receipts(self):
        return get_receipts_from_db(self.receipt_db, Receipt)

    #
    # Header API
    #
    @classmethod
    def from_header(cls, header, db):
        """
        Returns the block denoted by the given block header.
        """
        if header.uncles_hash == EMPTY_UNCLE_HASH:
            uncles = []
        else:
            uncles = rlp.decode(
                db.get(header.uncles_hash),
                sedes=CountableList(BlockHeader),
            )

        transaction_db = Trie(db, root_hash=header.transaction_root)
        transactions = get_transactions_from_db(transaction_db,
                                                cls.get_transaction_class())

        return cls(
            header=header,
            transactions=transactions,
            uncles=uncles,
            db=db,
        )

    #
    # Execution API
    #
    def add_transaction(self, transaction, computation):
        logs = [
            Log(address, topics, data)
            for address, topics, data in computation.get_log_entries()
        ]

        if computation.error:
            tx_gas_used = transaction.gas
        else:
            gas_remaining = computation.get_gas_remaining()
            gas_refund = computation.get_gas_refund()
            tx_gas_used = (transaction.gas - gas_remaining) - min(
                gas_refund,
                (transaction.gas - gas_remaining) // 2,
            )

        gas_used = self.header.gas_used + tx_gas_used

        receipt = Receipt(
            state_root=self.header.state_root,
            gas_used=gas_used,
            logs=logs,
        )

        transaction_idx = len(self.transactions)

        index_key = rlp.encode(transaction_idx, sedes=rlp.sedes.big_endian_int)

        self.transactions.append(transaction)

        self.transaction_db[index_key] = rlp.encode(transaction)
        self.receipt_db[index_key] = rlp.encode(receipt)

        self.bloom_filter |= receipt.bloom

        self.header.transaction_root = self.transaction_db.root_hash
        self.header.receipt_root = self.receipt_db.root_hash
        self.header.bloom = int(self.bloom_filter)
        self.header.gas_used = gas_used

        return self

    def add_uncle(self, uncle):
        self.uncles.append(uncle)
        self.header.uncles_hash = keccak(rlp.encode(self.uncles))
        return self

    # TODO: Check with Piper what's the use case for having the mine() method allowing callsites
    # to override header attributes, since the only place it's used we don't pass any kwarg and
    # hence it just performs block-level validation.
    def mine(self, **kwargs):
        """
        - `uncles_hash`
        - `state_root`
        - `transaction_root`
        - `receipt_root`
        - `bloom`
        - `gas_used`
        - `extra_data`
        - `mix_hash`
        - `nonce`
        """
        if 'uncles' in kwargs:
            self.uncles = kwargs.pop('uncles')
            kwargs.setdefault('uncles_hash', keccak(rlp.encode(self.uncles)))

        header = self.header
        provided_fields = set(kwargs.keys())
        known_fields = set(tuple(zip(*BlockHeader.fields))[0])
        unknown_fields = provided_fields.difference(known_fields)

        if unknown_fields:
            raise AttributeError(
                "Unable to set the field(s) {0} on the `BlockHeader` class. "
                "Received the following unexpected fields: {0}.".format(
                    ", ".join(known_fields),
                    ", ".join(unknown_fields),
                ))

        for key, value in kwargs.items():
            setattr(header, key, value)

        # Perform validation
        self.validate()

        return self
Exemple #21
0
 def deserialize(cls, serial):
     return cls(block_hashes=CountableList(hash32).deserialize(serial))
Exemple #22
0
class BaseMessage():

    """Prefix for our message

    :\x55 is the multicodec tag for raw based
    :\x01 is the version number in unsigned varint
    """
    prefix = b'\x55\x01'

    authenticators_sedes = CountableList(raw)

    def __init__(self):
        """Initialization, BaseMessage shall NOT on wire

        should ONLY be called directly when parsing a frame
        """
        self.verified = False

    @property:
    def raw_auth(self):
        if not self.auth:
            auth = b''
        elif self.use_signature:
            auth = self.auth
        else:
            assert type(message.auth) is list
            auth = rlp.encode(message.auth,
                              cls.authenticators_sedes)

        return auth

    def authenticate(self, node):
        if self.use_signature:
            self.auth = node.principal.sign(self.content_digest)
        else:
            self.auth = node.gen_authenticators(self.content_digest)

        return self.auth

    def verify(self, node, peer_principal):
        pp = peer_principal

        if self.verified:
            pass
        elif self.use_signature:
            self.verified = pp.verify(self.content_digest, self.auth)
        else:
            if len(node.replica_principals) != len(self.auth):
                self.verified = False
            else:
                assert pp.index == self.sender
                self.verified = (pp.gen_hmac('in', self.content_digest)
                        == self.auth[node.sender]))
        
        return self.verified

    @property
    def tag(self):
        return MessageTag[type(self).__name__]

    @property
    def sender_type:
        if hasattr(self, 'extra'):
            return 'Replica' if (self.extra >> 4) & 1) else 'Client'
        else:
            return 'Replica'

    @property
    def frame_head(self):
        return (self.prefix
                + self.tag.to_bytes(1, byteorder='big'))
Exemple #23
0
 def deserialize(cls, serial):
     return cls(transactions=CountableList(Transaction).deserialize(serial))
Exemple #24
0
class FrontierBlock(BaseBlock):
    transaction_class = FrontierTransaction
    fields = [
        ('header', BlockHeader),
        ('transactions', CountableList(transaction_class)),
        ('uncles', CountableList(BlockHeader))
    ]

    bloom_filter = None

    def __init__(self, header, transactions=None, uncles=None):
        if transactions is None:
            transactions = []
        if uncles is None:
            uncles = []

        self.bloom_filter = BloomFilter(header.bloom)

        super(FrontierBlock, self).__init__(
            header=header,
            transactions=transactions,
            uncles=uncles,
        )
        # TODO: should perform block validation at this point?

    #
    # Helpers
    #
    @property
    def number(self):
        return self.header.block_number

    @property
    def hash(self):
        return self.header.hash

    #
    # Transaction class for this block class
    #
    @classmethod
    def get_transaction_class(cls):
        return cls.transaction_class

    #
    # Receipts API
    #
    def get_receipts(self, chaindb):
        return chaindb.get_receipts(self.header, Receipt)

    #
    # Header API
    #
    @classmethod
    def from_header(cls, header, chaindb):
        """
        Returns the block denoted by the given block header.
        """
        if header.uncles_hash == EMPTY_UNCLE_HASH:
            uncles = []  # type: List[bytes]
        else:
            uncles = chaindb.get_block_uncles(header.uncles_hash)

        transactions = chaindb.get_block_transactions(header, cls.get_transaction_class())

        return cls(
            header=header,
            transactions=transactions,
            uncles=uncles,
        )

    #
    # Execution API
    #
    def add_uncle(self, uncle):
        self.uncles.append(uncle)
        self.header.uncles_hash = keccak(rlp.encode(self.uncles))
        return self
Exemple #25
0
class TerminalBlockHashes(rlp.Serializable):
    fields = [
        ("reqid", big_endian_int),
        ("hashes", CountableList(hash32)),
    ]
Exemple #26
0
 def serialize(cls, obj):
     return CountableList(hash32).serialize(obj.block_hashes)
Exemple #27
0
class GetCompactBlocks(rlp.Serializable):
    fields = [
        ("reqid", big_endian_int),
        ("hashes", CountableList(hash32)),
    ]
Exemple #28
0
class BlockHeader(rlp.Serializable):
    fields = [
        ("parent_hash", binary),
        ("height", big_endian_int),
        ("timestamp", big_endian_int),
        ("author", binary),
        ("transactions_root", binary),
        ("deferred_state_root", binary),
        ("deferred_receipts_root", binary),
        ("deferred_logs_bloom_hash", binary),
        ("blame", big_endian_int),
        ("difficulty", big_endian_int),
        ("adaptive", big_endian_int),
        ("gas_limit", big_endian_int),
        ("referee_hashes", CountableList(binary)),
        ("nonce", big_endian_int),
    ]

    def __init__(
            self,
            parent_hash=default_config['GENESIS_PREVHASH'],
            height=0,
            timestamp=0,
            author=default_config['GENESIS_COINBASE'],
            transactions_root=trie.BLANK_ROOT,
            deferred_state_root=sha3(rlp.encode(trie.state_root())),
            deferred_receipts_root=trie.BLANK_ROOT,
            deferred_logs_bloom_hash=default_config['GENESIS_LOGS_BLOOM_HASH'],
            blame=0,
            difficulty=default_config['GENESIS_DIFFICULTY'],
            gas_limit=0,
            referee_hashes=[],
            adaptive=0,
            nonce=0):
        # at the beginning of a method, locals() is a dict of all arguments
        fields = {
            k: v
            for k, v in locals().items() if k not in ['self', '__class__']
        }
        self.block = None
        super(BlockHeader, self).__init__(**fields)

    @property
    def hash(self):
        return sha3(rlp.encode(self.rlp_part()))

    def get_hex_hash(self):
        return eth_utils.encode_hex(self.hash)

    def problem_hash(self):
        return sha3(rlp.encode(self.without_nonce()))

    def pow_decimal(self):
        return bytes_to_int(sha3(rlp.encode([self.problem_hash(),
                                             self.nonce])))

    def without_nonce(self):
        fields = {
            field: getattr(self, field)
            for field in BlockHeaderWithoutNonce._meta.field_names
        }
        return BlockHeaderWithoutNonce(**fields)

    def rlp_part(self):
        fields = {
            field: getattr(self, field)
            for field in BlockHeaderRlpPart._meta.field_names
        }
        return BlockHeaderRlpPart(**fields)
Exemple #29
0
class GetCompactBlocksResponse(rlp.Serializable):
    fields = [("reqid", big_endian_int),
              ("compact_blocks", CountableList(CompactBlock)),
              ("blocks", CountableList(Block))]
Exemple #30
0
class FrontierBlock(BaseBlock):
    transaction_builder = FrontierTransaction
    receipt_builder = Receipt
    fields = [
        ('header', BlockHeader),
        ('transactions', CountableList(transaction_builder)),
        ('uncles', CountableList(BlockHeader))
    ]

    bloom_filter = None

    def __init__(self,
                 header: BlockHeaderAPI,
                 transactions: Sequence[SignedTransactionAPI] = None,
                 uncles: Sequence[BlockHeaderAPI] = None) -> None:
        if transactions is None:
            transactions = []
        if uncles is None:
            uncles = []

        self.bloom_filter = BloomFilter(header.bloom)

        super().__init__(
            header=header,
            transactions=transactions,
            uncles=uncles,
        )
        # TODO: should perform block validation at this point?

    #
    # Helpers
    #
    @property
    def number(self) -> BlockNumber:
        return self.header.block_number

    @property
    def hash(self) -> Hash32:
        return self.header.hash

    #
    # Transaction class for this block class
    #
    @classmethod
    def get_transaction_builder(cls) -> Type[TransactionBuilderAPI]:
        return cls.transaction_builder

    @classmethod
    def get_receipt_builder(cls) -> Type[ReceiptBuilderAPI]:
        return cls.receipt_builder

    #
    # Receipts API
    #
    def get_receipts(self, chaindb: ChainDatabaseAPI) -> Tuple[ReceiptAPI, ...]:
        return chaindb.get_receipts(self.header, self.get_receipt_builder())

    #
    # Header API
    #
    @classmethod
    def from_header(cls, header: BlockHeaderAPI, chaindb: ChainDatabaseAPI) -> "FrontierBlock":
        """
        Returns the block denoted by the given block header.

        :raise eth.exceptions.BlockNotFound: if transactions or uncle headers are missing
        """
        if header.uncles_hash == EMPTY_UNCLE_HASH:
            uncles: Tuple[BlockHeaderAPI, ...] = ()
        else:
            try:
                uncles = chaindb.get_block_uncles(header.uncles_hash)
            except HeaderNotFound as exc:
                raise BlockNotFound(f"Uncles not found in database for {header}: {exc}") from exc

        try:
            transactions = chaindb.get_block_transactions(header, cls.get_transaction_builder())
        except MissingTrieNode as exc:
            raise BlockNotFound(f"Transactions not found in database for {header}: {exc}") from exc

        return cls(
            header=header,
            transactions=transactions,
            uncles=uncles,
        )