Beispiel #1
0
 def sender(self):
     if not self._sender:
         if self.r >= secpk1n or self.s >= secpk1n or self.r == 0 or self.s == 0:
             raise InvalidTransaction("Invalid signature values!")
         if self.version == 0:
             pub = ecrecover_to_pub(self.hash_unsigned, self.v, self.r,
                                    self.s)
         if self.version == 1:
             pub = ecrecover_to_pub(self.hash_typed, self.v, self.r, self.s)
         if pub == b"\x00" * 64:
             raise InvalidTransaction(
                 "Invalid signature (zero privkey cannot sign)")
         self._sender = sha3_256(pub)[-20:]
     return self._sender
Beispiel #2
0
def config_fork_specific_validation(config, blknum, tx):
    # (1) The transaction signature is valid;
    _ = tx.sender
    if _ is None:
        pass
    if blknum >= config["CONSTANTINOPLE_FORK_BLKNUM"]:
        tx.check_low_s_metropolis()
    else:
        if tx.sender == null_address:
            raise InvalidTransaction("EIP86 transactions not available yet")
        if blknum >= config["HOMESTEAD_FORK_BLKNUM"]:
            tx.check_low_s_homestead()

    if tx.network_id != config["NETWORK_ID"]:
        raise InvalidTransaction("Wrong network ID")
    return True
Beispiel #3
0
    def __init__(self, nonce, gasprice, startgas, to, value, data,
                 v=0, r=0, s=0, from_full_shard_id=0, to_full_shard_id=0, network_id=1, version=0):
        self.data = None
        self.shard_size = 0

        to = utils.normalize_address(to, allow_blank=True)

        super(
            Transaction,
            self).__init__(
            nonce,
            gasprice,
            startgas,
            to,
            value,
            data,
            from_full_shard_id,
            to_full_shard_id,
            network_id,
            version,
            v,
            r,
            s)

        if self.gasprice >= TT256 or self.startgas >= TT256 or \
                self.value >= TT256 or self.nonce >= TT256:
            raise InvalidTransaction("Values way too high!")
 def sender(self):
     if not self._sender:
         if self.r >= secpk1n or self.s >= secpk1n or self.r == 0 or self.s == 0:
             raise InvalidTransaction("Invalid signature values!")
         if self.version == 0:
             pub = ecrecover_to_pub(self.hash_unsigned, self.v, self.r,
                                    self.s)
         if self.version == 1:
             pub = ecrecover_to_pub(self.hash_typed, self.v, self.r, self.s)
         if self.version == 2:
             v = 35 - 27 + self.network_id * 2
             if self.v < v:
                 raise InvalidTransaction(
                     "Invalid signature (wrong v with tx version = 2)")
             v = self.v - v
             pub = ecrecover_to_pub(self.hash_unsigned, v, self.r, self.s)
         if pub == b"\x00" * 64:
             raise InvalidTransaction(
                 "Invalid signature (zero privkey cannot sign)")
         self._sender = sha3_256(pub)[-20:]
     return self._sender
    def __init__(
        self,
        nonce,
        gasprice,
        startgas,
        to,
        value,
        data,
        gas_token_id,
        transfer_token_id,
        v=0,
        r=0,
        s=0,
        from_full_shard_key=0,
        to_full_shard_key=0,
        network_id=1,
        version=0,
        is_testing=False,
    ):
        self.quark_chain_config = None
        self.is_testing = is_testing

        to = utils.normalize_address(to, allow_blank=True)

        super(Transaction, self).__init__(
            nonce,
            gasprice,
            startgas,
            to,
            value,
            data,
            network_id,
            from_full_shard_key,
            to_full_shard_key,
            gas_token_id,
            transfer_token_id,
            version,
            v,
            r,
            s,
        )

        if (self.gasprice >= TT256 or self.startgas >= TT256
                or self.value >= TT256 or self.nonce >= TT256
                or self.version >= TT256 or self.gas_token_id > TOKEN_ID_MAX
                or self.transfer_token_id > TOKEN_ID_MAX
                or self.from_full_shard_key > SHARD_KEY_MAX
                or self.to_full_shard_key > SHARD_KEY_MAX):
            raise InvalidTransaction("Values way too high!")
