def sender(self): if not self._sender: # Determine sender if self.r == 0 and self.s == 0: self._sender = null_address else: if self.v in (27, 28): vee = self.v sighash = utils.sha3(rlp.encode(self, UnsignedTransaction)) elif self.v >= 37: vee = self.v - self.network_id * 2 - 8 assert vee in (27, 28) rlpdata = rlp.encode(rlp.infer_sedes(self).serialize(self)[ :-3] + [self.network_id, '', '']) sighash = utils.sha3(rlpdata) else: raise InvalidTransaction("Invalid V value") if self.r >= secpk1n or self.s >= secpk1n or self.r == 0 or self.s == 0: raise InvalidTransaction("Invalid signature values!") pub = ecrecover_to_pub(sighash, vee, self.r, self.s) if pub == b'\x00' * 64: raise InvalidTransaction( "Invalid signature (zero privkey cannot sign)") self._sender = utils.sha3(pub)[-20:] return self._sender
def sender(self): if not self._sender: # Determine sender if self.v: if self.r >= N or self.s >= N or self.v < 27 or self.v > 28 \ or self.r == 0 or self.s == 0: raise InvalidTransaction("Invalid signature values!") log.debug('recovering sender') rlpdata = rlp.encode(self, UnsignedTransaction) rawhash = utils.sha3(rlpdata) pk = PublicKey(flags=ALL_FLAGS) try: pk.public_key = pk.ecdsa_recover( rawhash, pk.ecdsa_recoverable_deserialize( zpad(utils.bytearray_to_bytestr(int_to_32bytearray(self.r)), 32) + zpad(utils.bytearray_to_bytestr(int_to_32bytearray(self.s)), 32), self.v - 27 ), raw=True ) pub = pk.serialize(compressed=False) except Exception: raise InvalidTransaction("Invalid signature values (x^3+7 is non-residue)") if pub[1:] == b"\x00" * 32: raise InvalidTransaction("Invalid signature (zero privkey cannot sign)") pub = encode_pubkey(pub, 'bin') self._sender = utils.sha3(pub[1:])[-20:] assert self.sender == self._sender else: self._sender = 0 return self._sender
def __init__(self, nonce, gasprice, startgas, to, value, data, v=0, r=0, s=0): self.data = None to = utils.normalize_address(to, allow_blank=True) assert len(to) == 20 or len(to) == 0 super(Transaction, self).__init__(nonce, gasprice, startgas, to, value, data, v, r, s) self.logs = [] if self.gasprice >= TT256 or self.startgas >= TT256 or \ self.value >= TT256 or self.nonce >= TT256: raise InvalidTransaction("Values way too high!") if self.startgas < self.intrinsic_gas_used: raise InvalidTransaction("Startgas too low") log.debug('deserialized tx', tx=encode_hex(self.hash)[:8])
def __init__(self, nonce, gasprice, startgas, to, value, data, v=0, r=0, s=0): if len(to) in (40, 48): to = decode_hex(to) if len(to) == 24: to = utils.check_and_strip_checksum(to) assert len(to) == 20 or len(to) == 0 super(Transaction, self).__init__(nonce, gasprice, startgas, to, value, data, v, r, s) self.logs = [] if self.gasprice >= TT256 or self.startgas >= TT256 or \ self.value >= TT256 or self.nonce >= TT256: raise InvalidTransaction("Values way too high!") if self.startgas < intrinsic_gas_used(self): raise InvalidTransaction("Startgas too low") log.debug('deserialized tx', tx=encode_hex(self.hash)[:8])
def __init__(self, nonce, gasprice, startgas, to, value, data, v=0, r=0, s=0, sender=None, network=None): # self.data = None to = utils.normalize_address(to, allow_blank=True) super(Transaction, self).__init__(nonce, gasprice, startgas, to, value, data, 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!") if sender: self._sender = bytes.fromhex(sender[2:]) if network: self.network = network
def config_fork_specific_validation(config, blknum, tx): # (1) The transaction signature is valid; _ = tx.sender 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 blknum >= config["SPURIOUS_DRAGON_FORK_BLKNUM"]: if tx.network_id not in (None, config["NETWORK_ID"]): raise InvalidTransaction("Wrong network ID") else: if tx.network_id is not None: raise InvalidTransaction("Wrong network ID") return True
def sign(self, key): """Sign this transaction with a private key. A potentially already existing signature would be overridden. """ if key in (0, '', '\x00' * 32): raise InvalidTransaction("Zero privkey cannot sign") rawhash = utils.sha3(rlp.encode(self, UnsignedTransaction)) self.v, self.r, self.s = ecdsa_raw_sign(rawhash, key) self.sender = utils.privtoaddr(key) return self
def sender(self): if not self._sender: # Determine sender if self.v: if self.r >= N or self.s >= P or self.v < 27 or self.v > 28 or self.r == 0 or self.s == 0: raise InvalidTransaction("Invalid signature values!") log.debug('recovering sender') rlpdata = rlp.encode(self, UnsignedTransaction) rawhash = utils.sha3(rlpdata) pub = ecdsa_raw_recover(rawhash, (self.v, self.r, self.s)) if pub is False: raise InvalidTransaction("Invalid signature values (x^3+7 is non-residue)") if pub == (0, 0): raise InvalidTransaction("Invalid signature (zero privkey cannot sign)") pub = encode_pubkey(pub, 'bin') self._sender = utils.sha3(pub[1:])[-20:] assert self.sender == self._sender else: self._sender = 0 return self._sender
def sender(self): if not self._sender: # Determine sender if self.v: if self.r >= N or self.s >= P or self.v < 27 or self.v > 28: raise InvalidTransaction("Invalid signature values!") log.debug('recovering sender') rlpdata = rlp.encode(self, UnsignedTransaction) rawhash = utils.sha3(rlpdata) pub = encode_pubkey( ecdsa_raw_recover(rawhash, (self.v, self.r, self.s)), 'bin') self._sender = utils.sha3(pub[1:])[-20:] assert self.sender == self._sender else: self._sender = 0 return self._sender
def __init__(self, nonce, gasprice, startgas, to, value, data, v=0, r=0, s=0): # self.data = None to = utils.normalize_address(to, allow_blank=True) super(Transaction, self).__init__(nonce, gasprice, startgas, to, value, data, 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 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; if tx.startgas < tx.intrinsic_gas_used: raise InsufficientStartGas( rp(tx, 'startgas', tx.startgas, tx.intrinsic_gas_used)) # (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) < total_cost: raise InsufficientBalance( rp(tx, 'balance', state.get_balance(tx.sender), 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 __init__(self, nonce, gasprice, startgas, to, value, data, v=0, r=0, s=0): if len(to) == 40: to = decode_hex(to) assert len(to) == 20 or len(to) == 0 super(Transaction, self).__init__(nonce, gasprice, startgas, to, value, data, v, r, s) self.logs = [] if self.gasprice >= TT256 or self.startgas >= TT256 or \ self.value >= TT256 or self.nonce >= TT256: raise InvalidTransaction("Values way too high!") log.debug('deserialized tx', tx=self.hash.encode('hex')[:8])
def sign(self, key): """Sign this transaction with a private key. A potentially already existing signature would be overridden. """ if key in (0, '', b'\x00' * 32, '0' * 64): raise InvalidTransaction("Zero privkey cannot sign") rawhash = utils.sha3(rlp.encode(self, UnsignedTransaction)) if len(key) == 64: # we need a binary key key = encode_privkey(key, 'bin') pk = PrivateKey(key, raw=True) signature = pk.ecdsa_recoverable_serialize( pk.ecdsa_sign_recoverable(rawhash, raw=True)) signature = signature[0] + utils.bytearray_to_bytestr([signature[1]]) self.v = utils.safe_ord(signature[64]) + 27 self.r = big_endian_to_int(signature[0:32]) self.s = big_endian_to_int(signature[32:64]) self.sender = utils.privtoaddr(key) return self
def check_low_s_homestead(self): if self.s > secpk1n // 2 or self.s == 0: raise InvalidTransaction("Invalid signature S value!")
def check_low_s_metropolis(self): if self.s > secpk1n // 2: raise InvalidTransaction("Invalid signature S value!")
def check_low_s(self): if self.s > N // 2 or self.s == 0: raise InvalidTransaction("Invalid signature S value!")