diff --git a/packages/protocol/contracts/L1/TaikoData.sol b/packages/protocol/contracts/L1/TaikoData.sol index 2330cb0d120..bdf9a1372dd 100644 --- a/packages/protocol/contracts/L1/TaikoData.sol +++ b/packages/protocol/contracts/L1/TaikoData.sol @@ -42,6 +42,8 @@ library TaikoData { uint24 blobExpiry; // True if EIP-4844 is enabled for DA bool blobAllowedForDA; + // True if blob can be reused + bool blobReuseEnabled; // --------------------------------------------------------------------- // Group 3: Proof related configs // --------------------------------------------------------------------- diff --git a/packages/protocol/contracts/L1/TaikoErrors.sol b/packages/protocol/contracts/L1/TaikoErrors.sol index 79d3b8c3be3..c874b3561cd 100644 --- a/packages/protocol/contracts/L1/TaikoErrors.sol +++ b/packages/protocol/contracts/L1/TaikoErrors.sol @@ -28,6 +28,7 @@ abstract contract TaikoErrors { error L1_BLOB_NOT_FOUND(); error L1_BLOB_NOT_REUSEABLE(); error L1_BLOB_NOT_USED(); + error L1_BLOB_REUSE_DISALBED(); error L1_BLOCK_MISMATCH(); error L1_CHAIN_DATA_NOT_RELAYED(); error L1_INVALID_BLOCK_ID(); diff --git a/packages/protocol/contracts/L1/TaikoL1.sol b/packages/protocol/contracts/L1/TaikoL1.sol index 9b4e9a5494c..df34a0e1b94 100644 --- a/packages/protocol/contracts/L1/TaikoL1.sol +++ b/packages/protocol/contracts/L1/TaikoL1.sol @@ -142,8 +142,18 @@ contract TaikoL1 is EssentialContract, ITaikoL1, ITierProvider, TaikoEvents, Tai /// @notice Gets the details of a block. /// @param blockId Index of the block. /// @return blk The block. - function getBlock(uint64 blockId) public view returns (TaikoData.Block memory blk) { - return LibUtils.getBlock(state, getConfig(), blockId); + /// @return ts The transition used to verify this block. + function getBlock(uint64 blockId) + public + view + returns (TaikoData.Block memory blk, TaikoData.TransitionState memory ts) + { + uint64 slot; + (blk, slot) = LibUtils.getBlock(state, getConfig(), blockId); + + if (blk.verifiedTransitionId != 0) { + ts = state.transitions[slot][blk.verifiedTransitionId]; + } } /// @notice Gets the state transition for a specific block. @@ -219,6 +229,7 @@ contract TaikoL1 is EssentialContract, ITaikoL1, ITierProvider, TaikoEvents, Tai blockMaxTxListBytes: 120_000, blobExpiry: 24 hours, blobAllowedForDA: false, + blobReuseEnabled: false, livenessBond: 250e18, // 250 Taiko token // ETH deposit related. ethDepositRingBufferSize: 1024, diff --git a/packages/protocol/contracts/L1/libs/LibProposing.sol b/packages/protocol/contracts/L1/libs/LibProposing.sol index a4ae28e4859..4852521bb52 100644 --- a/packages/protocol/contracts/L1/libs/LibProposing.sol +++ b/packages/protocol/contracts/L1/libs/LibProposing.sol @@ -46,6 +46,7 @@ library LibProposing { error L1_BLOB_FOR_DA_DISABLED(); error L1_BLOB_NOT_FOUND(); error L1_BLOB_NOT_REUSEABLE(); + error L1_BLOB_REUSE_DISALBED(); error L1_INVALID_HOOK(); error L1_INVALID_PARAM(); error L1_INVALID_PROVER(); @@ -139,6 +140,8 @@ library LibProposing { if (!config.blobAllowedForDA) revert L1_BLOB_FOR_DA_DISABLED(); if (params.blobHash != 0) { + if (!config.blobReuseEnabled) revert L1_BLOB_REUSE_DISALBED(); + // We try to reuse an old blob if (!isBlobReusable(state, config, params.blobHash)) { revert L1_BLOB_NOT_REUSEABLE(); @@ -156,7 +159,7 @@ library LibProposing { // Depends on the blob data price, it may not make sense to // cache the blob which costs 20,000 (sstore) + 631 (event) // extra gas. - if (params.cacheBlobForReuse) { + if (config.blobReuseEnabled && params.cacheBlobForReuse) { state.reusableBlobs[meta.blobHash] = block.timestamp; emit BlobCached(meta.blobHash); } diff --git a/packages/protocol/contracts/L1/libs/LibUtils.sol b/packages/protocol/contracts/L1/libs/LibUtils.sol index 6c6fd8d4331..1f87ae5d826 100644 --- a/packages/protocol/contracts/L1/libs/LibUtils.sol +++ b/packages/protocol/contracts/L1/libs/LibUtils.sol @@ -64,9 +64,10 @@ library LibUtils { ) external view - returns (TaikoData.Block storage blk) + returns (TaikoData.Block storage blk, uint64 slot) { - blk = state.blocks[blockId % config.blockRingBufferSize]; + slot = blockId % config.blockRingBufferSize; + blk = state.blocks[slot]; if (blk.blockId != blockId) { revert L1_INVALID_BLOCK_ID(); } diff --git a/packages/protocol/contracts/tokenvault/ERC721Vault.sol b/packages/protocol/contracts/tokenvault/ERC721Vault.sol index b87663d3fb2..92df7884e7a 100644 --- a/packages/protocol/contracts/tokenvault/ERC721Vault.sol +++ b/packages/protocol/contracts/tokenvault/ERC721Vault.sol @@ -114,7 +114,7 @@ contract ERC721Vault is BaseNFTVault, IERC721ReceiverUpgradeable { ctoken: ctoken.addr, token: token, tokenIds: tokenIds, - amounts: new uint256[](0) + amounts: new uint256[](tokenIds.length) }); } @@ -143,7 +143,7 @@ contract ERC721Vault is BaseNFTVault, IERC721ReceiverUpgradeable { ctoken: ctoken.addr, token: token, tokenIds: tokenIds, - amounts: new uint256[](0) + amounts: new uint256[](tokenIds.length) }); } diff --git a/packages/relayer/.gitignore b/packages/relayer/.gitignore index 1e90821859d..210208a1b08 100644 --- a/packages/relayer/.gitignore +++ b/packages/relayer/.gitignore @@ -10,8 +10,10 @@ .l1l3processor.env .l2l1processor.env .l1processor.env +.l1indexer.env .l2indexer.env main +relayer coverage.txt # Local .terraform directories diff --git a/packages/relayer/cmd/flags/indexer.go b/packages/relayer/cmd/flags/indexer.go index 9a9958951d4..a052b2223a3 100644 --- a/packages/relayer/cmd/flags/indexer.go +++ b/packages/relayer/cmd/flags/indexer.go @@ -57,6 +57,7 @@ var ( filter: only filter the chain, when caught up, exit subscribe: do not filter the chain, only subscribe to new events filter-and-subscribe: the default behavior, filter the chain and subscribe when caught up + crawl-past-blocks: crawl past blocks `, Value: "filter-and-subscribe", Category: indexerCategory, @@ -85,6 +86,7 @@ var ( var IndexerFlags = MergeFlags(CommonFlags, QueueFlags, []cli.Flag{ SrcBridgeAddress, + DestBridgeAddress, // optional SrcTaikoAddress, BlockBatchSize, @@ -92,7 +94,6 @@ var IndexerFlags = MergeFlags(CommonFlags, QueueFlags, []cli.Flag{ SubscriptionBackoff, SyncMode, WatchMode, - DestBridgeAddress, NumLatestBlocksToIgnoreWhenCrawling, EventName, }) diff --git a/packages/relayer/event.go b/packages/relayer/event.go index 7d55c968359..daffa2c30a8 100644 --- a/packages/relayer/event.go +++ b/packages/relayer/event.go @@ -25,7 +25,7 @@ const ( EventStatusRetriable EventStatusDone EventStatusFailed - EventStatusNewOnlyOwner + EventStatusNewOnlyOwner // internal used in Relayer only ) type EventType int diff --git a/packages/relayer/processor/can_process_message.go b/packages/relayer/processor/can_process_message.go index 2c2486c19f5..39298e8e36c 100644 --- a/packages/relayer/processor/can_process_message.go +++ b/packages/relayer/processor/can_process_message.go @@ -28,7 +28,7 @@ func canProcessMessage( return true } - slog.Info("cant process message", "eventStatus", eventStatus.String()) + slog.Info("cant process message due to", "eventStatus", eventStatus.String()) return false } diff --git a/packages/relayer/processor/process_single.go b/packages/relayer/processor/process_single.go index 36a6b244236..766e48a5ddc 100644 --- a/packages/relayer/processor/process_single.go +++ b/packages/relayer/processor/process_single.go @@ -3,14 +3,19 @@ package processor import ( "context" "encoding/json" + "log/slog" "strings" "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/taikoxyz/taiko-mono/packages/relayer/bindings/bridge" "github.com/taikoxyz/taiko-mono/packages/relayer/pkg/queue" ) func (p *Processor) processSingle(ctx context.Context) error { + slog.Info("processing tx", "estimateGas", common.Hash(*p.targetTxHash).Hex()) + bridgeAbi, err := abi.JSON(strings.NewReader(bridge.BridgeABI)) if err != nil { return err diff --git a/packages/relayer/processor/processor.go b/packages/relayer/processor/processor.go index a813d854c59..8458a1baac3 100644 --- a/packages/relayer/processor/processor.go +++ b/packages/relayer/processor/processor.go @@ -8,6 +8,7 @@ import ( "fmt" "log/slog" "math/big" + "os" "sync" "time" @@ -362,7 +363,12 @@ func (p *Processor) Start() error { // if a targetTxHash is set, we only want to process that specific one. if p.targetTxHash != nil { - return p.processSingle(ctx) + err := p.processSingle(ctx) + if err != nil { + slog.Error(err.Error()) + } + + os.Exit(0) } // otherwise, we can start the queue, and process messages from it @@ -411,14 +417,14 @@ func (p *Processor) eventLoop(ctx context.Context) { err := p.processMessage(ctx, msg) if err != nil { - slog.Error("err processing message", "err", err.Error()) - if errors.Is(err, errUnprocessable) { if err := p.queue.Ack(ctx, msg); err != nil { slog.Error("Err acking message", "err", err.Error()) } } else { - if err := p.queue.Nack(ctx, msg); err != nil { + slog.Error("process message failed", "err", err.Error()) + + if err = p.queue.Nack(ctx, msg); err != nil { slog.Error("Err nacking message", "err", err.Error()) } } diff --git a/packages/status-page/src/constants/abi/TaikoL2.ts b/packages/status-page/src/constants/abi/TaikoL2.ts deleted file mode 100644 index 8368362b8cd..00000000000 --- a/packages/status-page/src/constants/abi/TaikoL2.ts +++ /dev/null @@ -1,670 +0,0 @@ -export default [ - { - inputs: [ - { - internalType: "uint64", - name: "expected", - type: "uint64", - }, - { - internalType: "uint64", - name: "actual", - type: "uint64", - }, - ], - name: "L2_BASEFEE_MISMATCH", - type: "error", - }, - { - inputs: [], - name: "L2_INVALID_1559_PARAMS", - type: "error", - }, - { - inputs: [], - name: "L2_INVALID_CHAIN_ID", - type: "error", - }, - { - inputs: [], - name: "L2_INVALID_GOLDEN_TOUCH_K", - type: "error", - }, - { - inputs: [], - name: "L2_INVALID_SENDER", - type: "error", - }, - { - inputs: [ - { - internalType: "bytes32", - name: "expected", - type: "bytes32", - }, - { - internalType: "bytes32", - name: "actual", - type: "bytes32", - }, - ], - name: "L2_PUBLIC_INPUT_HASH_MISMATCH", - type: "error", - }, - { - inputs: [], - name: "L2_TOO_LATE", - type: "error", - }, - { - inputs: [], - name: "M1559_OUT_OF_STOCK", - type: "error", - }, - { - inputs: [], - name: "M1559_OUT_OF_STOCK", - type: "error", - }, - { - inputs: [ - { - internalType: "uint64", - name: "expected", - type: "uint64", - }, - { - internalType: "uint64", - name: "actual", - type: "uint64", - }, - ], - name: "M1559_UNEXPECTED_CHANGE", - type: "error", - }, - { - inputs: [ - { - internalType: "uint64", - name: "expected", - type: "uint64", - }, - { - internalType: "uint64", - name: "actual", - type: "uint64", - }, - ], - name: "M1559_UNEXPECTED_CHANGE", - type: "error", - }, - { - inputs: [], - name: "Overflow", - type: "error", - }, - { - inputs: [], - name: "RESOLVER_DENIED", - type: "error", - }, - { - inputs: [], - name: "RESOLVER_INVALID_ADDR", - type: "error", - }, - { - inputs: [ - { - internalType: "uint256", - name: "chainId", - type: "uint256", - }, - { - internalType: "bytes32", - name: "name", - type: "bytes32", - }, - ], - name: "RESOLVER_ZERO_ADDR", - type: "error", - }, - { - anonymous: false, - inputs: [ - { - indexed: false, - internalType: "address", - name: "addressManager", - type: "address", - }, - ], - name: "AddressManagerChanged", - type: "event", - }, - { - anonymous: false, - inputs: [ - { - indexed: false, - internalType: "uint64", - name: "number", - type: "uint64", - }, - { - indexed: false, - internalType: "uint64", - name: "basefee", - type: "uint64", - }, - { - indexed: false, - internalType: "uint64", - name: "gaslimit", - type: "uint64", - }, - { - indexed: false, - internalType: "uint64", - name: "timestamp", - type: "uint64", - }, - { - indexed: false, - internalType: "bytes32", - name: "parentHash", - type: "bytes32", - }, - { - indexed: false, - internalType: "uint256", - name: "prevrandao", - type: "uint256", - }, - { - indexed: false, - internalType: "address", - name: "coinbase", - type: "address", - }, - { - indexed: false, - internalType: "uint32", - name: "chainid", - type: "uint32", - }, - ], - name: "Anchored", - type: "event", - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "uint256", - name: "srcHeight", - type: "uint256", - }, - { - indexed: false, - internalType: "bytes32", - name: "blockHash", - type: "bytes32", - }, - { - indexed: false, - internalType: "bytes32", - name: "signalRoot", - type: "bytes32", - }, - ], - name: "CrossChainSynced", - type: "event", - }, - { - anonymous: false, - inputs: [ - { - indexed: false, - internalType: "uint8", - name: "version", - type: "uint8", - }, - ], - name: "Initialized", - type: "event", - }, - { - anonymous: false, - inputs: [ - { - indexed: true, - internalType: "address", - name: "previousOwner", - type: "address", - }, - { - indexed: true, - internalType: "address", - name: "newOwner", - type: "address", - }, - ], - name: "OwnershipTransferred", - type: "event", - }, - { - inputs: [], - name: "GOLDEN_TOUCH_ADDRESS", - outputs: [ - { - internalType: "address", - name: "", - type: "address", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "GOLDEN_TOUCH_PRIVATEKEY", - outputs: [ - { - internalType: "uint256", - name: "", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "addressManager", - outputs: [ - { - internalType: "address", - name: "", - type: "address", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "bytes32", - name: "l1Hash", - type: "bytes32", - }, - { - internalType: "bytes32", - name: "l1SignalRoot", - type: "bytes32", - }, - { - internalType: "uint64", - name: "l1Height", - type: "uint64", - }, - { - internalType: "uint64", - name: "parentGasUsed", - type: "uint64", - }, - ], - name: "anchor", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [], - name: "gasExcess", - outputs: [ - { - internalType: "uint64", - name: "", - type: "uint64", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "uint32", - name: "timeSinceParent", - type: "uint32", - }, - { - internalType: "uint64", - name: "gasLimit", - type: "uint64", - }, - { - internalType: "uint64", - name: "parentGasUsed", - type: "uint64", - }, - ], - name: "getBasefee", - outputs: [ - { - internalType: "uint256", - name: "_basefee", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "uint256", - name: "number", - type: "uint256", - }, - ], - name: "getBlockHash", - outputs: [ - { - internalType: "bytes32", - name: "", - type: "bytes32", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "uint256", - name: "number", - type: "uint256", - }, - ], - name: "getCrossChainBlockHash", - outputs: [ - { - internalType: "bytes32", - name: "", - type: "bytes32", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "uint256", - name: "number", - type: "uint256", - }, - ], - name: "getCrossChainSignalRoot", - outputs: [ - { - internalType: "bytes32", - name: "", - type: "bytes32", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "getEIP1559Config", - outputs: [ - { - components: [ - { - internalType: "uint128", - name: "yscale", - type: "uint128", - }, - { - internalType: "uint64", - name: "xscale", - type: "uint64", - }, - { - internalType: "uint64", - name: "gasIssuedPerSecond", - type: "uint64", - }, - ], - internalType: "struct TaikoL2.EIP1559Config", - name: "", - type: "tuple", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "_addressManager", - type: "address", - }, - { - components: [ - { - internalType: "uint64", - name: "basefee", - type: "uint64", - }, - { - internalType: "uint64", - name: "gasIssuedPerSecond", - type: "uint64", - }, - { - internalType: "uint64", - name: "gasExcessMax", - type: "uint64", - }, - { - internalType: "uint64", - name: "gasTarget", - type: "uint64", - }, - { - internalType: "uint64", - name: "ratio2x1x", - type: "uint64", - }, - ], - internalType: "struct TaikoL2.EIP1559Params", - name: "_param1559", - type: "tuple", - }, - ], - name: "init", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [], - name: "latestRelayedL1BlockId", - outputs: [ - { - internalType: "uint64", - name: "", - type: "uint64", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "owner", - outputs: [ - { - internalType: "address", - name: "", - type: "address", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "parentTimestamp", - outputs: [ - { - internalType: "uint64", - name: "", - type: "uint64", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "publicInputHash", - outputs: [ - { - internalType: "bytes32", - name: "", - type: "bytes32", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [], - name: "renounceOwnership", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [ - { - internalType: "uint256", - name: "chainId", - type: "uint256", - }, - { - internalType: "bytes32", - name: "name", - type: "bytes32", - }, - { - internalType: "bool", - name: "allowZeroAddress", - type: "bool", - }, - ], - name: "resolve", - outputs: [ - { - internalType: "address payable", - name: "", - type: "address", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "bytes32", - name: "name", - type: "bytes32", - }, - { - internalType: "bool", - name: "allowZeroAddress", - type: "bool", - }, - ], - name: "resolve", - outputs: [ - { - internalType: "address payable", - name: "", - type: "address", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "newAddressManager", - type: "address", - }, - ], - name: "setAddressManager", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, - { - inputs: [ - { - internalType: "bytes32", - name: "digest", - type: "bytes32", - }, - { - internalType: "uint8", - name: "k", - type: "uint8", - }, - ], - name: "signAnchor", - outputs: [ - { - internalType: "uint8", - name: "v", - type: "uint8", - }, - { - internalType: "uint256", - name: "r", - type: "uint256", - }, - { - internalType: "uint256", - name: "s", - type: "uint256", - }, - ], - stateMutability: "view", - type: "function", - }, - { - inputs: [ - { - internalType: "address", - name: "newOwner", - type: "address", - }, - ], - name: "transferOwnership", - outputs: [], - stateMutability: "nonpayable", - type: "function", - }, -];