Beispiel #6
0
    def __init__(
        self,
        nonce,
        gasprice,
        startgas,
        to,
        value,
        data,
        v=0,
        r=0,
        s=0,
        from_full_shard_key=0,
        to_full_shard_key=0,
        network_id=1,
        version=0,
    ):
        self.quark_chain_config = None

        to = utils.normalize_address(to, allow_blank=True)

        super(Transaction, self).__init__(
            nonce,
            gasprice,
            startgas,
            to,
            value,
            data,
            from_full_shard_key,
            to_full_shard_key,
            network_id,
            version,
            v,
            r,
            s,
        )

        if (
            self.gasprice >= TT256
            or self.startgas >= TT256
            or self.value >= TT256
            or self.nonce >= TT256
        ):
            raise InvalidTransaction("Values way too high!")
Beispiel #7
0
def validate_transaction(state, tx):

    # (1) The transaction signature is valid;
    if not tx.sender:  # sender is set and validated on Transaction initialization
        raise UnsignedTransaction(tx)

    # assert config_fork_specific_validation(
    #     state.config, state.block_number, tx)

    # (2) the transaction nonce is valid (equivalent to the
    #     sender account's current nonce);
    req_nonce = 0 if tx.sender == null_address else state.get_nonce(tx.sender)
    if req_nonce != tx.nonce:
        raise InvalidNonce(rp(tx, "nonce", tx.nonce, req_nonce))

    # (3) the gas limit is no smaller than the intrinsic gas,
    # g0, used by the transaction;
    total_gas = tx.intrinsic_gas_used
    if tx.startgas < total_gas:
        raise InsufficientStartGas(rp(tx, "startgas", tx.startgas, total_gas))

    # (4) the sender account balance contains at least the
    # cost, v0, required in up-front payment.
    total_cost = tx.value + tx.gasprice * tx.startgas

    if state.get_balance(tx.sender, tx.gas_token_id) < total_cost:
        raise InsufficientBalance(
            rp(tx, "balance", state.get_balance(tx.sender, tx.gas_token_id),
               total_cost))

    # check block gas limit
    if state.gas_used + tx.startgas > state.gas_limit:
        raise BlockGasLimitReached(
            rp(tx, "gaslimit", state.gas_used + tx.startgas, state.gas_limit))

    # EIP86-specific restrictions
    if tx.sender == null_address and (tx.value != 0 or tx.gasprice != 0):
        raise InvalidTransaction(
            "EIP86 transactions must have 0 value and gasprice")

    return True
    def sign(self, key, network_id=None):
        """Sign this transaction with a private key.

        A potentially already existing signature would be overridden.
        """
        if network_id is not None:
            self.network_id = network_id
        key = normalize_key(key)

        self._in_mutable_context = True

        if self.version == 0:
            self.v, self.r, self.s = ecsign(self.hash_unsigned, key)
        if self.version == 1:
            self.v, self.r, self.s = ecsign(self.hash_typed, key)
        if self.version == 2:
            self.v, self.r, self.s = ecsign(self.hash_unsigned, key)
            self.v = self.v + 35 - 27 + self.network_id * 2
        if self.version > 2:
            raise InvalidTransaction("Invalid transaction version.")
        self._in_mutable_context = False

        self._sender = utils.privtoaddr(key)
        return self
Beispiel #9
0
 def check_low_s_homestead(self):
     if self.s > secpk1n // 2 or self.s == 0:
         raise InvalidTransaction("Invalid signature S value!")
Beispiel #10
0
 def check_low_s_metropolis(self):
     if self.s > secpk1n // 2:
         raise InvalidTransaction("Invalid signature S value!")
