2018-04-06 14:52:10 +00:00
|
|
|
# Nimbus
|
|
|
|
# Copyright (c) 2018 Status Research & Development GmbH
|
|
|
|
# Licensed under either of
|
|
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
|
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
|
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
|
2018-01-17 12:57:50 +00:00
|
|
|
import
|
2018-09-05 23:48:06 +00:00
|
|
|
constants, errors, eth_common, eth_keys, nimcrypto, rlp
|
2018-01-17 12:57:50 +00:00
|
|
|
|
2018-08-24 15:46:48 +00:00
|
|
|
proc intrinsicGas*(t: Transaction): GasInt =
|
2018-01-17 12:57:50 +00:00
|
|
|
# Compute the baseline gas cost for this transaction. This is the amount
|
|
|
|
# of gas needed to send this transaction (but that is not actually used
|
|
|
|
# for computation)
|
|
|
|
raise newException(ValueError, "not implemented intrinsicGas")
|
|
|
|
|
2018-08-24 15:46:48 +00:00
|
|
|
proc validate*(t: Transaction) =
|
2018-01-17 12:57:50 +00:00
|
|
|
# Hook called during instantiation to ensure that all transaction
|
|
|
|
# parameters pass validation rules
|
2018-08-24 15:46:48 +00:00
|
|
|
if t.intrinsicGas() > t.gasLimit:
|
2018-01-17 12:57:50 +00:00
|
|
|
raise newException(ValidationError, "Insufficient gas")
|
|
|
|
# self.check_signature_validity()
|
2018-01-17 14:16:00 +00:00
|
|
|
|
2018-09-05 23:48:06 +00:00
|
|
|
func rlpEncode*(transaction: Transaction): auto =
|
|
|
|
# Encode transaction without signature
|
2018-08-24 15:46:48 +00:00
|
|
|
type
|
|
|
|
TransHashObj = object
|
2018-08-31 17:37:26 +00:00
|
|
|
accountNonce: AccountNonce
|
2018-08-24 15:46:48 +00:00
|
|
|
gasPrice: GasInt
|
|
|
|
gasLimit: GasInt
|
|
|
|
to: EthAddress
|
|
|
|
value: UInt256
|
|
|
|
payload: Blob
|
2018-09-05 23:48:06 +00:00
|
|
|
return rlp.encode(TransHashObj(
|
2018-08-24 15:46:48 +00:00
|
|
|
accountNonce: transaction.accountNonce,
|
|
|
|
gasPrice: transaction.gasPrice,
|
|
|
|
gasLimit: transaction.gasLimit,
|
|
|
|
to: transaction.to,
|
|
|
|
value: transaction.value,
|
|
|
|
payload: transaction.payload
|
2018-09-05 23:48:06 +00:00
|
|
|
))
|
|
|
|
|
|
|
|
func hash*(transaction: Transaction): Hash256 =
|
|
|
|
# Hash transaction without signature
|
|
|
|
return keccak256.digest(transaction.rlpEncode.toOpenArray)
|
2018-08-24 15:46:48 +00:00
|
|
|
|
|
|
|
proc toSignature*(transaction: Transaction): Signature =
|
|
|
|
var bytes: array[65, byte]
|
|
|
|
bytes[0..31] = transaction.R.toByteArrayBE()
|
|
|
|
bytes[32..63] = transaction.S.toByteArrayBE()
|
|
|
|
# TODO: V will become a byte or range soon.
|
2018-08-31 14:15:31 +00:00
|
|
|
bytes[64] = transaction.V
|
2018-08-24 15:46:48 +00:00
|
|
|
initSignature(bytes)
|
|
|
|
|
|
|
|
proc getSender*(transaction: Transaction, output: var EthAddress): bool =
|
|
|
|
## Find the address the transaction was sent from.
|
|
|
|
let
|
|
|
|
txHash = transaction.hash # hash without signature
|
|
|
|
sig = transaction.toSignature()
|
|
|
|
var pubKey: PublicKey
|
2018-08-24 17:34:54 +00:00
|
|
|
if recoverSignatureKey(sig, txHash.data, pubKey) == EthKeysStatus.Success:
|
2018-08-24 15:46:48 +00:00
|
|
|
output = pubKey.toCanonicalAddress()
|
|
|
|
result = true
|
|
|
|
|
2018-08-29 15:52:12 +00:00
|
|
|
proc getSender*(transaction: Transaction): EthAddress =
|
|
|
|
## Raises error on failure to recover public key
|
|
|
|
if not transaction.getSender(result):
|
|
|
|
raise newException(ValidationError, "Could not derive sender address from transaction")
|