mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-03-03 23:51:22 +00:00
add helpers for processing withdrawals to libnimbus_lc.a
(#5374)
Similar to the existing helpers for processing transactions / receipts, extend `libnimbus_lc.a` with support for processing withdrawals as well.
This commit is contained in:
parent
41ce581149
commit
be9ecfa1c9
@ -1080,6 +1080,26 @@ ETH_RESULT_USE_CHECK
|
|||||||
const ETHRoot *ETHExecutionBlockHeaderGetWithdrawalsRoot(
|
const ETHRoot *ETHExecutionBlockHeaderGetWithdrawalsRoot(
|
||||||
const ETHExecutionBlockHeader *executionBlockHeader);
|
const ETHExecutionBlockHeader *executionBlockHeader);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Withdrawal sequence.
|
||||||
|
*/
|
||||||
|
typedef struct ETHWithdrawals ETHWithdrawals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the withdrawal sequence of a given execution block header.
|
||||||
|
*
|
||||||
|
* - The returned value is allocated in the given execution block header.
|
||||||
|
* It must neither be released nor written to, and the execution block
|
||||||
|
* header must not be released while the returned value is in use.
|
||||||
|
*
|
||||||
|
* @param executionBlockHeader Execution block header.
|
||||||
|
*
|
||||||
|
* @return Withdrawal sequence.
|
||||||
|
*/
|
||||||
|
ETH_RESULT_USE_CHECK
|
||||||
|
const ETHWithdrawals *ETHExecutionBlockHeaderGetWithdrawals(
|
||||||
|
const ETHExecutionBlockHeader *executionBlockHeader);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transaction sequence.
|
* Transaction sequence.
|
||||||
*/
|
*/
|
||||||
@ -1765,6 +1785,114 @@ const void *ETHReceiptGetBytes(
|
|||||||
const ETHReceipt *receipt,
|
const ETHReceipt *receipt,
|
||||||
int *numBytes);
|
int *numBytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the total number of withdrawals in a withdrawal sequence.
|
||||||
|
*
|
||||||
|
* - Individual withdrawals may be investigated using `ETHWithdrawalsGet`.
|
||||||
|
*
|
||||||
|
* @param withdrawals Withdrawal sequence.
|
||||||
|
*
|
||||||
|
* @return Number of available withdrawals.
|
||||||
|
*/
|
||||||
|
ETH_RESULT_USE_CHECK
|
||||||
|
int ETHWithdrawalsGetCount(const ETHWithdrawals *withdrawals);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Withdrawal.
|
||||||
|
*/
|
||||||
|
typedef struct ETHWithdrawal ETHWithdrawal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains an individual withdrawal by sequential index
|
||||||
|
* in a withdrawal sequence.
|
||||||
|
*
|
||||||
|
* - The returned value is allocated in the given withdrawal sequence.
|
||||||
|
* It must neither be released nor written to, and the withdrawal
|
||||||
|
* sequence must not be released while the returned value is in use.
|
||||||
|
*
|
||||||
|
* @param withdrawals Withdrawal sequence.
|
||||||
|
* @param withdrawalIndex Sequential withdrawal index.
|
||||||
|
*
|
||||||
|
* @return Withdrawal.
|
||||||
|
*/
|
||||||
|
ETH_RESULT_USE_CHECK
|
||||||
|
const ETHWithdrawal *ETHWithdrawalsGet(
|
||||||
|
const ETHWithdrawals *withdrawals,
|
||||||
|
int withdrawalIndex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the index of a withdrawal.
|
||||||
|
*
|
||||||
|
* - The returned value is allocated in the given withdrawal.
|
||||||
|
* It must neither be released nor written to, and the withdrawal
|
||||||
|
* must not be released while the returned value is in use.
|
||||||
|
*
|
||||||
|
* @param withdrawal Withdrawal.
|
||||||
|
*
|
||||||
|
* @return Index.
|
||||||
|
*/
|
||||||
|
ETH_RESULT_USE_CHECK
|
||||||
|
const uint64_t *ETHWithdrawalGetIndex(const ETHWithdrawal *withdrawal);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the validator index of a withdrawal.
|
||||||
|
*
|
||||||
|
* - The returned value is allocated in the given withdrawal.
|
||||||
|
* It must neither be released nor written to, and the withdrawal
|
||||||
|
* must not be released while the returned value is in use.
|
||||||
|
*
|
||||||
|
* @param withdrawal Withdrawal.
|
||||||
|
*
|
||||||
|
* @return Validator index.
|
||||||
|
*/
|
||||||
|
ETH_RESULT_USE_CHECK
|
||||||
|
const uint64_t *ETHWithdrawalGetValidatorIndex(const ETHWithdrawal *withdrawal);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the address of a withdrawal.
|
||||||
|
*
|
||||||
|
* - The returned value is allocated in the given withdrawal.
|
||||||
|
* It must neither be released nor written to, and the withdrawal
|
||||||
|
* must not be released while the returned value is in use.
|
||||||
|
*
|
||||||
|
* @param withdrawal Withdrawal.
|
||||||
|
*
|
||||||
|
* @return Address.
|
||||||
|
*/
|
||||||
|
ETH_RESULT_USE_CHECK
|
||||||
|
const ETHExecutionAddress *ETHWithdrawalGetAddress(const ETHWithdrawal *withdrawal);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the amount of a withdrawal.
|
||||||
|
*
|
||||||
|
* - The returned value is allocated in the given withdrawal.
|
||||||
|
* It must neither be released nor written to, and the withdrawal
|
||||||
|
* must not be released while the returned value is in use.
|
||||||
|
*
|
||||||
|
* @param withdrawal Withdrawal.
|
||||||
|
*
|
||||||
|
* @return Amount.
|
||||||
|
*/
|
||||||
|
ETH_RESULT_USE_CHECK
|
||||||
|
const uint64_t *ETHWithdrawalGetAmount(const ETHWithdrawal *withdrawal);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the raw byte representation of a withdrawal.
|
||||||
|
*
|
||||||
|
* - The returned value is allocated in the given withdrawal.
|
||||||
|
* It must neither be released nor written to, and the withdrawal
|
||||||
|
* must not be released while the returned value is in use.
|
||||||
|
*
|
||||||
|
* @param withdrawal Withdrawal.
|
||||||
|
* @param[out] numBytes Length of buffer.
|
||||||
|
*
|
||||||
|
* @return Buffer with raw withdrawal data.
|
||||||
|
*/
|
||||||
|
ETH_RESULT_USE_CHECK
|
||||||
|
const void *ETHWithdrawalGetBytes(
|
||||||
|
const ETHWithdrawal *withdrawal,
|
||||||
|
int *numBytes);
|
||||||
|
|
||||||
#if __has_feature(nullability)
|
#if __has_feature(nullability)
|
||||||
#pragma clang assume_nonnull end
|
#pragma clang assume_nonnull end
|
||||||
#endif
|
#endif
|
||||||
|
@ -1169,9 +1169,18 @@ func ETHExecutionPayloadHeaderGetExcessBlobGas(
|
|||||||
## * Excess blob gas.
|
## * Excess blob gas.
|
||||||
execution[].excess_blob_gas.cint
|
execution[].excess_blob_gas.cint
|
||||||
|
|
||||||
type ETHExecutionBlockHeader = object
|
type
|
||||||
transactionsRoot: Eth2Digest
|
ETHWithdrawal = object
|
||||||
withdrawalsRoot: Eth2Digest
|
index: uint64
|
||||||
|
validatorIndex: uint64
|
||||||
|
address: ExecutionAddress
|
||||||
|
amount: uint64
|
||||||
|
bytes: seq[byte]
|
||||||
|
|
||||||
|
ETHExecutionBlockHeader = object
|
||||||
|
transactionsRoot: Eth2Digest
|
||||||
|
withdrawalsRoot: Eth2Digest
|
||||||
|
withdrawals: seq[ETHWithdrawal]
|
||||||
|
|
||||||
proc ETHExecutionBlockHeaderCreateFromJson(
|
proc ETHExecutionBlockHeaderCreateFromJson(
|
||||||
executionHash: ptr Eth2Digest,
|
executionHash: ptr Eth2Digest,
|
||||||
@ -1277,10 +1286,51 @@ proc ETHExecutionBlockHeaderCreateFromJson(
|
|||||||
if rlpHash(blockHeader) != executionHash[]:
|
if rlpHash(blockHeader) != executionHash[]:
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
|
# Construct withdrawals
|
||||||
|
var wds: seq[ETHWithdrawal]
|
||||||
|
if data.withdrawals.isSome:
|
||||||
|
doAssert data.withdrawalsRoot.isSome # Checked above
|
||||||
|
|
||||||
|
wds = newSeqOfCap[ETHWithdrawal](data.withdrawals.get.len)
|
||||||
|
for data in data.withdrawals.get:
|
||||||
|
# Check fork consistency
|
||||||
|
static: doAssert totalSerializedFields(WithdrawalObject) == 4,
|
||||||
|
"Only update this number once code is adjusted to check new fields!"
|
||||||
|
|
||||||
|
# Construct withdrawal
|
||||||
|
let
|
||||||
|
wd = ExecutionWithdrawal(
|
||||||
|
index: distinctBase(data.index),
|
||||||
|
validatorIndex: distinctBase(data.validatorIndex),
|
||||||
|
address: distinctBase(data.address),
|
||||||
|
amount: distinctBase(data.amount))
|
||||||
|
rlpBytes =
|
||||||
|
try:
|
||||||
|
rlp.encode(wd)
|
||||||
|
except RlpError:
|
||||||
|
raiseAssert "Unreachable"
|
||||||
|
|
||||||
|
wds.add ETHWithdrawal(
|
||||||
|
index: wd.index,
|
||||||
|
validatorIndex: wd.validatorIndex,
|
||||||
|
address: ExecutionAddress(data: wd.address),
|
||||||
|
amount: wd.amount,
|
||||||
|
bytes: rlpBytes)
|
||||||
|
|
||||||
|
var tr = initHexaryTrie(newMemoryDB())
|
||||||
|
for i, wd in wds:
|
||||||
|
try:
|
||||||
|
tr.put(rlp.encode(i), wd.bytes)
|
||||||
|
except RlpError:
|
||||||
|
raiseAssert "Unreachable"
|
||||||
|
if tr.rootHash() != data.withdrawalsRoot.get.asEth2Digest:
|
||||||
|
return nil
|
||||||
|
|
||||||
let executionBlockHeader = ETHExecutionBlockHeader.new()
|
let executionBlockHeader = ETHExecutionBlockHeader.new()
|
||||||
executionBlockHeader[] = ETHExecutionBlockHeader(
|
executionBlockHeader[] = ETHExecutionBlockHeader(
|
||||||
transactionsRoot: blockHeader.txRoot,
|
transactionsRoot: blockHeader.txRoot,
|
||||||
withdrawalsRoot: blockHeader.withdrawalsRoot.get(ZERO_HASH))
|
withdrawalsRoot: blockHeader.withdrawalsRoot.get(ZERO_HASH),
|
||||||
|
withdrawals: wds)
|
||||||
executionBlockHeader.toUnmanagedPtr()
|
executionBlockHeader.toUnmanagedPtr()
|
||||||
|
|
||||||
proc ETHExecutionBlockHeaderDestroy(
|
proc ETHExecutionBlockHeaderDestroy(
|
||||||
@ -1325,6 +1375,22 @@ func ETHExecutionBlockHeaderGetWithdrawalsRoot(
|
|||||||
## * Execution withdrawals root.
|
## * Execution withdrawals root.
|
||||||
addr executionBlockHeader[].withdrawalsRoot
|
addr executionBlockHeader[].withdrawalsRoot
|
||||||
|
|
||||||
|
func ETHExecutionBlockHeaderGetWithdrawals(
|
||||||
|
executionBlockHeader: ptr ETHExecutionBlockHeader
|
||||||
|
): ptr seq[ETHWithdrawal] {.exported.} =
|
||||||
|
## Obtains the withdrawal sequence of a given execution block header.
|
||||||
|
##
|
||||||
|
## * The returned value is allocated in the given execution block header.
|
||||||
|
## It must neither be released nor written to, and the execution block
|
||||||
|
## header must not be released while the returned value is in use.
|
||||||
|
##
|
||||||
|
## Parameters:
|
||||||
|
## * `executionBlockHeader` - Execution block header.
|
||||||
|
##
|
||||||
|
## Returns:
|
||||||
|
## * Withdrawal sequence.
|
||||||
|
addr executionBlockHeader[].withdrawals
|
||||||
|
|
||||||
type
|
type
|
||||||
ETHAccessTuple = object
|
ETHAccessTuple = object
|
||||||
address: ExecutionAddress
|
address: ExecutionAddress
|
||||||
@ -2391,3 +2457,116 @@ func ETHReceiptGetBytes(
|
|||||||
const defaultBytes: cstring = ""
|
const defaultBytes: cstring = ""
|
||||||
return cast[ptr UncheckedArray[byte]](defaultBytes)
|
return cast[ptr UncheckedArray[byte]](defaultBytes)
|
||||||
cast[ptr UncheckedArray[byte]](addr distinctBase(receipt[].bytes)[0])
|
cast[ptr UncheckedArray[byte]](addr distinctBase(receipt[].bytes)[0])
|
||||||
|
|
||||||
|
func ETHWithdrawalsGetCount(
|
||||||
|
withdrawals: ptr seq[ETHWithdrawal]): cint {.exported.} =
|
||||||
|
## Indicates the total number of withdrawals in a withdrawal sequence.
|
||||||
|
##
|
||||||
|
## * Individual withdrawals may be investigated using `ETHWithdrawalsGet`.
|
||||||
|
##
|
||||||
|
## Parameters:
|
||||||
|
## * `withdrawals` - Withdrawal sequence.
|
||||||
|
##
|
||||||
|
## Returns:
|
||||||
|
## * Number of available withdrawals.
|
||||||
|
withdrawals[].len.cint
|
||||||
|
|
||||||
|
func ETHWithdrawalsGet(
|
||||||
|
withdrawals: ptr seq[ETHWithdrawal],
|
||||||
|
withdrawalIndex: cint): ptr ETHWithdrawal {.exported.} =
|
||||||
|
## Obtains an individual withdrawal by sequential index
|
||||||
|
## in a withdrawal sequence.
|
||||||
|
##
|
||||||
|
## * The returned value is allocated in the given withdrawal sequence.
|
||||||
|
## It must neither be released nor written to, and the withdrawal
|
||||||
|
## sequence must not be released while the returned value is in use.
|
||||||
|
##
|
||||||
|
## Parameters:
|
||||||
|
## * `withdrawals` - Withdrawal sequence.
|
||||||
|
## * `withdrawalIndex` - Sequential withdrawal index.
|
||||||
|
##
|
||||||
|
## Returns:
|
||||||
|
## * Withdrawal.
|
||||||
|
addr withdrawals[][withdrawalIndex.int]
|
||||||
|
|
||||||
|
func ETHWithdrawalGetIndex(
|
||||||
|
withdrawal: ptr ETHWithdrawal): ptr uint64 {.exported.} =
|
||||||
|
## Obtains the index of a withdrawal.
|
||||||
|
##
|
||||||
|
## * The returned value is allocated in the given withdrawal.
|
||||||
|
## It must neither be released nor written to, and the withdrawal
|
||||||
|
## must not be released while the returned value is in use.
|
||||||
|
##
|
||||||
|
## Parameters:
|
||||||
|
## * `withdrawal` - Withdrawal.
|
||||||
|
##
|
||||||
|
## Returns:
|
||||||
|
## * Index.
|
||||||
|
addr withdrawal[].index
|
||||||
|
|
||||||
|
func ETHWithdrawalGetValidatorIndex(
|
||||||
|
withdrawal: ptr ETHWithdrawal): ptr uint64 {.exported.} =
|
||||||
|
## Obtains the validator index of a withdrawal.
|
||||||
|
##
|
||||||
|
## * The returned value is allocated in the given withdrawal.
|
||||||
|
## It must neither be released nor written to, and the withdrawal
|
||||||
|
## must not be released while the returned value is in use.
|
||||||
|
##
|
||||||
|
## Parameters:
|
||||||
|
## * `withdrawal` - Withdrawal.
|
||||||
|
##
|
||||||
|
## Returns:
|
||||||
|
## * Validator index.
|
||||||
|
addr withdrawal[].validatorIndex
|
||||||
|
|
||||||
|
func ETHWithdrawalGetAddress(
|
||||||
|
withdrawal: ptr ETHWithdrawal): ptr ExecutionAddress {.exported.} =
|
||||||
|
## Obtains the address of a withdrawal.
|
||||||
|
##
|
||||||
|
## * The returned value is allocated in the given withdrawal.
|
||||||
|
## It must neither be released nor written to, and the withdrawal
|
||||||
|
## must not be released while the returned value is in use.
|
||||||
|
##
|
||||||
|
## Parameters:
|
||||||
|
## * `withdrawal` - Withdrawal.
|
||||||
|
##
|
||||||
|
## Returns:
|
||||||
|
## * Address.
|
||||||
|
addr withdrawal[].address
|
||||||
|
|
||||||
|
func ETHWithdrawalGetAmount(
|
||||||
|
withdrawal: ptr ETHWithdrawal): ptr uint64 {.exported.} =
|
||||||
|
## Obtains the amount of a withdrawal.
|
||||||
|
##
|
||||||
|
## * The returned value is allocated in the given withdrawal.
|
||||||
|
## It must neither be released nor written to, and the withdrawal
|
||||||
|
## must not be released while the returned value is in use.
|
||||||
|
##
|
||||||
|
## Parameters:
|
||||||
|
## * `withdrawal` - Withdrawal.
|
||||||
|
##
|
||||||
|
## Returns:
|
||||||
|
## * Amount.
|
||||||
|
addr withdrawal[].amount
|
||||||
|
|
||||||
|
func ETHWithdrawalGetBytes(
|
||||||
|
withdrawal: ptr ETHWithdrawal,
|
||||||
|
numBytes #[out]#: ptr cint): ptr UncheckedArray[byte] {.exported.} =
|
||||||
|
## Obtains the raw byte representation of a withdrawal.
|
||||||
|
##
|
||||||
|
## * The returned value is allocated in the given withdrawal.
|
||||||
|
## It must neither be released nor written to, and the withdrawal
|
||||||
|
## must not be released while the returned value is in use.
|
||||||
|
##
|
||||||
|
## Parameters:
|
||||||
|
## * `withdrawal` - Withdrawal.
|
||||||
|
## * `numBytes` [out] - Length of buffer.
|
||||||
|
##
|
||||||
|
## Returns:
|
||||||
|
## * Buffer with raw withdrawal data.
|
||||||
|
numBytes[] = distinctBase(withdrawal[].bytes).len.cint
|
||||||
|
if distinctBase(withdrawal[].bytes).len == 0:
|
||||||
|
# https://github.com/nim-lang/Nim/issues/22389
|
||||||
|
const defaultBytes: cstring = ""
|
||||||
|
return cast[ptr UncheckedArray[byte]](defaultBytes)
|
||||||
|
cast[ptr UncheckedArray[byte]](addr distinctBase(withdrawal[].bytes)[0])
|
||||||
|
@ -375,7 +375,7 @@ int main(void)
|
|||||||
ETHRootDestroy(copiedExecutionHash);
|
ETHRootDestroy(copiedExecutionHash);
|
||||||
ETHLightClientHeaderDestroy(copiedHeader);
|
ETHLightClientHeaderDestroy(copiedHeader);
|
||||||
|
|
||||||
printf("- finalized_header (execution block header):\n");
|
printf("\nFinalized_header (execution block header):\n");
|
||||||
|
|
||||||
const ETHRoot *executionTransactionsRoot =
|
const ETHRoot *executionTransactionsRoot =
|
||||||
ETHExecutionBlockHeaderGetTransactionsRoot(executionBlockHeader);
|
ETHExecutionBlockHeaderGetTransactionsRoot(executionBlockHeader);
|
||||||
@ -389,6 +389,34 @@ int main(void)
|
|||||||
printHexString(executionWithdrawalsRoot, sizeof *executionWithdrawalsRoot);
|
printHexString(executionWithdrawalsRoot, sizeof *executionWithdrawalsRoot);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
const ETHWithdrawals *withdrawals =
|
||||||
|
ETHExecutionBlockHeaderGetWithdrawals(executionBlockHeader);
|
||||||
|
int numWithdrawals = ETHWithdrawalsGetCount(withdrawals);
|
||||||
|
printf(" - withdrawals:\n");
|
||||||
|
for (int withdrawalIndex = 0; withdrawalIndex < numWithdrawals; withdrawalIndex++) {
|
||||||
|
const ETHWithdrawal *withdrawal = ETHWithdrawalsGet(withdrawals, withdrawalIndex);
|
||||||
|
|
||||||
|
const uint64_t *index = ETHWithdrawalGetIndex(withdrawal);
|
||||||
|
printf(" - index: %" PRIu64 "\n", *index);
|
||||||
|
|
||||||
|
const uint64_t *validatorIndex = ETHWithdrawalGetValidatorIndex(withdrawal);
|
||||||
|
printf(" - validator_index: %" PRIu64 "\n", *validatorIndex);
|
||||||
|
|
||||||
|
const ETHExecutionAddress *address = ETHWithdrawalGetAddress(withdrawal);
|
||||||
|
printf(" - address: ");
|
||||||
|
printHexString(address, sizeof *address);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
const uint64_t *amount = ETHWithdrawalGetAmount(withdrawal);
|
||||||
|
printf(" - amount: %" PRIu64 "\n", *amount);
|
||||||
|
|
||||||
|
int numBytes;
|
||||||
|
const void *bytes = ETHWithdrawalGetBytes(withdrawal, &numBytes);
|
||||||
|
printf(" - bytes: ");
|
||||||
|
printHexString(bytes, numBytes);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
ETHExecutionBlockHeaderDestroy(executionBlockHeader);
|
ETHExecutionBlockHeaderDestroy(executionBlockHeader);
|
||||||
|
|
||||||
ETHRoot sampleTransactionsRoot = {{
|
ETHRoot sampleTransactionsRoot = {{
|
||||||
|
@ -34,7 +34,7 @@ type
|
|||||||
ExecutionHash256* = eth_types.Hash256
|
ExecutionHash256* = eth_types.Hash256
|
||||||
ExecutionTransaction* = eth_types.Transaction
|
ExecutionTransaction* = eth_types.Transaction
|
||||||
ExecutionReceipt* = eth_types.Receipt
|
ExecutionReceipt* = eth_types.Receipt
|
||||||
ExecutionWithdrawal = eth_types.Withdrawal
|
ExecutionWithdrawal* = eth_types.Withdrawal
|
||||||
ExecutionBlockHeader* = eth_types.BlockHeader
|
ExecutionBlockHeader* = eth_types.BlockHeader
|
||||||
|
|
||||||
FinalityCheckpoints* = object
|
FinalityCheckpoints* = object
|
||||||
|
Loading…
x
Reference in New Issue
Block a user