Beispiel #11
0
def validate_transaction(state, tx):
    # (1) The transaction signature is valid;
    if not tx.sender:  # sender is set and validated on Transaction initialization
        raise UnsignedTransaction(tx)

    if tx.version == 2:
        # When tx.version == 2 (EIP155 tx), check
        # 0. EIP155_SIGNER enable
        # 1. tx.v == tx.network_id * 2 + 35 (+ 1)
        # 2. gas_token_id & transfer_token_id should equal to default_token_id (like qkc)
        # 3. tx.from_chain_id == tx.to_chain_id and tx.from_shard_key = 0 & tx.to_shard_key = 0
        # 4. tx.network_id == chain_config.ETH_CHAIN_ID, where chain_config is derived from tx.from_chain_id
        chain_config = state.qkc_config.CHAINS[tx.from_chain_id]
        default_token_id = token_id_encode(chain_config.DEFAULT_CHAIN_TOKEN)
        if (state.qkc_config.ENABLE_EIP155_SIGNER_TIMESTAMP is not None
                and state.timestamp <
                state.qkc_config.ENABLE_EIP155_SIGNER_TIMESTAMP):
            raise InvalidTransaction("EIP155 Signer is not enable yet.")
        if tx.v != 35 + tx.network_id * 2 and tx.v != 36 + tx.network_id * 2:
            raise InvalidTransaction(
                "network_id {} does not match the signature v {}.".format(
                    tx.network_id, tx.v))
        if tx.from_chain_id != tx.to_chain_id:
            raise InvalidTransaction(
                "EIP155 Signer do not support cross shard transaction.")
        if tx.from_shard_key != 0 or tx.to_shard_key != 0:
            raise InvalidTransaction(
                "EIP155 Signer do not support cross shard transaction.")
        if tx.gas_token_id != default_token_id:
            raise InvalidTransaction(
                "EIP155 Signer only support {} as gas token.".format(
                    chain_config.DEFAULT_CHAIN_TOKEN))
        if tx.transfer_token_id != default_token_id:
            raise InvalidTransaction(
                "EIP155 Signer only support {} as transfer token.".format(
                    chain_config.DEFAULT_CHAIN_TOKEN))
        assert (tx.network_id == chain_config.ETH_CHAIN_ID,
                "Invalid network_id.")
        assert (
            tx.eth_chain_id - state.qkc_config.BASE_ETH_CHAIN_ID -
            1 == tx.from_chain_id,
            "Invalid Eth_Chain_Id.",
        )

    # (1a) startgas, gasprice, gas token id, transfer token id must be <= UINT128_MAX
    if (tx.startgas > UINT128_MAX or tx.gasprice > UINT128_MAX
            or tx.gas_token_id > TOKEN_ID_MAX
            or tx.transfer_token_id > TOKEN_ID_MAX):
        raise InvalidTransaction(
            "startgas, gasprice, and token_id must <= UINT128_MAX")

    # (2) the transaction nonce is valid (equivalent to the
    #     sender account's current nonce);
    req_nonce = state.get_nonce(tx.sender)
    if req_nonce != tx.nonce:
        raise InvalidNonce(rp(tx, "nonce", tx.nonce, req_nonce))

    # (3) the gas limit is no smaller than the intrinsic gas,
    # g0, used by the transaction;
    total_gas = tx.intrinsic_gas_used
    if tx.startgas < total_gas:
        raise InsufficientStartGas(rp(tx, "startgas", tx.startgas, total_gas))

    default_chain_token = state.shard_config.default_chain_token
    bal = {
        tx.transfer_token_id: state.get_balance(tx.sender,
                                                tx.transfer_token_id)
    }
    if tx.transfer_token_id != tx.gas_token_id:
        bal[tx.gas_token_id] = state.get_balance(tx.sender, tx.gas_token_id)

    # (4) requires non-zero balance for transfer_token_id and gas_token_id if non-default
    for token_id in [tx.transfer_token_id, tx.gas_token_id]:
        if token_id != default_chain_token and bal[token_id] == 0:
            raise InvalidNativeToken(
                "{}: non-default token {} has zero balance".format(
                    tx.__repr__(), token_id_decode(token_id)))

    # (5) the sender account balance contains at least the cost required in up-front payment
    cost = Counter({tx.transfer_token_id: tx.value}) + Counter(
        {tx.gas_token_id: tx.gasprice * tx.startgas})
    for token_id, b in bal.items():
        if b < cost[token_id]:
            raise InsufficientBalance(
                rp(
                    tx,
                    "token %s balance" % token_id_decode(token_id),
                    b,
                    cost[token_id],
                ))

    # (6) if gas token non-default, need to check system contract for gas conversion
    if tx.gasprice != 0 and tx.gas_token_id != default_chain_token:
        snapshot = state.snapshot()
        _, genesis_token_gas_price = pay_native_token_as_gas(
            state, tx.gas_token_id, tx.startgas, tx.gasprice)
        state.revert(snapshot)
        if genesis_token_gas_price == 0:
            raise InvalidNativeToken(
                "{}: non-default gas token {} not ready for being used to pay gas"
                .format(tx.__repr__(), token_id_decode(tx.gas_token_id)))
        # should be guaranteed by previous check. check added to make sure
        bal_gas_reserve = state.get_balance(
            SystemContract.GENERAL_NATIVE_TOKEN.addr(), state.genesis_token)
        if bal_gas_reserve < genesis_token_gas_price * tx.startgas:
            raise InvalidNativeToken(
                "{}: non-default gas token {} not enough reserve balance for conversion"
                .format(tx.__repr__(), token_id_decode(tx.gas_token_id)))

    # (7) check block gas limit
    if state.gas_used + tx.startgas > state.gas_limit:
        raise BlockGasLimitReached(
            rp(tx, "gaslimit", state.gas_used + tx.startgas, state.gas_limit))

    return True
