Commit fca6e255 authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into inphi/host-chainid

parents 73f16c19 0511b47b
......@@ -887,6 +887,10 @@ jobs:
name: Build
command: make indexer
working_directory: indexer
- run:
name: Install node_modules
command: pnpm install --frozen-lockfile --prefer-offline
working_directory: indexer/api-ts
- run:
name: Install tygo
command: go install github.com/gzuidhof/tygo@latest
......
......@@ -13,3 +13,10 @@
[submodule "packages/contracts-bedrock/lib/forge-std"]
path = packages/contracts-bedrock/lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "packages/contracts-bedrock/lib/safe-contracts"]
path = packages/contracts-bedrock/lib/safe-contracts
url = https://github.com/safe-global/safe-contracts
branch = v1.4.0
......@@ -18,7 +18,7 @@ tests/
# Semgrep-action log folder
.semgrep_logs/
op-bindings/bindings
op-bindings/bindings/
packages/*/node_modules
packages/*/test
......@@ -8,12 +8,12 @@ export interface DepositItem {
from: string;
to: string;
timestamp: number /* uint64 */;
L1TxHash: string;
L2TxHash: string;
Block: string;
l1BlockHash: string;
l1TxHash: string;
l2TxHash: string;
amount: string;
l1Token: string;
l2Token: string;
l1TokenAddress: string;
l2TokenAddress: string;
}
export interface DepositResponse {
cursor: string;
......@@ -41,10 +41,10 @@ export interface WithdrawalItem {
timestamp: number /* uint64 */;
l2BlockHash: string;
amount: string;
proof: string;
claim: string;
l1Token: string;
l2Token: string;
proofTransactionHash: string;
claimTransactionHash: string;
l1TokenAddress: string;
l2TokenAddress: string;
}
export interface WithdrawalResponse {
cursor: string;
......
......@@ -38,10 +38,10 @@ var createQueryString = ({ cursor, limit }) => {
return `?${queries.join("&")}`;
};
var depositEndpoint = ({ baseUrl = "", address, cursor, limit }) => {
return [baseUrl, "deposits", address, createQueryString({ cursor, limit })].join("/");
return [baseUrl, "deposits", `${address}${createQueryString({ cursor, limit })}`].join("/");
};
var withdrawalEndoint = ({ baseUrl = "", address, cursor, limit }) => {
return [baseUrl, "withdrawals", address, createQueryString({ cursor, limit })].join("/");
return [baseUrl, "withdrawals", `${address}${createQueryString({ cursor, limit })}`].join("/");
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
......
{"version":3,"sources":["indexer.ts"],"sourcesContent":["export * from './generated'\n\ntype PaginationOptions = {\n limit?: number\n cursor?: string\n}\n\ntype Options = {\n baseUrl?: string\n address: `0x${string}`\n} & PaginationOptions\n\nconst createQueryString = ({ cursor, limit }: PaginationOptions): string => {\n if (cursor === undefined && limit === undefined) {\n return ''\n }\n const queries: string[] = []\n if (cursor) {\n queries.push(`cursor=${cursor}`)\n }\n if (limit) {\n queries.push(`limit=${limit}`)\n }\n return `?${queries.join('&')}`\n}\n\nexport const depositEndpoint = ({ baseUrl = '', address, cursor, limit }: Options): string => {\n return [baseUrl, 'deposits', address, createQueryString({ cursor, limit })].join('/')\n}\n\nexport const withdrawalEndoint = ({ baseUrl = '', address, cursor, limit }: Options): string => {\n return [baseUrl, 'withdrawals', address, createQueryString({ cursor, limit })].join('/')\n}\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYA,IAAM,oBAAoB,CAAC,EAAE,QAAQ,MAAM,MAAiC;AAC1E,MAAI,WAAW,UAAa,UAAU,QAAW;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,UAAoB,CAAC;AAC3B,MAAI,QAAQ;AACV,YAAQ,KAAK,UAAU,MAAM,EAAE;AAAA,EACjC;AACA,MAAI,OAAO;AACT,YAAQ,KAAK,SAAS,KAAK,EAAE;AAAA,EAC/B;AACA,SAAO,IAAI,QAAQ,KAAK,GAAG,CAAC;AAC9B;AAEO,IAAM,kBAAkB,CAAC,EAAE,UAAU,IAAI,SAAS,QAAQ,MAAM,MAAuB;AAC5F,SAAO,CAAC,SAAS,YAAY,SAAS,kBAAkB,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,KAAK,GAAG;AACtF;AAEO,IAAM,oBAAoB,CAAC,EAAE,UAAU,IAAI,SAAS,QAAQ,MAAM,MAAuB;AAC9F,SAAO,CAAC,SAAS,eAAe,SAAS,kBAAkB,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,KAAK,GAAG;AACzF;","names":[]}
\ No newline at end of file
{"version":3,"sources":["indexer.ts"],"sourcesContent":["export * from './generated'\n\ntype PaginationOptions = {\n limit?: number\n cursor?: string\n}\n\ntype Options = {\n baseUrl?: string\n address: `0x${string}`\n} & PaginationOptions\n\nconst createQueryString = ({ cursor, limit }: PaginationOptions): string => {\n if (cursor === undefined && limit === undefined) {\n return ''\n }\n const queries: string[] = []\n if (cursor) {\n queries.push(`cursor=${cursor}`)\n }\n if (limit) {\n queries.push(`limit=${limit}`)\n }\n return `?${queries.join('&')}`\n}\n\nexport const depositEndpoint = ({ baseUrl = '', address, cursor, limit }: Options): string => {\n return [baseUrl, 'deposits', `${address}${createQueryString({ cursor, limit })}`].join('/')\n}\n\nexport const withdrawalEndoint = ({ baseUrl = '', address, cursor, limit }: Options): string => {\n return [baseUrl, 'withdrawals', `${address}${createQueryString({ cursor, limit })}`].join('/')\n}\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYA,IAAM,oBAAoB,CAAC,EAAE,QAAQ,MAAM,MAAiC;AAC1E,MAAI,WAAW,UAAa,UAAU,QAAW;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,UAAoB,CAAC;AAC3B,MAAI,QAAQ;AACV,YAAQ,KAAK,UAAU,MAAM,EAAE;AAAA,EACjC;AACA,MAAI,OAAO;AACT,YAAQ,KAAK,SAAS,KAAK,EAAE;AAAA,EAC/B;AACA,SAAO,IAAI,QAAQ,KAAK,GAAG,CAAC;AAC9B;AAEO,IAAM,kBAAkB,CAAC,EAAE,UAAU,IAAI,SAAS,QAAQ,MAAM,MAAuB;AAC5F,SAAO,CAAC,SAAS,YAAY,GAAG,OAAO,GAAG,kBAAkB,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,EAAE,KAAK,GAAG;AAC5F;AAEO,IAAM,oBAAoB,CAAC,EAAE,UAAU,IAAI,SAAS,QAAQ,MAAM,MAAuB;AAC9F,SAAO,CAAC,SAAS,eAAe,GAAG,OAAO,GAAG,kBAAkB,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,EAAE,KAAK,GAAG;AAC/F;","names":[]}
\ No newline at end of file
......@@ -13,10 +13,10 @@ var createQueryString = ({ cursor, limit }) => {
return `?${queries.join("&")}`;
};
var depositEndpoint = ({ baseUrl = "", address, cursor, limit }) => {
return [baseUrl, "deposits", address, createQueryString({ cursor, limit })].join("/");
return [baseUrl, "deposits", `${address}${createQueryString({ cursor, limit })}`].join("/");
};
var withdrawalEndoint = ({ baseUrl = "", address, cursor, limit }) => {
return [baseUrl, "withdrawals", address, createQueryString({ cursor, limit })].join("/");
return [baseUrl, "withdrawals", `${address}${createQueryString({ cursor, limit })}`].join("/");
};
export {
depositEndpoint,
......
{"version":3,"sources":["indexer.ts"],"sourcesContent":["export * from './generated'\n\ntype PaginationOptions = {\n limit?: number\n cursor?: string\n}\n\ntype Options = {\n baseUrl?: string\n address: `0x${string}`\n} & PaginationOptions\n\nconst createQueryString = ({ cursor, limit }: PaginationOptions): string => {\n if (cursor === undefined && limit === undefined) {\n return ''\n }\n const queries: string[] = []\n if (cursor) {\n queries.push(`cursor=${cursor}`)\n }\n if (limit) {\n queries.push(`limit=${limit}`)\n }\n return `?${queries.join('&')}`\n}\n\nexport const depositEndpoint = ({ baseUrl = '', address, cursor, limit }: Options): string => {\n return [baseUrl, 'deposits', address, createQueryString({ cursor, limit })].join('/')\n}\n\nexport const withdrawalEndoint = ({ baseUrl = '', address, cursor, limit }: Options): string => {\n return [baseUrl, 'withdrawals', address, createQueryString({ cursor, limit })].join('/')\n}\n\n"],"mappings":";AAYA,IAAM,oBAAoB,CAAC,EAAE,QAAQ,MAAM,MAAiC;AAC1E,MAAI,WAAW,UAAa,UAAU,QAAW;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,UAAoB,CAAC;AAC3B,MAAI,QAAQ;AACV,YAAQ,KAAK,UAAU,MAAM,EAAE;AAAA,EACjC;AACA,MAAI,OAAO;AACT,YAAQ,KAAK,SAAS,KAAK,EAAE;AAAA,EAC/B;AACA,SAAO,IAAI,QAAQ,KAAK,GAAG,CAAC;AAC9B;AAEO,IAAM,kBAAkB,CAAC,EAAE,UAAU,IAAI,SAAS,QAAQ,MAAM,MAAuB;AAC5F,SAAO,CAAC,SAAS,YAAY,SAAS,kBAAkB,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,KAAK,GAAG;AACtF;AAEO,IAAM,oBAAoB,CAAC,EAAE,UAAU,IAAI,SAAS,QAAQ,MAAM,MAAuB;AAC9F,SAAO,CAAC,SAAS,eAAe,SAAS,kBAAkB,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,KAAK,GAAG;AACzF;","names":[]}
\ No newline at end of file
{"version":3,"sources":["indexer.ts"],"sourcesContent":["export * from './generated'\n\ntype PaginationOptions = {\n limit?: number\n cursor?: string\n}\n\ntype Options = {\n baseUrl?: string\n address: `0x${string}`\n} & PaginationOptions\n\nconst createQueryString = ({ cursor, limit }: PaginationOptions): string => {\n if (cursor === undefined && limit === undefined) {\n return ''\n }\n const queries: string[] = []\n if (cursor) {\n queries.push(`cursor=${cursor}`)\n }\n if (limit) {\n queries.push(`limit=${limit}`)\n }\n return `?${queries.join('&')}`\n}\n\nexport const depositEndpoint = ({ baseUrl = '', address, cursor, limit }: Options): string => {\n return [baseUrl, 'deposits', `${address}${createQueryString({ cursor, limit })}`].join('/')\n}\n\nexport const withdrawalEndoint = ({ baseUrl = '', address, cursor, limit }: Options): string => {\n return [baseUrl, 'withdrawals', `${address}${createQueryString({ cursor, limit })}`].join('/')\n}\n\n"],"mappings":";AAYA,IAAM,oBAAoB,CAAC,EAAE,QAAQ,MAAM,MAAiC;AAC1E,MAAI,WAAW,UAAa,UAAU,QAAW;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,UAAoB,CAAC;AAC3B,MAAI,QAAQ;AACV,YAAQ,KAAK,UAAU,MAAM,EAAE;AAAA,EACjC;AACA,MAAI,OAAO;AACT,YAAQ,KAAK,SAAS,KAAK,EAAE;AAAA,EAC/B;AACA,SAAO,IAAI,QAAQ,KAAK,GAAG,CAAC;AAC9B;AAEO,IAAM,kBAAkB,CAAC,EAAE,UAAU,IAAI,SAAS,QAAQ,MAAM,MAAuB;AAC5F,SAAO,CAAC,SAAS,YAAY,GAAG,OAAO,GAAG,kBAAkB,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,EAAE,KAAK,GAAG;AAC5F;AAEO,IAAM,oBAAoB,CAAC,EAAE,UAAU,IAAI,SAAS,QAAQ,MAAM,MAAuB;AAC9F,SAAO,CAAC,SAAS,eAAe,GAAG,OAAO,GAAG,kBAAkB,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,EAAE,KAAK,GAAG;AAC/F;","names":[]}
\ No newline at end of file
import { test, expect } from 'vitest'
import { depositEndpoint, withdrawalEndoint } from './indexer.ts'
test(depositEndpoint.name, () => {
expect(depositEndpoint({ baseUrl: 'http://localhost:8080/api/v0', address: '0x1234', cursor: '0x1235', limit: 10 })).toMatchInlineSnapshot('"http://localhost:8080/api/v0/deposits/0x1234?cursor=0x1235&limit=10"')
expect(depositEndpoint({ baseUrl: 'http://localhost:8080/api/v0', address: '0x1234' })).toMatchInlineSnapshot('"http://localhost:8080/api/v0/deposits/0x1234"')
})
test(withdrawalEndoint.name, () => {
expect(withdrawalEndoint({ baseUrl: 'http://localhost:8080/api/v0', address: '0x1234', cursor: '0x1235', limit: 10 })).toMatchInlineSnapshot('"http://localhost:8080/api/v0/withdrawals/0x1234?cursor=0x1235&limit=10"')
expect(withdrawalEndoint({ baseUrl: 'http://localhost:8080/api/v0', address: '0x1234' })).toMatchInlineSnapshot('"http://localhost:8080/api/v0/withdrawals/0x1234"')
})
......@@ -25,10 +25,10 @@ const createQueryString = ({ cursor, limit }: PaginationOptions): string => {
}
export const depositEndpoint = ({ baseUrl = '', address, cursor, limit }: Options): string => {
return [baseUrl, 'deposits', address, createQueryString({ cursor, limit })].join('/')
return [baseUrl, 'deposits', `${address}${createQueryString({ cursor, limit })}`].join('/')
}
export const withdrawalEndoint = ({ baseUrl = '', address, cursor, limit }: Options): string => {
return [baseUrl, 'withdrawals', address, createQueryString({ cursor, limit })].join('/')
return [baseUrl, 'withdrawals', `${address}${createQueryString({ cursor, limit })}`].join('/')
}
{
"name": "@eth-optimism/indexer-api",
"version": "0.0.1",
"version": "0.0.3",
"description": "[Optimism] typescript types for the indexer service",
"main": "indexer.cjs",
"module": "indexer.js",
......@@ -17,7 +17,8 @@
],
"scripts": {
"clean": "rm -rf generated.ts indexer.cjs indexer.js",
"generate": "npm run clean && tygo generate && mv ../api/routes/index.ts generated.ts && npx tsup"
"generate": "npm run clean && tygo generate && mv ../api/routes/index.ts generated.ts && tsup",
"test": "vitest"
},
"keywords": [
"optimism",
......@@ -30,4 +31,9 @@
"repository": {
"type": "git",
"url": "https://github.com/ethereum-optimism/optimism.git"
}}
},
"devDependencies": {
"tsup": "^7.2.0",
"vitest": "^0.34.4"
}
}
......@@ -4,7 +4,7 @@
"strict": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"moduleResolution": "NodeNext",
"jsx": "react",
"target": "ESNext",
"noEmit": true
......
......@@ -14,12 +14,12 @@ type DepositItem struct {
From string `json:"from"`
To string `json:"to"`
Timestamp uint64 `json:"timestamp"`
L1TxHash string `json:"L1TxHash"`
L2TxHash string `json:"L2TxHash"`
L1BlockHash string `json:"Block"`
L1BlockHash string `json:"l1BlockHash"`
L1TxHash string `json:"l1TxHash"`
L2TxHash string `json:"l2TxHash"`
Amount string `json:"amount"`
L1TokenAddress string `json:"l1Token"`
L2TokenAddress string `json:"l2Token"`
L1TokenAddress string `json:"l1TokenAddress"`
L2TokenAddress string `json:"l2TokenAddress"`
}
type DepositResponse struct {
......
......@@ -17,10 +17,10 @@ type WithdrawalItem struct {
Timestamp uint64 `json:"timestamp"`
L2BlockHash string `json:"l2BlockHash"`
Amount string `json:"amount"`
ProofTransactionHash string `json:"proof"`
ClaimTransactionHash string `json:"claim"`
L1TokenAddress string `json:"l1Token"`
L2TokenAddress string `json:"l2Token"`
ProofTransactionHash string `json:"proofTransactionHash"`
ClaimTransactionHash string `json:"claimTransactionHash"`
L1TokenAddress string `json:"l1TokenAddress"`
L2TokenAddress string `json:"l2TokenAddress"`
}
type WithdrawalResponse struct {
......
......@@ -36,5 +36,8 @@
"BlockOracle",
"EAS",
"SchemaRegistry",
"ProtocolVersions"
"ProtocolVersions",
"Safe",
"SafeProxyFactory",
"DelayedVetoable"
]
This diff is collapsed.
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindings
import (
"encoding/json"
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const DelayedVetoableStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/L1/DelayedVetoable.sol:DelayedVetoable\",\"label\":\"_delay\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint256\"},{\"astId\":1001,\"contract\":\"src/L1/DelayedVetoable.sol:DelayedVetoable\",\"label\":\"_queuedAt\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_bytes32,t_uint256)\"}],\"types\":{\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_uint256\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
var DelayedVetoableStorageLayout = new(solc.StorageLayout)
var DelayedVetoableDeployedBin = "0x608060405234801561001057600080fd5b50600436106100725760003560e01c8063b912de5d11610050578063b912de5d14610111578063d4b8399214610124578063d8bff4401461012c57610072565b806354fd4d501461007c5780635c39fcc1146100ce5780636a42b8f8146100fb575b61007a610134565b005b6100b86040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100c591906106a7565b60405180910390f35b6100d66104fb565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100c5565b610103610532565b6040519081526020016100c5565b61010361011f36600461071a565b610540565b6100d6610567565b6100d6610593565b361580156101425750600054155b15610298573373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015906101c357503373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614155b1561023d576040517f295a81c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660048201523360248201526044015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000060008190556040519081527febf28bfb587e28dfffd9173cf71c32ba5d3f0544a0117b5539c9b274a5bba2a89060200160405180910390a1565b600080366040516102aa929190610733565b60405190819003902090503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103065750600081815260016020526040902054155b1561036c5760005460000361031e5761031e816105bf565b6000818152600160205260408082204290555182917f87a332a414acbc7da074543639ce7ae02ff1ea72e88379da9f261b080beb5a139161036191903690610743565b60405180910390a250565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103be575060008181526001602052604090205415155b15610406576000818152600160205260408082208290555182917fbede6852c1d97d93ff557f676de76670cd0dec861e7fe8beb13aa0ba2b0ab0409161036191903690610743565b600081815260016020526040812054900361048b576040517f295a81c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152336024820152604401610234565b60008054828252600160205260409091205442916104a891610790565b10156104e0576040517f43dc986d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600160205260408120556104f8816105bf565b50565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b61052f610134565b90565b600033610527575060005490565b60003361055a575060009081526001602052604090205490565b610562610134565b919050565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b807f4c109d85bcd0bb5c735b4be850953d652afe4cd9aa2e0b1426a65a4dcb2e12296000366040516105f2929190610743565b60405180910390a26000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16600036604051610645929190610733565b6000604051808303816000865af19150503d8060008114610682576040519150601f19603f3d011682016040523d82523d6000602084013e610687565b606091505b50909250905081151560010361069f57805160208201f35b805160208201fd5b600060208083528351808285015260005b818110156106d4578581018301518582016040015282016106b8565b818111156106e6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561072c57600080fd5b5035919050565b8183823760009101908152919050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b600082198211156107ca577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fea164736f6c634300080f000a"
func init() {
if err := json.Unmarshal([]byte(DelayedVetoableStorageLayoutJSON), DelayedVetoableStorageLayout); err != nil {
panic(err)
}
layouts["DelayedVetoable"] = DelayedVetoableStorageLayout
deployedBytecodes["DelayedVetoable"] = DelayedVetoableDeployedBin
}
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package bindings
import (
"encoding/json"
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const SafeProxyFactoryStorageLayoutJSON = "{\"storage\":null,\"types\":{}}"
var SafeProxyFactoryStorageLayout = new(solc.StorageLayout)
var SafeProxyFactoryDeployedBin = "0x608060405234801561001057600080fd5b50600436106100675760003560e01c806353e5d9351161005057806353e5d935146100b7578063d18af54d146100cc578063ec9e80bb146100df57600080fd5b80631688f0b91461006c5780633408e470146100a9575b600080fd5b61007f61007a3660046105d2565b6100f2565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6040514681526020016100a0565b6100bf610194565b6040516100a091906106a5565b61007f6100da3660046106bf565b6101dc565b61007f6100ed3660046105d2565b6102f8565b600080838051906020012083604051602001610118929190918252602082015260400190565b60405160208183030381529060405280519060200120905061013b85858361032a565b60405173ffffffffffffffffffffffffffffffffffffffff8781168252919350908316907f4f51faf6c4561ff95f067657e43439f0f856d97c04d9ec9070a6199ad418e2359060200160405180910390a2509392505050565b6060604051806020016101a6906104c6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604052919050565b600080838360405160200161022092919091825260601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602082015260340190565b6040516020818303038152906040528051906020012060001c90506102468686836100f2565b915073ffffffffffffffffffffffffffffffffffffffff8316156102ef576040517f1e52b51800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690631e52b518906102bc9085908a908a908a9060040161072b565b600060405180830381600087803b1580156102d657600080fd5b505af11580156102ea573d6000803e3d6000fd5b505050505b50949350505050565b60008083805190602001208361030b4690565b6040805160208101949094528301919091526060820152608001610118565b6000833b610399576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53696e676c65746f6e20636f6e7472616374206e6f74206465706c6f7965640060448201526064015b60405180910390fd5b6000604051806020016103ab906104c6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052610403919073ffffffffffffffffffffffffffffffffffffffff881690602001610775565b6040516020818303038152906040529050828151826020016000f5915073ffffffffffffffffffffffffffffffffffffffff821661049d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f437265617465322063616c6c206661696c6564000000000000000000000000006044820152606401610390565b8351156104be5760008060008651602088016000875af1036104be57600080fd5b509392505050565b61016f8061079883390190565b73ffffffffffffffffffffffffffffffffffffffff811681146104f557600080fd5b50565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261053857600080fd5b813567ffffffffffffffff80821115610553576105536104f8565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610599576105996104f8565b816040528381528660208588010111156105b257600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000606084860312156105e757600080fd5b83356105f2816104d3565b9250602084013567ffffffffffffffff81111561060e57600080fd5b61061a86828701610527565b925050604084013590509250925092565b60005b8381101561064657818101518382015260200161062e565b83811115610655576000848401525b50505050565b6000815180845261067381602086016020860161062b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006106b8602083018461065b565b9392505050565b600080600080608085870312156106d557600080fd5b84356106e0816104d3565b9350602085013567ffffffffffffffff8111156106fc57600080fd5b61070887828801610527565b935050604085013591506060850135610720816104d3565b939692955090935050565b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525060806040830152610764608083018561065b565b905082606083015295945050505050565b6000835161078781846020880161062b565b919091019182525060200191905056fe608060405234801561001057600080fd5b5060405161016f38038061016f83398101604081905261002f916100b9565b6001600160a01b0381166100945760405162461bcd60e51b815260206004820152602260248201527f496e76616c69642073696e676c65746f6e20616464726573732070726f766964604482015261195960f21b606482015260840160405180910390fd5b600080546001600160a01b0319166001600160a01b03929092169190911790556100e9565b6000602082840312156100cb57600080fd5b81516001600160a01b03811681146100e257600080fd5b9392505050565b6078806100f76000396000f3fe6080604052600073ffffffffffffffffffffffffffffffffffffffff8154167fa619486e00000000000000000000000000000000000000000000000000000000823503604d57808252602082f35b3682833781823684845af490503d82833e806066573d82fd5b503d81f3fea164736f6c634300080f000aa164736f6c634300080f000a"
func init() {
if err := json.Unmarshal([]byte(SafeProxyFactoryStorageLayoutJSON), SafeProxyFactoryStorageLayout); err != nil {
panic(err)
}
layouts["SafeProxyFactory"] = SafeProxyFactoryStorageLayout
deployedBytecodes["SafeProxyFactory"] = SafeProxyFactoryDeployedBin
}
This diff is collapsed.
......@@ -13,7 +13,7 @@ const WETH9StorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src
var WETH9StorageLayout = new(solc.StorageLayout)
var WETH9DeployedBin = "0x6080604052600436106100bc5760003560e01c8063313ce56711610074578063a9059cbb1161004e578063a9059cbb146102cb578063d0e30db0146100bc578063dd62ed3e14610311576100bc565b8063313ce5671461024b57806370a082311461027657806395d89b41146102b6576100bc565b806318160ddd116100a557806318160ddd146101aa57806323b872dd146101d15780632e1a7d4d14610221576100bc565b806306fdde03146100c6578063095ea7b314610150575b6100c4610359565b005b3480156100d257600080fd5b506100db6103a8565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101155781810151838201526020016100fd565b50505050905090810190601f1680156101425780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015c57600080fd5b506101966004803603604081101561017357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610454565b604080519115158252519081900360200190f35b3480156101b657600080fd5b506101bf6104c7565b60408051918252519081900360200190f35b3480156101dd57600080fd5b50610196600480360360608110156101f457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356104cb565b34801561022d57600080fd5b506100c46004803603602081101561024457600080fd5b503561066b565b34801561025757600080fd5b50610260610700565b6040805160ff9092168252519081900360200190f35b34801561028257600080fd5b506101bf6004803603602081101561029957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610709565b3480156102c257600080fd5b506100db61071b565b3480156102d757600080fd5b50610196600480360360408110156102ee57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610793565b34801561031d57600080fd5b506101bf6004803603604081101561033457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166107a7565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b820191906000526020600020905b81548152906001019060200180831161042f57829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120548211156104fd57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610573575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105ed5773ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020548211156105b557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020805483900390555b73ffffffffffffffffffffffffffffffffffffffff808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b3360009081526003602052604090205481111561068757600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f193505050501580156106c6573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b60006107a03384846104cb565b9392505050565b60046020908152600092835260408084209091529082529020548156fea265627a7a7231582067ace7518c12acba9306ac90d5b712c789ea3d50860ef4996a20921a3c1e61f764736f6c63430005110032"
var WETH9DeployedBin = "0x6080604052600436106100bc5760003560e01c8063313ce56711610074578063a9059cbb1161004e578063a9059cbb146102cb578063d0e30db0146100bc578063dd62ed3e14610311576100bc565b8063313ce5671461024b57806370a082311461027657806395d89b41146102b6576100bc565b806318160ddd116100a557806318160ddd146101aa57806323b872dd146101d15780632e1a7d4d14610221576100bc565b806306fdde03146100c6578063095ea7b314610150575b6100c4610359565b005b3480156100d257600080fd5b506100db6103a8565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101155781810151838201526020016100fd565b50505050905090810190601f1680156101425780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015c57600080fd5b506101966004803603604081101561017357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610454565b604080519115158252519081900360200190f35b3480156101b657600080fd5b506101bf6104c7565b60408051918252519081900360200190f35b3480156101dd57600080fd5b50610196600480360360608110156101f457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135811691602081013590911690604001356104cb565b34801561022d57600080fd5b506100c46004803603602081101561024457600080fd5b503561066b565b34801561025757600080fd5b50610260610700565b6040805160ff9092168252519081900360200190f35b34801561028257600080fd5b506101bf6004803603602081101561029957600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610709565b3480156102c257600080fd5b506100db61071b565b3480156102d757600080fd5b50610196600480360360408110156102ee57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610793565b34801561031d57600080fd5b506101bf6004803603604081101561033457600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160200135166107a7565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b820191906000526020600020905b81548152906001019060200180831161042f57829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b4790565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120548211156104fd57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610573575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105ed5773ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020548211156105b557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020805483900390555b73ffffffffffffffffffffffffffffffffffffffff808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b3360009081526003602052604090205481111561068757600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f193505050501580156106c6573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f8101849004840282018401909252818152929183018282801561044c5780601f106104215761010080835404028352916020019161044c565b60006107a03384846104cb565b9392505050565b60046020908152600092835260408084209091529082529020548156fea265627a7a723158203b5b5adf37f507cc9ca5ac0b72acf7873b794171cc0eeb888a5f850e69fe540d64736f6c63430005110032"
func init() {
if err := json.Unmarshal([]byte(WETH9StorageLayoutJSON), WETH9StorageLayout); err != nil {
......
......@@ -422,7 +422,7 @@ func requiredArgs(traceType config.TraceType) map[string]string {
switch traceType {
case config.TraceTypeAlphabet:
args["--alphabet"] = alphabetTrace
case config.TraceTypeCannon:
case config.TraceTypeCannon, config.TraceTypeOutputCannon:
args["--cannon-network"] = cannonNetwork
args["--cannon-bin"] = cannonBin
args["--cannon-server"] = cannonServer
......
......@@ -39,6 +39,7 @@ type TraceType string
const (
TraceTypeAlphabet TraceType = "alphabet"
TraceTypeCannon TraceType = "cannon"
TraceTypeOutputCannon TraceType = "output_cannon"
// Mainnet games
CannonFaultGameID = 0
......@@ -47,7 +48,7 @@ const (
AlphabetFaultGameID = 255
)
var TraceTypes = []TraceType{TraceTypeAlphabet, TraceTypeCannon}
var TraceTypes = []TraceType{TraceTypeAlphabet, TraceTypeCannon, TraceTypeOutputCannon}
// GameIdToString maps game IDs to their string representation.
var GameIdToString = map[uint8]string{
......@@ -167,7 +168,7 @@ func (c Config) Check() error {
if c.MaxConcurrency == 0 {
return ErrMaxConcurrencyZero
}
if c.TraceType == TraceTypeCannon {
if c.TraceType == TraceTypeCannon || c.TraceType == TraceTypeOutputCannon {
if c.CannonBin == "" {
return ErrMissingCannonBin
}
......
......@@ -28,7 +28,7 @@ func validConfig(traceType TraceType) Config {
switch traceType {
case TraceTypeAlphabet:
cfg.AlphabetTrace = validAlphabetTrace
case TraceTypeCannon:
case TraceTypeCannon, TraceTypeOutputCannon:
cfg.CannonBin = validCannonBin
cfg.CannonServer = validCannonOpProgramBin
cfg.CannonAbsolutePreState = validCannonAbsolutPreState
......
......@@ -175,15 +175,7 @@ func init() {
// Flags contains the list of configuration options available to the binary.
var Flags []cli.Flag
func CheckRequired(ctx *cli.Context) error {
for _, f := range requiredFlags {
if !ctx.IsSet(f.Names()[0]) {
return fmt.Errorf("flag %s is required", f.Names()[0])
}
}
gameType := config.TraceType(strings.ToLower(ctx.String(TraceTypeFlag.Name)))
switch gameType {
case config.TraceTypeCannon:
func CheckCannonFlags(ctx *cli.Context) error {
if !ctx.IsSet(CannonNetworkFlag.Name) &&
!(ctx.IsSet(CannonRollupConfigFlag.Name) && ctx.IsSet(CannonL2GenesisFlag.Name)) {
return fmt.Errorf("flag %v or %v and %v is required",
......@@ -206,10 +198,29 @@ func CheckRequired(ctx *cli.Context) error {
if !ctx.IsSet(CannonL2Flag.Name) {
return fmt.Errorf("flag %s is required", CannonL2Flag.Name)
}
return nil
}
func CheckRequired(ctx *cli.Context) error {
for _, f := range requiredFlags {
if !ctx.IsSet(f.Names()[0]) {
return fmt.Errorf("flag %s is required", f.Names()[0])
}
}
gameType := config.TraceType(strings.ToLower(ctx.String(TraceTypeFlag.Name)))
switch gameType {
case config.TraceTypeCannon:
if err := CheckCannonFlags(ctx); err != nil {
return err
}
case config.TraceTypeAlphabet:
if !ctx.IsSet(AlphabetFlag.Name) {
return fmt.Errorf("flag %s is required", "alphabet")
}
case config.TraceTypeOutputCannon:
if err := CheckCannonFlags(ctx); err != nil {
return err
}
default:
return fmt.Errorf("invalid trace type. must be one of %v", config.TraceTypes)
}
......
......@@ -49,6 +49,9 @@ type OpNode struct {
resourcesCtx context.Context
resourcesClose context.CancelFunc
// Indicates when it's safe to close data sources used by the runtimeConfig bg loader
runtimeConfigReloaderDone chan struct{}
closed atomic.Bool
}
......@@ -197,9 +200,8 @@ func (n *OpNode) initRuntimeConfig(ctx context.Context, cfg *Config) error {
return l1Head, err
}
n.handleProtocolVersionsUpdate(ctx)
return l1Head, nil
err = n.handleProtocolVersionsUpdate(ctx)
return l1Head, err
}
// initialize the runtime config before unblocking
......@@ -210,10 +212,10 @@ func (n *OpNode) initRuntimeConfig(ctx context.Context, cfg *Config) error {
}
// start a background loop, to keep reloading it at the configured reload interval
go func(ctx context.Context, reloadInterval time.Duration) {
reloader := func(ctx context.Context, reloadInterval time.Duration) bool {
if reloadInterval <= 0 {
n.log.Debug("not running runtime-config reloading background loop")
return
return false
}
ticker := time.NewTicker(reloadInterval)
defer ticker.Stop()
......@@ -222,13 +224,30 @@ func (n *OpNode) initRuntimeConfig(ctx context.Context, cfg *Config) error {
case <-ticker.C:
// If the reload fails, we will try again the next interval.
// Missing a runtime-config update is not critical, and we do not want to overwhelm the L1 RPC.
if l1Head, err := reload(ctx); err != nil {
n.log.Warn("failed to reload runtime config", "err", err)
} else {
l1Head, err := reload(ctx)
switch err {
case errNodeHalt, nil:
n.log.Debug("reloaded runtime config", "l1_head", l1Head)
if err == errNodeHalt {
return true
}
default:
n.log.Warn("failed to reload runtime config", "err", err)
}
case <-ctx.Done():
return
return false
}
}
}
n.runtimeConfigReloaderDone = make(chan struct{})
// Manages the lifetime of reloader. In order to safely Close the OpNode
go func(ctx context.Context, reloadInterval time.Duration) {
halt := reloader(ctx, reloadInterval)
close(n.runtimeConfigReloaderDone)
if halt {
if err := n.Close(); err != nil {
n.log.Error("Failed to halt rollup", "err", err)
}
}
}(n.resourcesCtx, cfg.RuntimeConfigReloadInterval) // this keeps running after initialization
......@@ -499,6 +518,11 @@ func (n *OpNode) Close() error {
}
}
// Wait for the runtime config loader to be done using the data sources before closing them
if n.runtimeConfigReloaderDone != nil {
<-n.runtimeConfigReloaderDone
}
// close L2 engine RPC client
if n.l2Source != nil {
n.l2Source.Close()
......
......@@ -2,18 +2,21 @@ package node
import (
"context"
"errors"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum/go-ethereum/eth/catalyst"
"github.com/ethereum/go-ethereum/params"
)
func (n *OpNode) handleProtocolVersionsUpdate(ctx context.Context) {
var errNodeHalt = errors.New("opted to halt, unprepared for protocol change")
func (n *OpNode) handleProtocolVersionsUpdate(ctx context.Context) error {
recommended := n.runCfg.RecommendedProtocolVersion()
required := n.runCfg.RequiredProtocolVersion()
// if the protocol version sources are disabled we do not process them
if recommended == (params.ProtocolVersion{}) && required == (params.ProtocolVersion{}) {
return
return nil
}
local := rollup.OPStackSupport
// forward to execution engine, and get back the protocol version that op-geth supports
......@@ -30,20 +33,20 @@ func (n *OpNode) handleProtocolVersionsUpdate(ctx context.Context) {
catalyst.LogProtocolVersionSupport(n.log.New("node", "engine"), local, required, "required")
// We may need to halt the node, if the user opted in to handling incompatible protocol-version signals
n.HaltMaybe()
return n.haltMaybe()
}
// HaltMaybe halts the rollup node if the runtime config indicates an incompatible required protocol change
// haltMaybe returns errNodeHalt if the runtime config indicates an incompatible required protocol change
// and the node is configured to opt-in to halting at this protocol-change level.
func (n *OpNode) HaltMaybe() {
func (n *OpNode) haltMaybe() error {
local := rollup.OPStackSupport
required := n.runCfg.RequiredProtocolVersion()
if haltMaybe(n.rollupHalt, local.Compare(required)) { // halt if we opted in to do so at this granularity
n.log.Error("Opted to halt, unprepared for protocol change", "required", required, "local", local)
if err := n.Close(); err != nil {
n.log.Error("Failed to halt rollup", "err", err)
}
// Avoid deadlocking the runtime config reloader by closing the OpNode elsewhere
return errNodeHalt
}
return nil
}
// haltMaybe returns true when we should halt, given the halt-option and required-version comparison
......
FROM ethereum/client-go:v1.13.0
FROM ethereum/client-go:v1.13.1
RUN apk add --no-cache jq
......
......@@ -46,6 +46,9 @@ CrossDomainOwnable3_Test:test_transferOwnership_zeroAddress_reverts() (gas: 1208
CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner_succeeds() (gas: 81417)
CrossDomainOwnable_Test:test_onlyOwner_notOwner_reverts() (gas: 10597)
CrossDomainOwnable_Test:test_onlyOwner_succeeds() (gas: 34883)
DelayedVetoable_Getters_Test:test_getters() (gas: 21342)
DelayedVetoable_Getters_TestFail:test_getters_notZeroAddress_reverts() (gas: 26649)
DelayedVetoable_HandleCall_TestFail:test_handleCall_unauthorizedInitiation_reverts() (gas: 20234)
DeleteOutput:test_script_succeeds() (gas: 3100)
DeployerWhitelist_Test:test_owner_succeeds() (gas: 7582)
DeployerWhitelist_Test:test_storageSlots_succeeds() (gas: 33395)
......
......@@ -16,7 +16,8 @@ remappings = [
'@rari-capital/solmate/=lib/solmate',
'@cwia/=lib/clones-with-immutable-args/src',
'forge-std/=lib/forge-std/src',
'ds-test/=lib/forge-std/lib/ds-test/src'
'ds-test/=lib/forge-std/lib/ds-test/src',
'safe-contracts/=lib/safe-contracts/contracts'
]
extra_output = ['devdoc', 'userdoc', 'metadata', 'storageLayout']
bytecode_hash = 'none'
......
Subproject commit e870f514ad34cd9654c72174d6d4a839e3c6639f
......@@ -9,6 +9,8 @@ import { stdJson } from "forge-std/StdJson.sol";
import { Deployer } from "./Deployer.sol";
import { DeployConfig } from "./DeployConfig.s.sol";
import { Safe } from "safe-contracts/Safe.sol";
import { SafeProxyFactory } from "safe-contracts/proxies/SafeProxyFactory.sol";
import { ProxyAdmin } from "src/universal/ProxyAdmin.sol";
import { AddressManager } from "src/legacy/AddressManager.sol";
import { Proxy } from "src/universal/Proxy.sol";
......
{
"src/EAS/EAS.sol": "0x1acb25751a1206eb859cc5fcf934da2f84cfb907b8e8951d86fc4e43c53a7303",
"src/EAS/SchemaRegistry.sol": "0x305f3afed2e337cd70aac70fc202e6503b947b0a31e0d4e18c49486eeb635bb5",
"src/L1/DelayedVetoable.sol": "0x276c6276292095e6aa37a70008cf4e0d1cbcc020dbc9107459bbc72ab5ed744f",
"src/L1/L1CrossDomainMessenger.sol": "0x14f5991022705b8bd3bf931e138a528cc9c9e90d0f1ec398efd5079224d61b3b",
"src/L1/L1ERC721Bridge.sol": "0x3e0e3d2f4c151e41585850f06e6452cdda86348debfe6ff16e364a839266450b",
"src/L1/L1StandardBridge.sol": "0x12e227c6054660a83b92d823a7447db96a7d476b7a94e0f1807772d400329880",
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { ISemver } from "src/universal/ISemver.sol";
/// @title DelayedVetoable
/// @notice This contract enables a delay before a call is forwarded to a target contract, and during the delay period
/// the call can be vetoed by the authorized vetoer.
/// This contract does not support value transfers, only data is forwarded.
/// Additionally, this contract cannot be used to forward calls with data beginning with the function selector
/// of the queuedAt(bytes32) function. This is because of input validation checks which solidity performs at
/// runtime on functions which take an argument.
contract DelayedVetoable is ISemver {
/// @notice Error for when the delay has already been set.
error AlreadyDelayed();
/// @notice Error for when attempting to forward too early.
error ForwardingEarly();
/// @notice Error for the target is not set.
error TargetUnitialized();
/// @notice Error for unauthorized calls.
error Unauthorized(address expected, address actual);
/// @notice An event that is emitted when the delay is activated.
/// @param delay The delay that was activated.
event DelayActivated(uint256 delay);
/// @notice An event that is emitted when a call is initiated.
/// @param callHash The hash of the call data.
/// @param data The data of the initiated call.
event Initiated(bytes32 indexed callHash, bytes data);
/// @notice An event that is emitted each time a call is forwarded.
/// @param callHash The hash of the call data.
/// @param data The data forwarded to the target.
event Forwarded(bytes32 indexed callHash, bytes data);
/// @notice An event that is emitted each time a call is vetoed.
/// @param callHash The hash of the call data.
/// @param data The data forwarded to the target.
event Vetoed(bytes32 indexed callHash, bytes data);
/// @notice The address that all calls are forwarded to after the delay.
address internal immutable TARGET;
/// @notice The address that can veto a call.
address internal immutable VETOER;
/// @notice The address that can initiate a call.
address internal immutable INITIATOR;
/// @notice The delay which will be set after the initial system deployment is completed.
uint256 internal immutable OPERATING_DELAY;
/// @notice The current amount of time to wait before forwarding a call.
uint256 internal _delay;
/// @notice The time that a call was initiated.
mapping(bytes32 => uint256) internal _queuedAt;
/// @notice A modifier that reverts if not called by the vetoer or by address(0) to allow
/// eth_call to interact with this proxy without needing to use low-level storage
/// inspection. We assume that nobody is able to trigger calls from address(0) during
/// normal EVM execution.
modifier readOrHandle() {
if (msg.sender == address(0)) {
_;
} else {
// This WILL halt the call frame on completion.
_handleCall();
}
}
/// @notice Semantic version.
/// @custom:semver 1.0.0
string public constant version = "1.0.0";
/// @notice Sets the target admin during contract deployment.
/// @param vetoer_ Address of the vetoer.
/// @param initiator_ Address of the initiator.
/// @param target_ Address of the target.
/// @param operatingDelay_ Time to delay when the system is operational.
constructor(address vetoer_, address initiator_, address target_, uint256 operatingDelay_) {
// Note that the _delay value is not set here. Having an initial delay of 0 is helpful
// during the deployment of a new system.
VETOER = vetoer_;
INITIATOR = initiator_;
TARGET = target_;
OPERATING_DELAY = operatingDelay_;
}
/// @notice Gets the initiator
/// @return initiator_ Initiator address.
function initiator() external virtual readOrHandle returns (address initiator_) {
initiator_ = INITIATOR;
}
//// @notice Queries the vetoer address.
/// @return vetoer_ Vetoer address.
function vetoer() external virtual readOrHandle returns (address vetoer_) {
vetoer_ = VETOER;
}
//// @notice Queries the target address.
/// @return target_ Target address.
function target() external readOrHandle returns (address target_) {
target_ = TARGET;
}
/// @notice Gets the delay
/// @return delay_ Delay address.
function delay() external readOrHandle returns (uint256 delay_) {
delay_ = _delay;
}
/// @notice Gets entries in the _queuedAt mapping.
/// @param callHash The hash of the call data.
/// @return queuedAt_ The time the callHash was recorded.
function queuedAt(bytes32 callHash) external readOrHandle returns (uint256 queuedAt_) {
queuedAt_ = _queuedAt[callHash];
}
/// @notice Used for all calls that pass data to the contract.
fallback() external {
_handleCall();
}
/// @notice Receives all calls other than those made by the vetoer.
/// This enables transparent initiation and forwarding of calls to the target and avoids
/// the need for additional layers of abi encoding.
function _handleCall() internal {
// The initiator and vetoer activate the delay by passing in null data.
if (msg.data.length == 0 && _delay == 0) {
if (msg.sender != INITIATOR && msg.sender != VETOER) {
revert Unauthorized(INITIATOR, msg.sender);
}
_delay = OPERATING_DELAY;
emit DelayActivated(_delay);
return;
}
bytes32 callHash = keccak256(msg.data);
// Case 1: The initiator is calling the contract to initiate a call.
if (msg.sender == INITIATOR && _queuedAt[callHash] == 0) {
if (_delay == 0) {
// This forward function will halt the call frame on completion.
_forwardAndHalt(callHash);
}
_queuedAt[callHash] = block.timestamp;
emit Initiated(callHash, msg.data);
return;
}
// Case 2: The vetoer is calling the contract to veto a call.
// Note: The vetoer retains the ability to veto even after the delay has passed. This makes censoring the vetoer
// more costly, as there is no time limit after which their transaction can be included.
if (msg.sender == VETOER && _queuedAt[callHash] != 0) {
delete _queuedAt[callHash];
emit Vetoed(callHash, msg.data);
return;
}
// Case 3: The call is from an unpermissioned actor. We'll forward the call if the delay has
// passed.
if (_queuedAt[callHash] == 0) {
// The call has not been initiated, so we'll treat this is an unauthorized initiation attempt.
revert Unauthorized(INITIATOR, msg.sender);
}
if (_queuedAt[callHash] + _delay < block.timestamp) {
// Not enough time has passed, so we'll revert.
revert ForwardingEarly();
}
// Delete the call to prevent replays
delete _queuedAt[callHash];
_forwardAndHalt(callHash);
}
/// @notice Forwards the call to the target and halts the call frame.
function _forwardAndHalt(bytes32 callHash) internal {
// Forward the call
emit Forwarded(callHash, msg.data);
(bool success, bytes memory returndata) = TARGET.call(msg.data);
if (success == true) {
assembly {
return(add(returndata, 0x20), mload(returndata))
}
} else {
assembly {
revert(add(returndata, 0x20), mload(returndata))
}
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { CommonTest } from "./CommonTest.t.sol";
import { DelayedVetoable } from "src/L1/DelayedVetoable.sol";
contract DelayedVetoable_Init is CommonTest {
error Unauthorized(address expected, address actual);
error ForwardingEarly();
event Initiated(bytes32 indexed callHash, bytes data);
event Forwarded(bytes32 indexed callHash, bytes data);
event Vetoed(bytes32 indexed callHash, bytes data);
address target = address(0xabba);
address initiator = alice;
address vetoer = bob;
uint256 operatingDelay = 14 days;
DelayedVetoable delayedVetoable;
function setUp() public override {
super.setUp();
delayedVetoable = new DelayedVetoable({
initiator_: alice,
vetoer_: bob,
target_: address(target),
operatingDelay_: operatingDelay
});
// Most tests will use the operating delay, so we call as the initiator with null data
// to set the delay. For tests that need to use the initial zero delay, we'll modify the
// value in storage.
vm.prank(initiator);
(bool success,) = address(delayedVetoable).call(hex"");
}
/// @dev This function is used to prevent initiating the delay unintentionally..
/// @param data The data to be used in the call.
function assumeNonzeroData(bytes memory data) internal pure {
vm.assume(data.length > 0);
}
}
contract DelayedVetoable_Getters_Test is DelayedVetoable_Init {
/// @dev The getters return the expected values when called by the zero address.
function test_getters() external {
vm.startPrank(address(0));
assertEq(delayedVetoable.initiator(), initiator);
assertEq(delayedVetoable.vetoer(), vetoer);
assertEq(delayedVetoable.target(), target);
assertEq(delayedVetoable.delay(), operatingDelay);
}
}
contract DelayedVetoable_Getters_TestFail is DelayedVetoable_Init {
/// @dev Check that getter calls from unauthorized entities will revert.
function test_getters_notZeroAddress_reverts() external {
vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this)));
delayedVetoable.initiator();
vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this)));
delayedVetoable.vetoer();
vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this)));
delayedVetoable.target();
vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this)));
delayedVetoable.delay();
}
}
contract DelayedVetoable_HandleCall_Test is DelayedVetoable_Init {
/// @dev A call can be initiated by the initiator.
function testFuzz_handleCall_initiation_succeeds(bytes memory data) external {
assumeNonzeroData(data);
vm.expectEmit(true, false, false, true, address(delayedVetoable));
emit Initiated(keccak256(data), data);
vm.prank(initiator);
(bool success,) = address(delayedVetoable).call(data);
assertTrue(success);
}
/// @dev The delay is inititially set to zero and the call is immediately forwarded.
function testFuzz_handleCall_initialForwardingImmediately_succeeds(
bytes calldata inData,
bytes calldata outData
)
external
{
assumeNonzeroData(inData);
if (inData.length >= 4) {
vm.assume(bytes4(inData[0:4]) != bytes4(keccak256("queuedAt(bytes32)")));
}
// Reset the delay to zero
vm.store(address(delayedVetoable), bytes32(uint256(0)), bytes32(uint256(0)));
vm.mockCall(target, inData, outData);
vm.expectEmit(true, false, false, true, address(delayedVetoable));
vm.expectCall({ callee: target, data: inData });
emit Forwarded(keccak256(inData), inData);
vm.prank(initiator);
(bool success, bytes memory returnData) = address(delayedVetoable).call(inData);
assertTrue(success);
assertEq(returnData, outData);
}
/// @dev The delay can be activated by the vetoer or initiator, and are not forwarded until the delay has passed
/// once activated.
function testFuzz_handleCall_forwardingWithDelay_succeeds(bytes memory data) external {
assumeNonzeroData(data);
vm.prank(initiator);
(bool success,) = address(delayedVetoable).call(data);
// Check that the call is in the _queuedAt mapping
bytes32 callHash = keccak256(data);
vm.prank(address(0));
assertEq(delayedVetoable.queuedAt(callHash), block.timestamp);
vm.warp(block.timestamp + operatingDelay);
vm.expectEmit(true, false, false, true, address(delayedVetoable));
emit Forwarded(keccak256(data), data);
vm.expectCall({ callee: target, data: data });
(success,) = address(delayedVetoable).call(data);
assertTrue(success);
}
}
contract DelayedVetoable_HandleCall_TestFail is DelayedVetoable_Init {
/// @dev The delay is inititially set to zero and the call is immediately forwarded.
function test_handleCall_unauthorizedInitiation_reverts() external {
vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this)));
(bool success,) = address(delayedVetoable).call(NON_ZERO_DATA);
}
/// @dev The call cannot be forewarded until the delay has passed.
function testFuzz_handleCall_forwardingTooSoon_reverts(bytes memory data) external {
vm.prank(initiator);
(bool success,) = address(delayedVetoable).call(data);
vm.expectRevert(abi.encodeWithSelector(ForwardingEarly.selector));
(success,) = address(delayedVetoable).call(data);
}
/// @dev The call cannot be forwarded a second time.
function testFuzz_handleCall_forwardingTwice_reverts(bytes memory data) external {
assumeNonzeroData(data);
// Initiate the call
vm.prank(initiator);
(bool success,) = address(delayedVetoable).call(data);
vm.warp(block.timestamp + operatingDelay);
vm.expectEmit(true, false, false, true, address(delayedVetoable));
emit Forwarded(keccak256(data), data);
// Forward the call
vm.expectCall({ callee: target, data: data });
(success,) = address(delayedVetoable).call(data);
assertTrue(success);
// Attempt to foward the same call again.
vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this)));
(success,) = address(delayedVetoable).call(data);
assertTrue(success);
}
/// @dev If the target reverts, it is bubbled up.
function testFuzz_handleCall_forwardingTargetReverts_reverts(bytes memory inData, bytes memory outData) external {
assumeNonzeroData(inData);
// Initiate the call
vm.prank(initiator);
(bool success,) = address(delayedVetoable).call(inData);
vm.warp(block.timestamp + operatingDelay);
vm.expectEmit(true, false, false, true, address(delayedVetoable));
emit Forwarded(keccak256(inData), inData);
vm.mockCallRevert(target, inData, outData);
// Forward the call
vm.expectRevert(outData);
(bool success2,) = address(delayedVetoable).call(inData);
}
/// @dev A test documenting the single instance in which the contract is not 'transparent' to the initiator.
function testFuzz_handleCall_queuedAtClash_reverts(bytes memory outData) external {
// This will get us calldata with the same function selector as the queuedAt function, but
// with the incorrect input data length.
bytes memory inData = abi.encodePacked(keccak256("queuedAt(bytes32)"));
// Reset the delay to zero
vm.store(address(delayedVetoable), bytes32(uint256(0)), bytes32(uint256(0)));
vm.prank(initiator);
vm.expectRevert(outData);
(bool success,) = address(delayedVetoable).call(inData);
}
}
This diff is collapsed.
......@@ -2,4 +2,4 @@ packages:
- 'packages/*'
- 'endpoint-monitor'
- 'op-exporter'
- 'indexer/ts'
- 'indexer/api-ts'
......@@ -7,8 +7,8 @@ import (
"time"
"github.com/ethereum/go-ethereum/rpc"
"github.com/redis/go-redis/v9"
"github.com/go-redis/redis/v8"
"github.com/golang/snappy"
lru "github.com/hashicorp/golang-lru"
)
......@@ -78,7 +78,7 @@ func (c *redisCache) Get(ctx context.Context, key string) (string, error) {
func (c *redisCache) Put(ctx context.Context, key string, value string) error {
start := time.Now()
err := c.rdb.SetEX(ctx, c.namespaced(key), value, redisTTL).Err()
err := c.rdb.SetEx(ctx, c.namespaced(key), value, redisTTL).Err()
redisCacheDurationSumm.WithLabelValues("SETEX").Observe(float64(time.Since(start).Milliseconds()))
if err != nil {
......
......@@ -110,6 +110,10 @@ type BackendGroupConfig struct {
ConsensusMaxBlockLag uint64 `toml:"consensus_max_block_lag"`
ConsensusMaxBlockRange uint64 `toml:"consensus_max_block_range"`
ConsensusMinPeerCount int `toml:"consensus_min_peer_count"`
ConsensusHA bool `toml:"consensus_ha"`
ConsensusHAHeartbeatInterval TOMLDuration `toml:"consensus_ha_heartbeat_interval"`
ConsensusHALockPeriod TOMLDuration `toml:"consensus_ha_lock_period"`
}
type BackendGroupsConfig map[string]*BackendGroupConfig
......
......@@ -23,6 +23,7 @@ type OnConsensusBroken func()
// resolves the highest common block for multiple nodes, and reconciles the consensus
// in case of block hash divergence to minimize re-orgs
type ConsensusPoller struct {
ctx context.Context
cancelFunc context.CancelFunc
listeners []OnConsensusBroken
......@@ -220,6 +221,7 @@ func NewConsensusPoller(bg *BackendGroup, opts ...ConsensusOpt) *ConsensusPoller
state := make(map[*Backend]*backendState, len(bg.Backends))
cp := &ConsensusPoller{
ctx: ctx,
cancelFunc: cancelFunc,
backendGroup: bg,
backendState: state,
......
This diff is collapsed.
......@@ -6,7 +6,7 @@ import (
"sync"
"time"
"github.com/go-redis/redis/v8"
"github.com/redis/go-redis/v9"
)
type FrontendRateLimiter interface {
......
......@@ -7,7 +7,7 @@ import (
"time"
"github.com/alicebob/miniredis"
"github.com/go-redis/redis/v8"
"github.com/redis/go-redis/v9"
"github.com/stretchr/testify/require"
)
......
......@@ -7,7 +7,6 @@ require (
github.com/alicebob/miniredis v2.5.0+incompatible
github.com/emirpasic/gods v1.18.1
github.com/ethereum/go-ethereum v1.12.1
github.com/go-redis/redis/v8 v8.11.4
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.5.0
......@@ -44,11 +43,14 @@ require (
github.com/ethereum/c-kzg-4844 v0.3.0 // indirect
github.com/getsentry/sentry-go v0.18.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-redsync/redsync/v4 v4.9.4 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/gomodule/redigo v1.8.8 // indirect
github.com/gomodule/redigo v1.8.9 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/holiman/uint256 v1.2.3 // indirect
github.com/klauspost/compress v1.15.15 // indirect
......@@ -62,6 +64,7 @@ require (
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.39.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/redis/go-redis/v9 v9.1.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
......
This diff is collapsed.
......@@ -262,6 +262,33 @@ var (
"backend_group_name",
})
consensusHALatestBlock = promauto.NewGaugeVec(prometheus.GaugeOpts{
Namespace: MetricsNamespace,
Name: "group_consensus_ha_latest_block",
Help: "Consensus HA latest block",
}, []string{
"backend_group_name",
"leader",
})
consensusHASafeBlock = promauto.NewGaugeVec(prometheus.GaugeOpts{
Namespace: MetricsNamespace,
Name: "group_consensus_ha_safe_block",
Help: "Consensus HA safe block",
}, []string{
"backend_group_name",
"leader",
})
consensusHAFinalizedBlock = promauto.NewGaugeVec(prometheus.GaugeOpts{
Namespace: MetricsNamespace,
Name: "group_consensus_ha_finalized_block",
Help: "Consensus HA finalized block",
}, []string{
"backend_group_name",
"leader",
})
backendLatestBlockBackend = promauto.NewGaugeVec(prometheus.GaugeOpts{
Namespace: MetricsNamespace,
Name: "backend_latest_block",
......@@ -438,6 +465,18 @@ func RecordBatchSize(size int) {
batchSizeHistogram.Observe(float64(size))
}
func RecordGroupConsensusHALatestBlock(group *BackendGroup, leader string, blockNumber hexutil.Uint64) {
consensusHALatestBlock.WithLabelValues(group.Name, leader).Set(float64(blockNumber))
}
func RecordGroupConsensusHASafeBlock(group *BackendGroup, leader string, blockNumber hexutil.Uint64) {
consensusHASafeBlock.WithLabelValues(group.Name, leader).Set(float64(blockNumber))
}
func RecordGroupConsensusHAFinalizedBlock(group *BackendGroup, leader string, blockNumber hexutil.Uint64) {
consensusHAFinalizedBlock.WithLabelValues(group.Name, leader).Set(float64(blockNumber))
}
func RecordGroupConsensusLatestBlock(group *BackendGroup, blockNumber hexutil.Uint64) {
consensusLatestBlock.WithLabelValues(group.Name).Set(float64(blockNumber))
}
......
package proxyd
import (
"context"
"crypto/tls"
"errors"
"fmt"
......@@ -10,8 +11,8 @@ import (
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/log"
"github.com/go-redis/redis/v8"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/redis/go-redis/v9"
"golang.org/x/sync/semaphore"
)
......@@ -313,8 +314,28 @@ func Start(config *Config) (*Server, func(), error) {
copts = append(copts, WithMaxBlockRange(bgcfg.ConsensusMaxBlockRange))
}
var tracker ConsensusTracker
if bgcfg.ConsensusHA {
if redisClient == nil {
log.Crit("cant start - consensus high availability requires redis")
}
topts := make([]RedisConsensusTrackerOpt, 0)
if bgcfg.ConsensusHALockPeriod > 0 {
topts = append(topts, WithLockPeriod(time.Duration(bgcfg.ConsensusHALockPeriod)))
}
if bgcfg.ConsensusHAHeartbeatInterval > 0 {
topts = append(topts, WithLockPeriod(time.Duration(bgcfg.ConsensusHAHeartbeatInterval)))
}
tracker = NewRedisConsensusTracker(context.Background(), redisClient, bg, bg.Name, topts...)
copts = append(copts, WithTracker(tracker))
}
cp := NewConsensusPoller(bg, copts...)
bg.Consensus = cp
if bgcfg.ConsensusHA {
tracker.(*RedisConsensusTracker).Init()
}
}
}
......
......@@ -4,7 +4,7 @@ import (
"context"
"time"
"github.com/go-redis/redis/v8"
"github.com/redis/go-redis/v9"
)
func NewRedisClient(url string) (*redis.Client, error) {
......
......@@ -22,10 +22,10 @@ import (
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/go-redis/redis/v8"
"github.com/gorilla/mux"
"github.com/gorilla/websocket"
"github.com/prometheus/client_golang/prometheus"
"github.com/redis/go-redis/v9"
"github.com/rs/cors"
"github.com/syndtr/goleveldb/leveldb/opt"
)
......
......@@ -366,7 +366,7 @@ When decompressing a channel, we limit the amount of decompressed data to `MAX_R
10,000,000 bytes), in order to avoid "zip-bomb" types of attack (where a small compressed input decompresses to a
humongous amount of data). If the decompressed data exceeds the limit, things proceeds as though the channel contained
only the first `MAX_RLP_BYTES_PER_CHANNEL` decompressed bytes. The limit is set on RLP decoding, so all batches that
can be decoded in `MAX_RLP_BYTES_PER_CHANNEL` will be accepted ven if the size of the channel is greater than
can be decoded in `MAX_RLP_BYTES_PER_CHANNEL` will be accepted even if the size of the channel is greater than
`MAX_RLP_BYTES_PER_CHANNEL`. The exact requirement is that `length(input) <= MAX_RLP_BYTES_PER_CHANNEL`.
While the above pseudocode implies that all batches are known in advance, it is possible to perform streaming
......
......@@ -645,7 +645,7 @@ blocks older than two L1 epochs (64 L1 [time slots][time-slot]).
[address-aliasing]: glossary.md#address-aliasing
When a contract submits a [deposit][deposits] from L1 to L2, it's address (as returned by `ORIGIN` and `CALLER`) will be
When a contract submits a [deposit][deposits] from L1 to L2, its address (as returned by `ORIGIN` and `CALLER`) will be
aliased with a modified representation of the address of a contract.
- cf. [Deposit Specification](deposits.md#address-aliasing)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment