mirror of https://github.com/status-im/nim-eth.git
define Electra types and RLP encoding (#711)
Add types for EIP-6110, EIP-7002 and EIP-7251 validator operations.
This commit is contained in:
parent
b90483e9d2
commit
d8fda55c79
|
@ -23,6 +23,11 @@ export
|
||||||
eth_hash,
|
eth_hash,
|
||||||
eth_times
|
eth_times
|
||||||
|
|
||||||
|
const
|
||||||
|
DEPOSIT_REQUEST_TYPE* = 0x00'u8 # EIP-6110
|
||||||
|
WITHDRAWAL_REQUEST_TYPE* = 0x01'u8 # EIP-7002
|
||||||
|
CONSOLIDATION_REQUEST_TYPE* = 0x02'u8 # EIP-7251
|
||||||
|
|
||||||
type
|
type
|
||||||
Hash256* = MDigest[256]
|
Hash256* = MDigest[256]
|
||||||
VMWord* = UInt256
|
VMWord* = UInt256
|
||||||
|
@ -124,6 +129,23 @@ type
|
||||||
address* : EthAddress
|
address* : EthAddress
|
||||||
amount* : uint64
|
amount* : uint64
|
||||||
|
|
||||||
|
DepositRequest* = object # EIP-6110
|
||||||
|
pubkey* : array[48, byte]
|
||||||
|
withdrawalCredentials*: array[32, byte]
|
||||||
|
amount* : uint64
|
||||||
|
signature* : array[96, byte]
|
||||||
|
index* : uint64
|
||||||
|
|
||||||
|
WithdrawalRequest* = object # EIP-7002
|
||||||
|
sourceAddress* : array[20, byte]
|
||||||
|
validatorPubkey*: array[48, byte]
|
||||||
|
amount* : uint64
|
||||||
|
|
||||||
|
ConsolidationRequest* = object # EIP-7251
|
||||||
|
sourceAddress*: array[20, byte]
|
||||||
|
sourcePubkey* : array[48, byte]
|
||||||
|
targetPubkey* : array[48, byte]
|
||||||
|
|
||||||
# https://eips.ethereum.org/EIPS/eip-4844#header-extension
|
# https://eips.ethereum.org/EIPS/eip-4844#header-extension
|
||||||
BlockHeader* = object
|
BlockHeader* = object
|
||||||
parentHash*: Hash256
|
parentHash*: Hash256
|
||||||
|
@ -146,6 +168,7 @@ type
|
||||||
blobGasUsed*: Opt[uint64] # EIP-4844
|
blobGasUsed*: Opt[uint64] # EIP-4844
|
||||||
excessBlobGas*: Opt[uint64] # EIP-4844
|
excessBlobGas*: Opt[uint64] # EIP-4844
|
||||||
parentBeaconBlockRoot*: Opt[Hash256] # EIP-4788
|
parentBeaconBlockRoot*: Opt[Hash256] # EIP-4788
|
||||||
|
requestsRoot*: Opt[Hash256] # EIP-7685
|
||||||
|
|
||||||
BlockBody* = object
|
BlockBody* = object
|
||||||
transactions*: seq[Transaction]
|
transactions*: seq[Transaction]
|
||||||
|
|
|
@ -527,6 +527,85 @@ proc read*(rlp: var Rlp, T: type HashOrNum): T =
|
||||||
proc append*(rlpWriter: var RlpWriter, t: EthTime) {.inline.} =
|
proc append*(rlpWriter: var RlpWriter, t: EthTime) {.inline.} =
|
||||||
rlpWriter.append(t.uint64)
|
rlpWriter.append(t.uint64)
|
||||||
|
|
||||||
|
proc append*(rlpWriter: var RlpWriter, request: DepositRequest) =
|
||||||
|
rlpWriter.appendRawBytes([DEPOSIT_REQUEST_TYPE])
|
||||||
|
rlpWriter.startList(5)
|
||||||
|
rlpWriter.append(request.pubkey)
|
||||||
|
rlpWriter.append(request.withdrawalCredentials)
|
||||||
|
rlpWriter.append(request.amount)
|
||||||
|
rlpWriter.append(request.signature)
|
||||||
|
rlpWriter.append(request.index)
|
||||||
|
|
||||||
|
proc read*(rlp: var Rlp, T: type DepositRequest): T =
|
||||||
|
if not rlp.hasData:
|
||||||
|
raise (ref MalformedRlpError)(msg:
|
||||||
|
"DEPOSIT_REQUEST_TYPE expected but source RLP is empty")
|
||||||
|
let reqType = rlp.readRawByte()
|
||||||
|
if reqType != DEPOSIT_REQUEST_TYPE:
|
||||||
|
raise (ref UnsupportedRlpError)(msg:
|
||||||
|
"Unexpected DEPOSIT_REQUEST_TYPE: " & $reqType)
|
||||||
|
|
||||||
|
var res: DepositRequest
|
||||||
|
rlp.tryEnterList()
|
||||||
|
rlp.read(res.pubkey)
|
||||||
|
rlp.read(res.withdrawalCredentials)
|
||||||
|
rlp.read(res.amount)
|
||||||
|
rlp.read(res.signature)
|
||||||
|
rlp.read(res.index)
|
||||||
|
if rlp.hasData:
|
||||||
|
raise (ref MalformedRlpError)(msg: "Extra data after DepositRequest")
|
||||||
|
res
|
||||||
|
|
||||||
|
proc append*(rlpWriter: var RlpWriter, request: WithdrawalRequest) =
|
||||||
|
rlpWriter.appendRawBytes([WITHDRAWAL_REQUEST_TYPE])
|
||||||
|
rlpWriter.startList(3)
|
||||||
|
rlpWriter.append(request.sourceAddress)
|
||||||
|
rlpWriter.append(request.validatorPubkey)
|
||||||
|
rlpWriter.append(request.amount)
|
||||||
|
|
||||||
|
proc read*(rlp: var Rlp, T: type WithdrawalRequest): T =
|
||||||
|
if not rlp.hasData:
|
||||||
|
raise (ref MalformedRlpError)(msg:
|
||||||
|
"WITHDRAWAL_REQUEST_TYPE expected but source RLP is empty")
|
||||||
|
let reqType = rlp.readRawByte()
|
||||||
|
if reqType != WITHDRAWAL_REQUEST_TYPE:
|
||||||
|
raise (ref UnsupportedRlpError)(msg:
|
||||||
|
"Unexpected WITHDRAWAL_REQUEST_TYPE: " & $reqType)
|
||||||
|
|
||||||
|
var res: WithdrawalRequest
|
||||||
|
rlp.tryEnterList()
|
||||||
|
rlp.read(res.sourceAddress)
|
||||||
|
rlp.read(res.validatorPubkey)
|
||||||
|
rlp.read(res.amount)
|
||||||
|
if rlp.hasData:
|
||||||
|
raise (ref MalformedRlpError)(msg: "Extra data after WithdrawalRequest")
|
||||||
|
res
|
||||||
|
|
||||||
|
proc append*(rlpWriter: var RlpWriter, request: ConsolidationRequest) =
|
||||||
|
rlpWriter.appendRawBytes([CONSOLIDATION_REQUEST_TYPE])
|
||||||
|
rlpWriter.startList(3)
|
||||||
|
rlpWriter.append(request.sourceAddress)
|
||||||
|
rlpWriter.append(request.sourcePubkey)
|
||||||
|
rlpWriter.append(request.targetPubkey)
|
||||||
|
|
||||||
|
proc read*(rlp: var Rlp, T: type ConsolidationRequest): T =
|
||||||
|
if not rlp.hasData:
|
||||||
|
raise (ref MalformedRlpError)(msg:
|
||||||
|
"CONSOLIDATION_REQUEST_TYPE expected but source RLP is empty")
|
||||||
|
let reqType = rlp.readRawByte()
|
||||||
|
if reqType != CONSOLIDATION_REQUEST_TYPE:
|
||||||
|
raise (ref UnsupportedRlpError)(msg:
|
||||||
|
"Unexpected CONSOLIDATION_REQUEST_TYPE: " & $reqType)
|
||||||
|
|
||||||
|
var res: ConsolidationRequest
|
||||||
|
rlp.tryEnterList()
|
||||||
|
rlp.read(res.sourceAddress)
|
||||||
|
rlp.read(res.sourcePubkey)
|
||||||
|
rlp.read(res.targetPubkey)
|
||||||
|
if rlp.hasData:
|
||||||
|
raise (ref MalformedRlpError)(msg: "Extra data after ConsolidationRequest")
|
||||||
|
res
|
||||||
|
|
||||||
proc rlpHash*[T](v: T): Hash256 =
|
proc rlpHash*[T](v: T): Hash256 =
|
||||||
keccakHash(rlp.encode(v))
|
keccakHash(rlp.encode(v))
|
||||||
|
|
||||||
|
|
|
@ -217,6 +217,14 @@ func getByteValue*(self: Rlp): byte =
|
||||||
doAssert self.isSingleByte()
|
doAssert self.isSingleByte()
|
||||||
self.bytes[self.position]
|
self.bytes[self.position]
|
||||||
|
|
||||||
|
func readRawByte*(self: var Rlp): byte =
|
||||||
|
### Read a raw byte that is not RLP encoded
|
||||||
|
### This is sometimes used to communicate union type information
|
||||||
|
doAssert self.hasData
|
||||||
|
let res = self.bytes[self.position]
|
||||||
|
inc self.position
|
||||||
|
res
|
||||||
|
|
||||||
func blobLen*(self: Rlp): int =
|
func blobLen*(self: Rlp): int =
|
||||||
if self.isBlob():
|
if self.isBlob():
|
||||||
self.item().payload.len()
|
self.item().payload.len()
|
||||||
|
|
Loading…
Reference in New Issue