Beispiel #12
0
def validate_transaction(state, tx):
    # (1) The transaction signature is valid;
    if not tx.sender:  # sender is set and validated on Transaction initialization
        raise UnsignedTransaction(tx)

    # (1a) startgas, gasprice, gas token id, transfer token id must be <= UINT128_MAX
    if (tx.startgas > UINT128_MAX or tx.gasprice > UINT128_MAX
            or tx.gas_token_id > TOKEN_ID_MAX
            or tx.transfer_token_id > TOKEN_ID_MAX):
        raise InvalidTransaction(
            "startgas, gasprice, and token_id must <= UINT128_MAX")

    # (2) the transaction nonce is valid (equivalent to the
    #     sender account's current nonce);
    req_nonce = state.get_nonce(tx.sender)
    if req_nonce != tx.nonce:
        raise InvalidNonce(rp(tx, "nonce", tx.nonce, req_nonce))

    # (3) the gas limit is no smaller than the intrinsic gas,
    # g0, used by the transaction;
    total_gas = tx.intrinsic_gas_used
    if tx.startgas < total_gas:
        raise InsufficientStartGas(rp(tx, "startgas", tx.startgas, total_gas))

    default_chain_token = state.shard_config.default_chain_token
    bal = {
        tx.transfer_token_id: state.get_balance(tx.sender,
                                                tx.transfer_token_id)
    }
    if tx.transfer_token_id != tx.gas_token_id:
        bal[tx.gas_token_id] = state.get_balance(tx.sender, tx.gas_token_id)

    # (4) requires non-zero balance for transfer_token_id and gas_token_id if non-default
    for token_id in [tx.transfer_token_id, tx.gas_token_id]:
        if token_id != default_chain_token and bal[token_id] == 0:
            raise InvalidNativeToken(
                "{}: non-default token {} has zero balance".format(
                    tx.__repr__(), token_id_decode(token_id)))

    # (5) the sender account balance contains at least the cost required in up-front payment
    cost = Counter({tx.transfer_token_id: tx.value}) + Counter(
        {tx.gas_token_id: tx.gasprice * tx.startgas})
    for token_id, b in bal.items():
        if b < cost[token_id]:
            raise InsufficientBalance(
                rp(
                    tx,
                    "token %s balance" % token_id_decode(token_id),
                    b,
                    cost[token_id],
                ))

    # (6) if gas token non-default, need to check system contract for gas conversion
    if tx.gasprice != 0 and tx.gas_token_id != default_chain_token:
        snapshot = state.snapshot()
        _, genesis_token_gas_price = pay_native_token_as_gas(
            state, tx.gas_token_id, tx.startgas, tx.gasprice)
        state.revert(snapshot)
        if genesis_token_gas_price == 0:
            raise InvalidNativeToken(
                "{}: non-default gas token {} not ready for being used to pay gas"
                .format(tx.__repr__(), token_id_decode(tx.gas_token_id)))
        # should be guaranteed by previous check. check added to make sure
        bal_gas_reserve = state.get_balance(
            SystemContract.GENERAL_NATIVE_TOKEN.addr(), state.genesis_token)
        if bal_gas_reserve < genesis_token_gas_price * tx.startgas:
            raise InvalidNativeToken(
                "{}: non-default gas token {} not enough reserve balance for conversion"
                .format(tx.__repr__(), token_id_decode(tx.gas_token_id)))

    # (7) check block gas limit
    if state.gas_used + tx.startgas > state.gas_limit:
        raise BlockGasLimitReached(
            rp(tx, "gaslimit", state.gas_used + tx.startgas, state.gas_limit))

    return True
