Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implementation of EIP-4844: Shard Blob Transactions #1440

Merged
merged 15 commits into from
Jun 24, 2023
Merged
Prev Previous commit
Next Next commit
merge master branch
  • Loading branch information
jangko committed Jun 12, 2023
commit dec0182ffc3de70bd35d47d5382709dacf8d8d6b
3 changes: 2 additions & 1 deletion nimbus/core/executor/process_transaction.nim
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ proc asyncProcessTransactionImpl(
# before leaving is crucial for some unit tests that us a direct/deep call
# of the `processTransaction()` function. So there is no `return err()`
# statement, here.
if roDB.validateTransaction(tx, sender, header.gasLimit, baseFee256, excessDataGas, fork):
let txRes = roDB.validateTransaction(tx, sender, header.gasLimit, baseFee256, excessDataGas, fork)
if txRes.isOk:

# Execute the transaction.
let
Expand Down
2 changes: 1 addition & 1 deletion nimbus/core/tx_pool/tx_tasks/tx_classify.nim
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ proc classifyValidatePacked*(xp: TxPoolRef;
tx = item.tx.eip1559TxNormalization(xp.chain.baseFee.GasInt, fork)
excessDataGas = vmState.parent.excessDataGas.get(0'u64)

roDB.validateTransaction(tx, item.sender, gasLimit, baseFee, excessDataGas, fork)
roDB.validateTransaction(tx, item.sender, gasLimit, baseFee, excessDataGas, fork).isOk

proc classifyPacked*(xp: TxPoolRef; gasBurned, moreBurned: GasInt): bool =
## Classifier for *packing* (i.e. adding up `gasUsed` values after executing
Expand Down
109 changes: 51 additions & 58 deletions nimbus/core/validate.nim
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,8 @@ proc validateTransaction*(
maxLimit: GasInt; ## gasLimit from block header
baseFee: UInt256; ## baseFee from block header
excessDataGas: uint64; ## excessDataGas from parent block header
fork: EVMFork): bool =
fork: EVMFork): Result[void, string] =

let
balance = roDB.getBalance(sender)
nonce = roDB.getNonce(sender)
Expand All @@ -263,8 +264,7 @@ proc validateTransaction*(
return err("invalid tx: Eip1559 Tx type detected before London")

if tx.txType == TxEip4844 and fork < FkCancun:
debug "invalid tx: Eip4844 Tx type detected before Cancun"
return false
return err("invalid tx: Eip4844 Tx type detected before Cancun")

if fork >= FkShanghai and tx.contractCreation and tx.payload.len > EIP3860_MAX_INITCODE_SIZE:
return err("invalid tx: initcode size exceeds maximum")
Expand Down Expand Up @@ -299,13 +299,15 @@ proc validateTransaction*(
return err("invalid tx: maxFee is smaller than maPriorityFee. maxFee=$1, maxPriorityFee=$2" % [
$tx.maxFee, $tx.maxPriorityFee])

# the signer must be able to fully afford the transaction
let gasCost = tx.gasCost()
if balance < gasCost:
debug "invalid tx: not enough cash for gas",
available = balance,
require = gasCost
return false
# the signer must be able to fully afford the transaction
let gasCost = if tx.txType >= TxEip1559:
tx.gasLimit.u256 * tx.maxFee.u256
else:
tx.gasLimit.u256 * tx.gasPrice.u256

if balance < gasCost:
return err("invalid tx: not enough cash for gas. avail=$1, require=$2" % [
$balance, $gasCost])

if balance - gasCost < tx.value:
return err("invalid tx: not enough cash to send. avail=$1, availMinusGas=$2, require=$3" % [
Expand All @@ -331,57 +333,48 @@ proc validateTransaction*(
if codeHash != EMPTY_SHA3:
return err("invalid tx: sender is not an EOA. sender=$1, codeHash=$2" % [
sender.toHex, codeHash.data.toHex])


if fork >= FkCancun:
if tx.payload.len > MAX_CALLDATA_SIZE:
return err("invalid tx: payload len exceeds MAX_CALLDATA_SIZE. len=" &
$tx.payload.len)

if tx.accessList.len > MAX_ACCESS_LIST_SIZE:
return err("invalid tx: access list len exceeds MAX_ACCESS_LIST_SIZE. len=" &
$tx.accessList.len)

for i, acl in tx.accessList:
if acl.storageKeys.len > MAX_ACCESS_LIST_STORAGE_KEYS:
return err("invalid tx: access list storage keys len exceeds MAX_ACCESS_LIST_STORAGE_KEYS. " &
"index=$1, len=$2" % [$i, $acl.storageKeys.len])

if tx.txType == TxEip4844:
if tx.to.isNone:
return err("invalid tx: destination must be not empty")

if tx.versionedHashes.len == 0:
return err("invalid tx: there must be at least one blob")

if tx.versionedHashes.len > MAX_VERSIONED_HASHES_LIST_SIZE:
return err("invalid tx: access list len exceeds MAX_VERSIONED_HASHES_LIST_SIZE. len=" &
$tx.versionedHashes.len)

for i, bv in tx.versionedHashes:
if bv.data[0] != BLOB_COMMITMENT_VERSION_KZG:
return err("invalid tx: one of blobVersionedHash has invalid version. " &
"get=$1, expect=$2" % [$bv.data[0].int, $BLOB_COMMITMENT_VERSION_KZG.int])

# ensure that the user was willing to at least pay the current data gasprice
let dataGasPrice = getDataGasPrice(excessDataGas)
if tx.maxFeePerDataGas.uint64 < dataGasPrice:
return err("invalid tx: maxFeePerDataGas smaller than dataGasPrice. " &
"maxFeePerDataGas=$1, dataGasPrice=$2" % [$tx.maxFeePerDataGas, $dataGasPrice])

except CatchableError as ex:
return err(ex.msg)

if fork >= FkCancun:
if tx.payload.len > MAX_CALLDATA_SIZE:
debug "invalid tx: payload len exceeds MAX_CALLDATA_SIZE",
len=tx.payload.len
return false

if tx.accessList.len > MAX_ACCESS_LIST_SIZE:
debug "invalid tx: access list len exceeds MAX_ACCESS_LIST_SIZE",
len=tx.accessList.len
return false

for i, acl in tx.accessList:
if acl.storageKeys.len > MAX_ACCESS_LIST_STORAGE_KEYS:
debug "invalid tx: access list storage keys len exceeds MAX_ACCESS_LIST_STORAGE_KEYS",
index=i,
len=acl.storageKeys.len
return false

if tx.txType == TxEip4844:
if tx.to.isNone:
debug "invalid tx: destination must be not empty"
return false

if tx.versionedHashes.len == 0:
debug "invalid tx: there must be at least one blob"
return false

if tx.versionedHashes.len > MAX_VERSIONED_HASHES_LIST_SIZE:
debug "invalid tx: access list len exceeds MAX_VERSIONED_HASHES_LIST_SIZE",
len=tx.versionedHashes.len
return false

for i, bv in tx.versionedHashes:
if bv.data[0] != BLOB_COMMITMENT_VERSION_KZG:
debug "invalid tx: one of blobVersionedHash has invalid version",
get=bv.data[0].int,
expect=BLOB_COMMITMENT_VERSION_KZG.int
return false

# ensure that the user was willing to at least pay the current data gasprice
let dataGasPrice = getDataGasPrice(excessDataGas)
if tx.maxFeePerDataGas.uint64 < dataGasPrice:
debug "invalid tx: maxFeePerDataGas smaller than dataGasPrice",
maxFeePerDataGas=tx.maxFeePerDataGas,
dataGasPrice
return false

true
ok()

# ------------------------------------------------------------------------------
# Public functions, extracted from test_blockchain_json
Expand Down
You are viewing a condensed version of this merge commit. You can view the full changes here.