Beispiel #13
0
def validate_transaction(state, tx):

    # (1) The transaction signature is valid;
    if not tx.sender:  # sender is set and validated on Transaction initialization
        raise UnsignedTransaction(tx)

    # (2) the transaction nonce is valid (equivalent to the
    #     sender account's current nonce);
    req_nonce = 0 if tx.sender == null_address else state.get_nonce(tx.sender)
    if req_nonce != tx.nonce:
        raise InvalidNonce(rp(tx, "nonce", tx.nonce, req_nonce))

    # (3) the gas limit is no smaller than the intrinsic gas,
    # g0, used by the transaction;
    total_gas = tx.intrinsic_gas_used
    if tx.startgas < total_gas:
        raise InsufficientStartGas(rp(tx, "startgas", tx.startgas, total_gas))

    # (4.0) require transfer_token_id and gas_token_id to be in allowed list
    if tx.transfer_token_id not in state.qkc_config.allowed_transfer_token_ids:
        raise InsufficientBalance(
            "{}: token {} is not in allowed transfer_token list".format(
                tx.__repr__(), token_id_decode(tx.transfer_token_id)))
    if tx.gas_token_id not in state.qkc_config.allowed_gas_token_ids:
        raise InsufficientBalance(
            "{}: token {} is not in allowed gas_token list".format(
                tx.__repr__(), token_id_decode(tx.gas_token_id)))

    # (4) the sender account balance contains at least the
    # cost, v0, required in up-front payment.
    if tx.transfer_token_id == tx.gas_token_id:
        total_cost = tx.value + tx.gasprice * tx.startgas
        if state.get_balance(tx.sender,
                             token_id=tx.transfer_token_id) < total_cost:
            raise InsufficientBalance(
                rp(
                    tx,
                    "token %d balance" % tx.transfer_token_id,
                    state.get_balance(tx.sender,
                                      token_id=tx.transfer_token_id),
                    total_cost,
                ))
    else:
        if state.get_balance(tx.sender,
                             token_id=tx.transfer_token_id) < tx.value:
            raise InsufficientBalance(
                rp(
                    tx,
                    "token %d balance" % tx.transfer_token_id,
                    state.get_balance(tx.sender,
                                      token_id=tx.transfer_token_id),
                    tx.value,
                ))
        if (state.get_balance(tx.sender, token_id=tx.gas_token_id) <
                tx.gasprice * tx.startgas):
            raise InsufficientBalance(
                rp(
                    tx,
                    "token %d balance" % tx.gas_token_id,
                    state.get_balance(tx.sender, token_id=tx.gas_token_id),
                    tx.gasprice * tx.startgas,
                ))

    # check block gas limit
    if state.gas_used + tx.startgas > state.gas_limit:
        raise BlockGasLimitReached(
            rp(tx, "gaslimit", state.gas_used + tx.startgas, state.gas_limit))

    # EIP86-specific restrictions
    if tx.sender == null_address and (tx.value != 0 or tx.gasprice != 0):
        raise InvalidTransaction(
            "EIP86 transactions must have 0 value and gasprice")

    return True