Commit 9eb5f880 authored by Michael de Hoog's avatar Michael de Hoog Committed by GitHub

Fjord: Add FastLZ compression into L1CostFunc (#9618)

* Add FastLZ for better L1Cost estimation
Co-authored-by: default avatarMichael de Hoog <michael.dehoog@coinbase.com>
Co-authored-by: default avatarDanyal Prout <danyal.prout@coinbase.com>
Co-authored-by: default avatarYukai Tu <yukai.tu@coinbase.com>
Co-authored-by: default avatarangel-ding-cb <angel.ding@coinbase.com>

* fix all the tests

* fix: upate GPO network transactions to match spec

* Update GPO contracts

* update to 1d model / add tests

* update allocs and test framework to support new fjord contracts

* add fuzz testing

* increase minimum estimation to 100 / update circleci for e2e fuzz tests

* use linear regression for l1 gas used

* Add differential fastlz fuzzing between solady/cgo fastlz/geth fastlz

* Review feedback

* Bump geth

* fix: ensure we don't gc the data during fastlz compression

* Replace common.Hex2Bytes with common.FromHex

---------
Co-authored-by: default avatarDanyal Prout <danyal.prout@coinbase.com>
Co-authored-by: default avatarYukai Tu <yukai.tu@coinbase.com>
Co-authored-by: default avatarangel-ding-cb <angel.ding@coinbase.com>
Co-authored-by: default avatarDanyal Prout <me@dany.al>
parent ae86d575
...@@ -1758,6 +1758,12 @@ workflows: ...@@ -1758,6 +1758,12 @@ workflows:
on_changes: cannon,packages/contracts-bedrock/src/cannon on_changes: cannon,packages/contracts-bedrock/src/cannon
uses_artifacts: true uses_artifacts: true
requires: ["go-mod-download", "pnpm-monorepo"] requires: ["go-mod-download", "pnpm-monorepo"]
- fuzz-golang:
name: op-e2e-fuzz
package_name: op-e2e
on_changes: op-e2e,packages/contracts-bedrock/src
uses_artifacts: true
requires: ["go-mod-download", "pnpm-monorepo"]
- go-test: - go-test:
name: op-heartbeat-tests name: op-heartbeat-tests
module: op-heartbeat module: op-heartbeat
......
...@@ -227,7 +227,7 @@ require ( ...@@ -227,7 +227,7 @@ require (
rsc.io/tmplfunc v0.0.3 // indirect rsc.io/tmplfunc v0.0.3 // indirect
) )
replace github.com/ethereum/go-ethereum => github.com/ethereum-optimism/op-geth v1.101315.1-rc.2 replace github.com/ethereum/go-ethereum => github.com/ethereum-optimism/op-geth v1.101315.1-rc.3
//replace github.com/ethereum/go-ethereum v1.13.9 => ../op-geth //replace github.com/ethereum/go-ethereum v1.13.9 => ../op-geth
......
...@@ -175,8 +175,8 @@ github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/ ...@@ -175,8 +175,8 @@ github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/
github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z8veEq5ZO3DfIhZ7xgRP9WTc= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z8veEq5ZO3DfIhZ7xgRP9WTc=
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs= github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs=
github.com/ethereum-optimism/op-geth v1.101315.1-rc.2 h1:uUrcs8fGrdDnVELB66GcMZRvwIeJow64DOtF+VFdAzY= github.com/ethereum-optimism/op-geth v1.101315.1-rc.3 h1:BvmzUehVSo7uuqtApy/h/A5uRDAuU2tJQLgHCWTxAUQ=
github.com/ethereum-optimism/op-geth v1.101315.1-rc.2/go.mod h1:VXVFzx1mr/JyJac5M4k5W/+0cqHZMkqKsIVDsOyj2rs= github.com/ethereum-optimism/op-geth v1.101315.1-rc.3/go.mod h1:VXVFzx1mr/JyJac5M4k5W/+0cqHZMkqKsIVDsOyj2rs=
github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240510200259-4be7024d2ba7 h1:e7oXWZwODAMM2TLo9beGDXaX2cCw7uM7qAqamYBHV40= github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240510200259-4be7024d2ba7 h1:e7oXWZwODAMM2TLo9beGDXaX2cCw7uM7qAqamYBHV40=
github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240510200259-4be7024d2ba7/go.mod h1:7xh2awFQqsiZxFrHKTgEd+InVfDRrkKVUIuK8SAFHp0= github.com/ethereum-optimism/superchain-registry/superchain v0.0.0-20240510200259-4be7024d2ba7/go.mod h1:7xh2awFQqsiZxFrHKTgEd+InVfDRrkKVUIuK8SAFHp0=
github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY=
......
...@@ -30,8 +30,8 @@ var ( ...@@ -30,8 +30,8 @@ var (
// GasPriceOracleMetaData contains all meta data concerning the GasPriceOracle contract. // GasPriceOracleMetaData contains all meta data concerning the GasPriceOracle contract.
var GasPriceOracleMetaData = &bind.MetaData{ var GasPriceOracleMetaData = &bind.MetaData{
ABI: "[{\"type\":\"function\",\"name\":\"DECIMALS\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"baseFee\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"baseFeeScalar\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"blobBaseFee\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"blobBaseFeeScalar\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"gasPrice\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getL1Fee\",\"inputs\":[{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getL1GasUsed\",\"inputs\":[{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isEcotone\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"l1BaseFee\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"overhead\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"scalar\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setEcotone\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"}]", ABI: "[{\"type\":\"function\",\"name\":\"DECIMALS\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"baseFee\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"baseFeeScalar\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"blobBaseFee\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"blobBaseFeeScalar\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"decimals\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"gasPrice\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getL1Fee\",\"inputs\":[{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getL1FeeUpperBound\",\"inputs\":[{\"name\":\"_unsignedTxSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getL1GasUsed\",\"inputs\":[{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isEcotone\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isFjord\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"l1BaseFee\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"overhead\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"scalar\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setEcotone\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setFjord\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"version\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"}]",
Bin: "0x608060405234801561001057600080fd5b50610fb5806100206000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c806354fd4d5011610097578063de26c4a111610066578063de26c4a1146101da578063f45e65d8146101ed578063f8206140146101f5578063fe173b97146101cc57600080fd5b806354fd4d501461016657806368d5dca6146101af5780636ef25c3a146101cc578063c5985918146101d257600080fd5b8063313ce567116100d3578063313ce5671461012757806349948e0e1461012e5780634ef6e22414610141578063519b4bd31461015e57600080fd5b80630c18c162146100fa57806322b90ab3146101155780632e0f26251461011f575b600080fd5b6101026101fd565b6040519081526020015b60405180910390f35b61011d61031e565b005b610102600681565b6006610102565b61010261013c366004610b73565b610541565b60005461014e9060ff1681565b604051901515815260200161010c565b610102610565565b6101a26040518060400160405280600581526020017f312e322e3000000000000000000000000000000000000000000000000000000081525081565b60405161010c9190610c42565b6101b76105c6565b60405163ffffffff909116815260200161010c565b48610102565b6101b761064b565b6101026101e8366004610b73565b6106ac565b610102610760565b610102610853565b6000805460ff1615610296576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f47617350726963654f7261636c653a206f76657268656164282920697320646560448201527f707265636174656400000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103199190610cb5565b905090565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663e591b2826040518163ffffffff1660e01b8152600401602060405180830381865afa15801561037d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a19190610cce565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610481576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f47617350726963654f7261636c653a206f6e6c7920746865206465706f73697460448201527f6f72206163636f756e742063616e2073657420697345636f746f6e6520666c6160648201527f6700000000000000000000000000000000000000000000000000000000000000608482015260a40161028d565b60005460ff1615610514576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f47617350726963654f7261636c653a2045636f746f6e6520616c72656164792060448201527f6163746976650000000000000000000000000000000000000000000000000000606482015260840161028d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000805460ff161561055c57610556826108b4565b92915050565b61055682610958565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16635cf249696040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f5573d6000803e3d6000fd5b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff166368d5dca66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610627573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103199190610d04565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663c59859186040518163ffffffff1660e01b8152600401602060405180830381865afa158015610627573d6000803e3d6000fd5b6000806106b883610ab4565b60005490915060ff16156106cc5792915050565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa15801561072b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074f9190610cb5565b6107599082610d59565b9392505050565b6000805460ff16156107f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f47617350726963654f7261636c653a207363616c61722829206973206465707260448201527f6563617465640000000000000000000000000000000000000000000000000000606482015260840161028d565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16639e8c49666040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f5573d6000803e3d6000fd5b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663f82061406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f5573d6000803e3d6000fd5b6000806108c083610ab4565b905060006108cc610565565b6108d461064b565b6108df906010610d71565b63ffffffff166108ef9190610d9d565b905060006108fb610853565b6109036105c6565b63ffffffff166109139190610d9d565b905060006109218284610d59565b61092b9085610d9d565b90506109396006600a610efa565b610944906010610d9d565b61094e9082610f06565b9695505050505050565b60008061096483610ab4565b9050600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16639e8c49666040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109eb9190610cb5565b6109f3610565565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a769190610cb5565b610a809085610d59565b610a8a9190610d9d565b610a949190610d9d565b9050610aa26006600a610efa565b610aac9082610f06565b949350505050565b80516000908190815b81811015610b3757848181518110610ad757610ad7610f41565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016600003610b1757610b10600484610d59565b9250610b25565b610b22601084610d59565b92505b80610b2f81610f70565b915050610abd565b50610aac82610440610d59565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208284031215610b8557600080fd5b813567ffffffffffffffff80821115610b9d57600080fd5b818401915084601f830112610bb157600080fd5b813581811115610bc357610bc3610b44565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610c0957610c09610b44565b81604052828152876020848701011115610c2257600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208083528351808285015260005b81811015610c6f57858101830151858201604001528201610c53565b81811115610c81576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b600060208284031215610cc757600080fd5b5051919050565b600060208284031215610ce057600080fd5b815173ffffffffffffffffffffffffffffffffffffffff8116811461075957600080fd5b600060208284031215610d1657600080fd5b815163ffffffff8116811461075957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115610d6c57610d6c610d2a565b500190565b600063ffffffff80831681851681830481118215151615610d9457610d94610d2a565b02949350505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610dd557610dd5610d2a565b500290565b600181815b80851115610e3357817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610e1957610e19610d2a565b80851615610e2657918102915b93841c9390800290610ddf565b509250929050565b600082610e4a57506001610556565b81610e5757506000610556565b8160018114610e6d5760028114610e7757610e93565b6001915050610556565b60ff841115610e8857610e88610d2a565b50506001821b610556565b5060208310610133831016604e8410600b8410161715610eb6575081810a610556565b610ec08383610dda565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610ef257610ef2610d2a565b029392505050565b60006107598383610e3b565b600082610f3c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610fa157610fa1610d2a565b506001019056fea164736f6c634300080f000a", Bin: "0x608060405234801561001057600080fd5b506117f6806100206000396000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c80636ef25c3a116100b2578063de26c4a111610081578063f45e65d811610066578063f45e65d81461025b578063f820614014610263578063fe173b971461020d57600080fd5b8063de26c4a114610235578063f1c7a58b1461024857600080fd5b80636ef25c3a1461020d5780638e98b10614610213578063960e3a231461021b578063c59859181461022d57600080fd5b806349948e0e11610109578063519b4bd3116100ee578063519b4bd31461019f57806354fd4d50146101a757806368d5dca6146101f057600080fd5b806349948e0e1461016f5780634ef6e2241461018257600080fd5b80630c18c1621461013b57806322b90ab3146101565780632e0f262514610160578063313ce56714610168575b600080fd5b61014361026b565b6040519081526020015b60405180910390f35b61015e61038c565b005b610143600681565b6006610143565b61014361017d3660046112a1565b610515565b60005461018f9060ff1681565b604051901515815260200161014d565b610143610552565b6101e36040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b60405161014d9190611370565b6101f86105b3565b60405163ffffffff909116815260200161014d565b48610143565b61015e610638565b60005461018f90610100900460ff1681565b6101f8610832565b6101436102433660046112a1565b610893565b6101436102563660046113e3565b61098d565b610143610a69565b610143610b5c565b6000805460ff1615610304576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f47617350726963654f7261636c653a206f76657268656164282920697320646560448201527f707265636174656400000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610363573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061038791906113fc565b905090565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610455576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f47617350726963654f7261636c653a206f6e6c7920746865206465706f73697460448201527f6f72206163636f756e742063616e2073657420697345636f746f6e6520666c6160648201527f6700000000000000000000000000000000000000000000000000000000000000608482015260a4016102fb565b60005460ff16156104e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f47617350726963654f7261636c653a2045636f746f6e6520616c72656164792060448201527f616374697665000000000000000000000000000000000000000000000000000060648201526084016102fb565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b60008054610100900460ff16156105355761052f82610bbd565b92915050565b60005460ff16156105495761052f82610bdc565b61052f82610c80565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16635cf249696040518163ffffffff1660e01b8152600401602060405180830381865afa158015610363573d6000803e3d6000fd5b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff166368d5dca66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610614573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103879190611415565b3373deaddeaddeaddeaddeaddeaddeaddeaddead0001146106db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f47617350726963654f7261636c653a206f6e6c7920746865206465706f73697460448201527f6f72206163636f756e742063616e20736574206973466a6f726420666c61670060648201526084016102fb565b60005460ff1661076d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f47617350726963654f7261636c653a20466a6f72642063616e206f6e6c79206260448201527f65206163746976617465642061667465722045636f746f6e650000000000000060648201526084016102fb565b600054610100900460ff1615610804576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f47617350726963654f7261636c653a20466a6f726420616c726561647920616360448201527f746976650000000000000000000000000000000000000000000000000000000060648201526084016102fb565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663c59859186040518163ffffffff1660e01b8152600401602060405180830381865afa158015610614573d6000803e3d6000fd5b60008054610100900460ff16156108da57620f42406108c56108b484610dd4565b516108c090604461146a565b6110f1565b6108d0906010611482565b61052f91906114bf565b60006108e583611150565b60005490915060ff16156108f95792915050565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610958573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097c91906113fc565b610986908261146a565b9392505050565b60008054610100900460ff16610a25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f47617350726963654f7261636c653a206765744c314665655570706572426f7560448201527f6e64206f6e6c7920737570706f72747320466a6f72640000000000000000000060648201526084016102fb565b6000610a3283604461146a565b90506000610a4160ff836114bf565b610a4b908361146a565b610a5690601061146a565b9050610a61816111e0565b949350505050565b6000805460ff1615610afd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f47617350726963654f7261636c653a207363616c61722829206973206465707260448201527f656361746564000000000000000000000000000000000000000000000000000060648201526084016102fb565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16639e8c49666040518163ffffffff1660e01b8152600401602060405180830381865afa158015610363573d6000803e3d6000fd5b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663f82061406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610363573d6000803e3d6000fd5b600061052f610bcb83610dd4565b51610bd790604461146a565b6111e0565b600080610be883611150565b90506000610bf4610552565b610bfc610832565b610c079060106114fa565b63ffffffff16610c179190611482565b90506000610c23610b5c565b610c2b6105b3565b63ffffffff16610c3b9190611482565b90506000610c49828461146a565b610c539085611482565b9050610c616006600a611646565b610c6c906010611482565b610c7690826114bf565b9695505050505050565b600080610c8c83611150565b9050600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16639e8c49666040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1391906113fc565b610d1b610552565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9e91906113fc565b610da8908561146a565b610db29190611482565b610dbc9190611482565b9050610dca6006600a611646565b610a6190826114bf565b6060610f63565b818153600101919050565b600082840393505b838110156109865782810151828201511860001a1590930292600101610dee565b825b60208210610e5b578251610e26601f83610ddb565b52602092909201917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090910190602101610e11565b8115610986578251610e706001840383610ddb565b520160010192915050565b60006001830392505b6101078210610ebc57610eae8360ff16610ea960fd610ea98760081c60e00189610ddb565b610ddb565b935061010682039150610e84565b60078210610ee957610ee28360ff16610ea960078503610ea98760081c60e00189610ddb565b9050610986565b610a618360ff16610ea98560081c8560051b0187610ddb565b610f5b828203610f3f610f2f84600081518060001a8160011a60081b178160021a60101b17915050919050565b639e3779b90260131c611fff1690565b8060021b6040510182815160e01c1860e01b8151188152505050565b600101919050565b6180003860405139618000604051016020830180600d8551820103826002015b81811015611096576000805b50508051604051600082901a600183901a60081b1760029290921a60101b91909117639e3779b9810260111c617ffc16909101805160e081811c878603811890911b90911890915284019081830390848410610feb5750611026565b600184019350611fff8211611020578251600081901a600182901a60081b1760029190911a60101b1781036110205750611026565b50610f8f565b838310611034575050611096565b600183039250858311156110525761104f8787888603610e0f565b96505b611066600985016003850160038501610de6565b9150611073878284610e7b565b96505061108b8461108686848601610f02565b610f02565b915050809350610f83565b50506110a88383848851850103610e0f565b925050506040519150618000820180820391508183526020830160005b838110156110dd5782810151828201526020016110c5565b506000920191825250602001604052919050565b60008061110183620cc394611482565b61112b907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd763200611652565b905061113b6064620f42406116c6565b81121561052f576109866064620f42406116c6565b80516000908190815b818110156111d35784818151811061117357611173611782565b01602001517fff00000000000000000000000000000000000000000000000000000000000000166000036111b3576111ac60048461146a565b92506111c1565b6111be60108461146a565b92505b806111cb816117b1565b915050611159565b50610a618261044061146a565b6000806111ec836110f1565b905060006111f8610b5c565b6112006105b3565b63ffffffff166112109190611482565b611218610552565b611220610832565b61122b9060106114fa565b63ffffffff1661123b9190611482565b611245919061146a565b905061125360066002611482565b61125e90600a611646565b6112688284611482565b610a6191906114bf565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156112b357600080fd5b813567ffffffffffffffff808211156112cb57600080fd5b818401915084601f8301126112df57600080fd5b8135818111156112f1576112f1611272565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561133757611337611272565b8160405282815287602084870101111561135057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208083528351808285015260005b8181101561139d57858101830151858201604001528201611381565b818111156113af576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b6000602082840312156113f557600080fd5b5035919050565b60006020828403121561140e57600080fd5b5051919050565b60006020828403121561142757600080fd5b815163ffffffff8116811461098657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561147d5761147d61143b565b500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156114ba576114ba61143b565b500290565b6000826114f5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600063ffffffff8083168185168183048111821515161561151d5761151d61143b565b02949350505050565b600181815b8085111561157f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156115655761156561143b565b8085161561157257918102915b93841c939080029061152b565b509250929050565b6000826115965750600161052f565b816115a35750600061052f565b81600181146115b957600281146115c3576115df565b600191505061052f565b60ff8411156115d4576115d461143b565b50506001821b61052f565b5060208310610133831016604e8410600b8410161715611602575081810a61052f565b61160c8383611526565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561163e5761163e61143b565b029392505050565b60006109868383611587565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561168c5761168c61143b565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156116c0576116c061143b565b50500190565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156117075761170761143b565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156117425761174261143b565b6000871292508782058712848416161561175e5761175e61143b565b878505871281841616156117745761177461143b565b505050929093029392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036117e2576117e261143b565b506001019056fea164736f6c634300080f000a",
} }
// GasPriceOracleABI is the input ABI used to generate the binding from. // GasPriceOracleABI is the input ABI used to generate the binding from.
...@@ -449,6 +449,37 @@ func (_GasPriceOracle *GasPriceOracleCallerSession) GetL1Fee(_data []byte) (*big ...@@ -449,6 +449,37 @@ func (_GasPriceOracle *GasPriceOracleCallerSession) GetL1Fee(_data []byte) (*big
return _GasPriceOracle.Contract.GetL1Fee(&_GasPriceOracle.CallOpts, _data) return _GasPriceOracle.Contract.GetL1Fee(&_GasPriceOracle.CallOpts, _data)
} }
// GetL1FeeUpperBound is a free data retrieval call binding the contract method 0xf1c7a58b.
//
// Solidity: function getL1FeeUpperBound(uint256 _unsignedTxSize) view returns(uint256)
func (_GasPriceOracle *GasPriceOracleCaller) GetL1FeeUpperBound(opts *bind.CallOpts, _unsignedTxSize *big.Int) (*big.Int, error) {
var out []interface{}
err := _GasPriceOracle.contract.Call(opts, &out, "getL1FeeUpperBound", _unsignedTxSize)
if err != nil {
return *new(*big.Int), err
}
out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
return out0, err
}
// GetL1FeeUpperBound is a free data retrieval call binding the contract method 0xf1c7a58b.
//
// Solidity: function getL1FeeUpperBound(uint256 _unsignedTxSize) view returns(uint256)
func (_GasPriceOracle *GasPriceOracleSession) GetL1FeeUpperBound(_unsignedTxSize *big.Int) (*big.Int, error) {
return _GasPriceOracle.Contract.GetL1FeeUpperBound(&_GasPriceOracle.CallOpts, _unsignedTxSize)
}
// GetL1FeeUpperBound is a free data retrieval call binding the contract method 0xf1c7a58b.
//
// Solidity: function getL1FeeUpperBound(uint256 _unsignedTxSize) view returns(uint256)
func (_GasPriceOracle *GasPriceOracleCallerSession) GetL1FeeUpperBound(_unsignedTxSize *big.Int) (*big.Int, error) {
return _GasPriceOracle.Contract.GetL1FeeUpperBound(&_GasPriceOracle.CallOpts, _unsignedTxSize)
}
// GetL1GasUsed is a free data retrieval call binding the contract method 0xde26c4a1. // GetL1GasUsed is a free data retrieval call binding the contract method 0xde26c4a1.
// //
// Solidity: function getL1GasUsed(bytes _data) view returns(uint256) // Solidity: function getL1GasUsed(bytes _data) view returns(uint256)
...@@ -511,6 +542,37 @@ func (_GasPriceOracle *GasPriceOracleCallerSession) IsEcotone() (bool, error) { ...@@ -511,6 +542,37 @@ func (_GasPriceOracle *GasPriceOracleCallerSession) IsEcotone() (bool, error) {
return _GasPriceOracle.Contract.IsEcotone(&_GasPriceOracle.CallOpts) return _GasPriceOracle.Contract.IsEcotone(&_GasPriceOracle.CallOpts)
} }
// IsFjord is a free data retrieval call binding the contract method 0x960e3a23.
//
// Solidity: function isFjord() view returns(bool)
func (_GasPriceOracle *GasPriceOracleCaller) IsFjord(opts *bind.CallOpts) (bool, error) {
var out []interface{}
err := _GasPriceOracle.contract.Call(opts, &out, "isFjord")
if err != nil {
return *new(bool), err
}
out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
return out0, err
}
// IsFjord is a free data retrieval call binding the contract method 0x960e3a23.
//
// Solidity: function isFjord() view returns(bool)
func (_GasPriceOracle *GasPriceOracleSession) IsFjord() (bool, error) {
return _GasPriceOracle.Contract.IsFjord(&_GasPriceOracle.CallOpts)
}
// IsFjord is a free data retrieval call binding the contract method 0x960e3a23.
//
// Solidity: function isFjord() view returns(bool)
func (_GasPriceOracle *GasPriceOracleCallerSession) IsFjord() (bool, error) {
return _GasPriceOracle.Contract.IsFjord(&_GasPriceOracle.CallOpts)
}
// L1BaseFee is a free data retrieval call binding the contract method 0x519b4bd3. // L1BaseFee is a free data retrieval call binding the contract method 0x519b4bd3.
// //
// Solidity: function l1BaseFee() view returns(uint256) // Solidity: function l1BaseFee() view returns(uint256)
...@@ -655,3 +717,24 @@ func (_GasPriceOracle *GasPriceOracleSession) SetEcotone() (*types.Transaction, ...@@ -655,3 +717,24 @@ func (_GasPriceOracle *GasPriceOracleSession) SetEcotone() (*types.Transaction,
func (_GasPriceOracle *GasPriceOracleTransactorSession) SetEcotone() (*types.Transaction, error) { func (_GasPriceOracle *GasPriceOracleTransactorSession) SetEcotone() (*types.Transaction, error) {
return _GasPriceOracle.Contract.SetEcotone(&_GasPriceOracle.TransactOpts) return _GasPriceOracle.Contract.SetEcotone(&_GasPriceOracle.TransactOpts)
} }
// SetFjord is a paid mutator transaction binding the contract method 0x8e98b106.
//
// Solidity: function setFjord() returns()
func (_GasPriceOracle *GasPriceOracleTransactor) SetFjord(opts *bind.TransactOpts) (*types.Transaction, error) {
return _GasPriceOracle.contract.Transact(opts, "setFjord")
}
// SetFjord is a paid mutator transaction binding the contract method 0x8e98b106.
//
// Solidity: function setFjord() returns()
func (_GasPriceOracle *GasPriceOracleSession) SetFjord() (*types.Transaction, error) {
return _GasPriceOracle.Contract.SetFjord(&_GasPriceOracle.TransactOpts)
}
// SetFjord is a paid mutator transaction binding the contract method 0x8e98b106.
//
// Solidity: function setFjord() returns()
func (_GasPriceOracle *GasPriceOracleTransactorSession) SetFjord() (*types.Transaction, error) {
return _GasPriceOracle.Contract.SetFjord(&_GasPriceOracle.TransactOpts)
}
...@@ -59,7 +59,7 @@ func main() { ...@@ -59,7 +59,7 @@ func main() {
scalar = uint(decoded.BaseFeeScalar) scalar = uint(decoded.BaseFeeScalar)
blobScalar = uint(decoded.BlobBaseFeeScalar) blobScalar = uint(decoded.BlobBaseFeeScalar)
} else { } else {
encoded = eth.EncodeScalar(eth.EcostoneScalars{ encoded = eth.EncodeScalar(eth.EcotoneScalars{
BlobBaseFeeScalar: uint32(blobScalar), BlobBaseFeeScalar: uint32(blobScalar),
BaseFeeScalar: uint32(scalar), BaseFeeScalar: uint32(scalar),
}) })
......
...@@ -493,7 +493,7 @@ func (d *DeployConfig) FeeScalar() [32]byte { ...@@ -493,7 +493,7 @@ func (d *DeployConfig) FeeScalar() [32]byte {
if d.GasPriceOracleScalar != 0 { if d.GasPriceOracleScalar != 0 {
return common.BigToHash(big.NewInt(int64(d.GasPriceOracleScalar))) return common.BigToHash(big.NewInt(int64(d.GasPriceOracleScalar)))
} }
return eth.EncodeScalar(eth.EcostoneScalars{ return eth.EncodeScalar(eth.EcotoneScalars{
BlobBaseFeeScalar: d.GasPriceOracleBlobBaseFeeScalar, BlobBaseFeeScalar: d.GasPriceOracleBlobBaseFeeScalar,
BaseFeeScalar: d.GasPriceOracleBaseFeeScalar, BaseFeeScalar: d.GasPriceOracleBaseFeeScalar,
}) })
......
...@@ -64,3 +64,9 @@ clean: ...@@ -64,3 +64,9 @@ clean:
rm -r ../.devnet rm -r ../.devnet
rm -r ../op-program/bin rm -r ../op-program/bin
.PHONY: clean .PHONY: clean
fuzz:
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzFjordCostFunction ./
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzFastLzGethSolidity ./
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzFastLzCgo ./
package actions
import (
"context"
"encoding/hex"
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-service/predeploys"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-service/testlog"
)
var (
fjordGasPriceOracleCodeHash = common.HexToHash("0xa88fa50a2745b15e6794247614b5298483070661adacb8d32d716434ed24c6b2")
// https://basescan.org/tx/0x8debb2fe54200183fb8baa3c6dbd8e6ec2e4f7a4add87416cd60336b8326d16a
txHex = "02f875822105819b8405709fb884057d460082e97f94273ca93a52b817294830ed7572aa591ccfa647fd80881249c58b0021fb3fc080a05bb08ccfd68f83392e446dac64d88a2d28e7072c06502dfabc4a77e77b5c7913a05878d53dd4ebba4f6367e572d524dffcabeec3abb1d8725ee3ac5dc32e1852e3"
)
func TestFjordNetworkUpgradeTransactions(gt *testing.T) {
t := NewDefaultTesting(gt)
dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams)
genesisBlock := hexutil.Uint64(0)
fjordOffset := hexutil.Uint64(2)
dp.DeployConfig.L1CancunTimeOffset = &genesisBlock // can be removed once Cancun on L1 is the default
// Activate all forks at genesis, and schedule Fjord the block after
dp.DeployConfig.L2GenesisRegolithTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisCanyonTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisDeltaTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisFjordTimeOffset = &fjordOffset
require.NoError(t, dp.DeployConfig.Check(), "must have valid config")
sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LvlDebug)
_, _, _, sequencer, engine, verifier, _, _ := setupReorgTestActors(t, dp, sd, log)
ethCl := engine.EthClient()
// start op-nodes
sequencer.ActL2PipelineFull(t)
verifier.ActL2PipelineFull(t)
// Get gas price from oracle
gasPriceOracle, err := bindings.NewGasPriceOracleCaller(predeploys.GasPriceOracleAddr, ethCl)
require.NoError(t, err)
// Get current implementations addresses (by slot) for L1Block + GasPriceOracle
initialGasPriceOracleAddress, err := ethCl.StorageAt(context.Background(), predeploys.GasPriceOracleAddr, genesis.ImplementationSlot, nil)
require.NoError(t, err)
sequencer.ActBuildL2ToFjord(t)
// get latest block
latestBlock, err := ethCl.BlockByNumber(context.Background(), nil)
require.NoError(t, err)
require.Equal(t, sequencer.L2Unsafe().Number, latestBlock.Number().Uint64())
transactions := latestBlock.Transactions()
// L1Block: 1 set-L1-info + 1 deploys + 1 upgradeTo + 1 enable fjord on GPO
// See [derive.FjordNetworkUpgradeTransactions]
require.Equal(t, 4, len(transactions))
// All transactions are successful
for i := 1; i < 4; i++ {
txn := transactions[i]
receipt, err := ethCl.TransactionReceipt(context.Background(), txn.Hash())
require.NoError(t, err)
require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status)
require.NotEmpty(t, txn.Data(), "upgrade tx must provide input data")
}
expectedGasPriceOracleAddress := crypto.CreateAddress(derive.GasPriceOracleFjordDeployerAddress, 0)
// Gas Price Oracle Proxy is updated
updatedGasPriceOracleAddress, err := ethCl.StorageAt(context.Background(), predeploys.GasPriceOracleAddr, genesis.ImplementationSlot, latestBlock.Number())
require.NoError(t, err)
require.Equal(t, expectedGasPriceOracleAddress, common.BytesToAddress(updatedGasPriceOracleAddress))
require.NotEqualf(t, initialGasPriceOracleAddress, updatedGasPriceOracleAddress, "Gas Price Oracle Proxy address should have changed")
verifyCodeHashMatches(t, ethCl, expectedGasPriceOracleAddress, fjordGasPriceOracleCodeHash)
// Check that Fjord was activated
isFjord, err := gasPriceOracle.IsFjord(nil)
require.NoError(t, err)
require.True(t, isFjord)
// Check GetL1GasUsed is updated
txData, err := hex.DecodeString(txHex)
require.NoError(t, err)
gpoL1GasUsed, err := gasPriceOracle.GetL1GasUsed(&bind.CallOpts{}, txData)
require.NoError(t, err)
require.Equal(gt, uint64(1_888), gpoL1GasUsed.Uint64())
// Check that GetL1Fee takes into account fast LZ
gpoFee, err := gasPriceOracle.GetL1Fee(&bind.CallOpts{}, txData)
require.NoError(t, err)
gethFee := fjordL1Cost(t, gasPriceOracle, types.RollupCostData{
FastLzSize: uint64(types.FlzCompressLen(txData) + 68),
})
require.Equal(t, gethFee.Uint64(), gpoFee.Uint64())
// Check that L1FeeUpperBound works
upperBound, err := gasPriceOracle.GetL1FeeUpperBound(&bind.CallOpts{}, big.NewInt(int64(len(txData))))
require.NoError(t, err)
txLen := len(txData) + 68
flzUpperBound := uint64(txLen + txLen/255 + 16)
upperBoundCost := fjordL1Cost(t, gasPriceOracle, types.RollupCostData{FastLzSize: flzUpperBound})
require.Equal(t, upperBoundCost.Uint64(), upperBound.Uint64())
}
func fjordL1Cost(t require.TestingT, gasPriceOracle *bindings.GasPriceOracleCaller, rollupCostData types.RollupCostData) *big.Int {
baseFeeScalar, err := gasPriceOracle.BaseFeeScalar(nil)
require.NoError(t, err)
l1BaseFee, err := gasPriceOracle.L1BaseFee(nil)
require.NoError(t, err)
blobBaseFeeScalar, err := gasPriceOracle.BlobBaseFeeScalar(nil)
require.NoError(t, err)
blobBaseFee, err := gasPriceOracle.BlobBaseFee(nil)
require.NoError(t, err)
costFunc := types.NewL1CostFuncFjord(
l1BaseFee,
blobBaseFee,
new(big.Int).SetUint64(uint64(baseFeeScalar)),
new(big.Int).SetUint64(uint64(blobBaseFeeScalar)))
fee, _ := costFunc(rollupCostData)
return fee
}
...@@ -175,3 +175,10 @@ func (s *L2Sequencer) ActBuildL2ToEcotone(t Testing) { ...@@ -175,3 +175,10 @@ func (s *L2Sequencer) ActBuildL2ToEcotone(t Testing) {
s.ActL2EndBlock(t) s.ActL2EndBlock(t)
} }
} }
func (s *L2Sequencer) ActBuildL2ToFjord(t Testing) {
require.NotNil(t, s.rollupCfg.FjordTime, "cannot activate FjordTime when it is not scheduled")
for s.L2Unsafe().Time < *s.rollupCfg.FjordTime {
s.ActL2StartBlock(t)
s.ActL2EndBlock(t)
}
}
...@@ -65,7 +65,7 @@ func (eec *ExternalEthClient) Close() error { ...@@ -65,7 +65,7 @@ func (eec *ExternalEthClient) Close() error {
return nil return nil
} }
func (er *ExternalRunner) Run(t *testing.T) *ExternalEthClient { func (er *ExternalRunner) Run(t testing.TB) *ExternalEthClient {
if er.BinPath == "" { if er.BinPath == "" {
t.Error("no external bin path set") t.Error("no external bin path set")
} }
......
...@@ -54,7 +54,7 @@ type TestParms struct { ...@@ -54,7 +54,7 @@ type TestParms struct {
SkipTests map[string]string `json:"skip_tests"` SkipTests map[string]string `json:"skip_tests"`
} }
func (tp TestParms) SkipIfNecessary(t *testing.T) { func (tp TestParms) SkipIfNecessary(t testing.TB) {
if len(tp.SkipTests) == 0 { if len(tp.SkipTests) == 0 {
return return
} }
......
/*
FastLZ - Byte-aligned LZ77 compression library
Copyright (C) 2005-2020 Ariya Hidayat <ariya.hidayat@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
This implementation is taken from the following repository/commit:
https://github.com/ariya/FastLZ/tree/344eb4025f9ae866ebf7a2ec48850f7113a97a42
*/
#include "fastlz.h"
#include <stdint.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
/*
* Give hints to the compiler for branch prediction optimization.
*/
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 2))
#define FASTLZ_LIKELY(c) (__builtin_expect(!!(c), 1))
#define FASTLZ_UNLIKELY(c) (__builtin_expect(!!(c), 0))
#else
#define FASTLZ_LIKELY(c) (c)
#define FASTLZ_UNLIKELY(c) (c)
#endif
/*
* Specialize custom 64-bit implementation for speed improvements.
*/
#if defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__)
#define FLZ_ARCH64
#endif
/*
* Workaround for DJGPP to find uint8_t, uint16_t, etc.
*/
#if defined(__MSDOS__) && defined(__GNUC__)
#include <stdint-gcc.h>
#endif
#if defined(FASTLZ_USE_MEMMOVE) && (FASTLZ_USE_MEMMOVE == 0)
static void fastlz_memmove(uint8_t* dest, const uint8_t* src, uint32_t count) {
do {
*dest++ = *src++;
} while (--count);
}
static void fastlz_memcpy(uint8_t* dest, const uint8_t* src, uint32_t count) {
return fastlz_memmove(dest, src, count);
}
#else
#include <string.h>
static void fastlz_memmove(uint8_t* dest, const uint8_t* src, uint32_t count) {
if ((count > 4) && (dest >= src + count)) {
memmove(dest, src, count);
} else {
switch (count) {
default:
do {
*dest++ = *src++;
} while (--count);
break;
case 3:
*dest++ = *src++;
case 2:
*dest++ = *src++;
case 1:
*dest++ = *src++;
case 0:
break;
}
}
}
static void fastlz_memcpy(uint8_t* dest, const uint8_t* src, uint32_t count) { memcpy(dest, src, count); }
#endif
#if defined(FLZ_ARCH64)
static uint32_t flz_readu32(const void* ptr) { return *(const uint32_t*)ptr; }
static uint32_t flz_cmp(const uint8_t* p, const uint8_t* q, const uint8_t* r) {
const uint8_t* start = p;
if (flz_readu32(p) == flz_readu32(q)) {
p += 4;
q += 4;
}
while (q < r)
if (*p++ != *q++) break;
return p - start;
}
#endif /* FLZ_ARCH64 */
#if !defined(FLZ_ARCH64)
static uint32_t flz_readu32(const void* ptr) {
const uint8_t* p = (const uint8_t*)ptr;
return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
}
static uint32_t flz_cmp(const uint8_t* p, const uint8_t* q, const uint8_t* r) {
const uint8_t* start = p;
while (q < r)
if (*p++ != *q++) break;
return p - start;
}
#endif /* !FLZ_ARCH64 */
#define MAX_COPY 32
#define MAX_LEN 264 /* 256 + 8 */
#define MAX_L1_DISTANCE 8192
#define MAX_L2_DISTANCE 8191
#define MAX_FARDISTANCE (65535 + MAX_L2_DISTANCE - 1)
#define HASH_LOG 13
#define HASH_SIZE (1 << HASH_LOG)
#define HASH_MASK (HASH_SIZE - 1)
static uint16_t flz_hash(uint32_t v) {
uint32_t h = (v * 2654435769LL) >> (32 - HASH_LOG);
return h & HASH_MASK;
}
/* special case of memcpy: at most MAX_COPY bytes */
static void flz_smallcopy(uint8_t* dest, const uint8_t* src, uint32_t count) {
#if defined(FLZ_ARCH64)
if (count >= 4) {
const uint32_t* p = (const uint32_t*)src;
uint32_t* q = (uint32_t*)dest;
while (count > 4) {
*q++ = *p++;
count -= 4;
dest += 4;
src += 4;
}
}
#endif
fastlz_memcpy(dest, src, count);
}
/* special case of memcpy: exactly MAX_COPY bytes */
static void flz_maxcopy(void* dest, const void* src) {
#if defined(FLZ_ARCH64)
const uint32_t* p = (const uint32_t*)src;
uint32_t* q = (uint32_t*)dest;
*q++ = *p++;
*q++ = *p++;
*q++ = *p++;
*q++ = *p++;
*q++ = *p++;
*q++ = *p++;
*q++ = *p++;
*q++ = *p++;
#else
fastlz_memcpy(dest, src, MAX_COPY);
#endif
}
static uint8_t* flz_literals(uint32_t runs, const uint8_t* src, uint8_t* dest) {
while (runs >= MAX_COPY) {
*dest++ = MAX_COPY - 1;
flz_maxcopy(dest, src);
src += MAX_COPY;
dest += MAX_COPY;
runs -= MAX_COPY;
}
if (runs > 0) {
*dest++ = runs - 1;
flz_smallcopy(dest, src, runs);
dest += runs;
}
return dest;
}
static uint8_t* flz1_match(uint32_t len, uint32_t distance, uint8_t* op) {
--distance;
if (FASTLZ_UNLIKELY(len > MAX_LEN - 2))
while (len > MAX_LEN - 2) {
*op++ = (7 << 5) + (distance >> 8);
*op++ = MAX_LEN - 2 - 7 - 2;
*op++ = (distance & 255);
len -= MAX_LEN - 2;
}
if (len < 7) {
*op++ = (len << 5) + (distance >> 8);
*op++ = (distance & 255);
} else {
*op++ = (7 << 5) + (distance >> 8);
*op++ = len - 7;
*op++ = (distance & 255);
}
return op;
}
#define FASTLZ_BOUND_CHECK(cond) \
if (FASTLZ_UNLIKELY(!(cond))) return 0;
int fastlz1_compress(const void* input, int length, void* output) {
const uint8_t* ip = (const uint8_t*)input;
const uint8_t* ip_start = ip;
const uint8_t* ip_bound = ip + length - 4; /* because readU32 */
const uint8_t* ip_limit = ip + length - 12 - 1;
uint8_t* op = (uint8_t*)output;
uint32_t htab[HASH_SIZE];
uint32_t seq, hash;
/* initializes hash table */
for (hash = 0; hash < HASH_SIZE; ++hash) htab[hash] = 0;
/* we start with literal copy */
const uint8_t* anchor = ip;
ip += 2;
/* main loop */
while (FASTLZ_LIKELY(ip < ip_limit)) {
const uint8_t* ref;
uint32_t distance, cmp;
/* find potential match */
do {
seq = flz_readu32(ip) & 0xffffff;
hash = flz_hash(seq);
ref = ip_start + htab[hash];
htab[hash] = ip - ip_start;
distance = ip - ref;
cmp = FASTLZ_LIKELY(distance < MAX_L1_DISTANCE) ? flz_readu32(ref) & 0xffffff : 0x1000000;
if (FASTLZ_UNLIKELY(ip >= ip_limit)) break;
++ip;
} while (seq != cmp);
if (FASTLZ_UNLIKELY(ip >= ip_limit)) break;
--ip;
if (FASTLZ_LIKELY(ip > anchor)) {
op = flz_literals(ip - anchor, anchor, op);
}
uint32_t len = flz_cmp(ref + 3, ip + 3, ip_bound);
op = flz1_match(len, distance, op);
/* update the hash at match boundary */
ip += len;
seq = flz_readu32(ip);
hash = flz_hash(seq & 0xffffff);
htab[hash] = ip++ - ip_start;
seq >>= 8;
hash = flz_hash(seq);
htab[hash] = ip++ - ip_start;
anchor = ip;
}
uint32_t copy = (uint8_t*)input + length - anchor;
op = flz_literals(copy, anchor, op);
return op - (uint8_t*)output;
}
int fastlz1_decompress(const void* input, int length, void* output, int maxout) {
const uint8_t* ip = (const uint8_t*)input;
const uint8_t* ip_limit = ip + length;
const uint8_t* ip_bound = ip_limit - 2;
uint8_t* op = (uint8_t*)output;
uint8_t* op_limit = op + maxout;
uint32_t ctrl = (*ip++) & 31;
while (1) {
if (ctrl >= 32) {
uint32_t len = (ctrl >> 5) - 1;
uint32_t ofs = (ctrl & 31) << 8;
const uint8_t* ref = op - ofs - 1;
if (len == 7 - 1) {
FASTLZ_BOUND_CHECK(ip <= ip_bound);
len += *ip++;
}
ref -= *ip++;
len += 3;
FASTLZ_BOUND_CHECK(op + len <= op_limit);
FASTLZ_BOUND_CHECK(ref >= (uint8_t*)output);
fastlz_memmove(op, ref, len);
op += len;
} else {
ctrl++;
FASTLZ_BOUND_CHECK(op + ctrl <= op_limit);
FASTLZ_BOUND_CHECK(ip + ctrl <= ip_limit);
fastlz_memcpy(op, ip, ctrl);
ip += ctrl;
op += ctrl;
}
if (FASTLZ_UNLIKELY(ip > ip_bound)) break;
ctrl = *ip++;
}
return op - (uint8_t*)output;
}
static uint8_t* flz2_match(uint32_t len, uint32_t distance, uint8_t* op) {
--distance;
if (distance < MAX_L2_DISTANCE) {
if (len < 7) {
*op++ = (len << 5) + (distance >> 8);
*op++ = (distance & 255);
} else {
*op++ = (7 << 5) + (distance >> 8);
for (len -= 7; len >= 255; len -= 255) *op++ = 255;
*op++ = len;
*op++ = (distance & 255);
}
} else {
/* far away, but not yet in the another galaxy... */
if (len < 7) {
distance -= MAX_L2_DISTANCE;
*op++ = (len << 5) + 31;
*op++ = 255;
*op++ = distance >> 8;
*op++ = distance & 255;
} else {
distance -= MAX_L2_DISTANCE;
*op++ = (7 << 5) + 31;
for (len -= 7; len >= 255; len -= 255) *op++ = 255;
*op++ = len;
*op++ = 255;
*op++ = distance >> 8;
*op++ = distance & 255;
}
}
return op;
}
int fastlz2_compress(const void* input, int length, void* output) {
const uint8_t* ip = (const uint8_t*)input;
const uint8_t* ip_start = ip;
const uint8_t* ip_bound = ip + length - 4; /* because readU32 */
const uint8_t* ip_limit = ip + length - 12 - 1;
uint8_t* op = (uint8_t*)output;
uint32_t htab[HASH_SIZE];
uint32_t seq, hash;
/* initializes hash table */
for (hash = 0; hash < HASH_SIZE; ++hash) htab[hash] = 0;
/* we start with literal copy */
const uint8_t* anchor = ip;
ip += 2;
/* main loop */
while (FASTLZ_LIKELY(ip < ip_limit)) {
const uint8_t* ref;
uint32_t distance, cmp;
/* find potential match */
do {
seq = flz_readu32(ip) & 0xffffff;
hash = flz_hash(seq);
ref = ip_start + htab[hash];
htab[hash] = ip - ip_start;
distance = ip - ref;
cmp = FASTLZ_LIKELY(distance < MAX_FARDISTANCE) ? flz_readu32(ref) & 0xffffff : 0x1000000;
if (FASTLZ_UNLIKELY(ip >= ip_limit)) break;
++ip;
} while (seq != cmp);
if (FASTLZ_UNLIKELY(ip >= ip_limit)) break;
--ip;
/* far, needs at least 5-byte match */
if (distance >= MAX_L2_DISTANCE) {
if (ref[3] != ip[3] || ref[4] != ip[4]) {
++ip;
continue;
}
}
if (FASTLZ_LIKELY(ip > anchor)) {
op = flz_literals(ip - anchor, anchor, op);
}
uint32_t len = flz_cmp(ref + 3, ip + 3, ip_bound);
op = flz2_match(len, distance, op);
/* update the hash at match boundary */
ip += len;
seq = flz_readu32(ip);
hash = flz_hash(seq & 0xffffff);
htab[hash] = ip++ - ip_start;
seq >>= 8;
hash = flz_hash(seq);
htab[hash] = ip++ - ip_start;
anchor = ip;
}
uint32_t copy = (uint8_t*)input + length - anchor;
op = flz_literals(copy, anchor, op);
/* marker for fastlz2 */
*(uint8_t*)output |= (1 << 5);
return op - (uint8_t*)output;
}
int fastlz2_decompress(const void* input, int length, void* output, int maxout) {
const uint8_t* ip = (const uint8_t*)input;
const uint8_t* ip_limit = ip + length;
const uint8_t* ip_bound = ip_limit - 2;
uint8_t* op = (uint8_t*)output;
uint8_t* op_limit = op + maxout;
uint32_t ctrl = (*ip++) & 31;
while (1) {
if (ctrl >= 32) {
uint32_t len = (ctrl >> 5) - 1;
uint32_t ofs = (ctrl & 31) << 8;
const uint8_t* ref = op - ofs - 1;
uint8_t code;
if (len == 7 - 1) do {
FASTLZ_BOUND_CHECK(ip <= ip_bound);
code = *ip++;
len += code;
} while (code == 255);
code = *ip++;
ref -= code;
len += 3;
/* match from 16-bit distance */
if (FASTLZ_UNLIKELY(code == 255))
if (FASTLZ_LIKELY(ofs == (31 << 8))) {
FASTLZ_BOUND_CHECK(ip < ip_bound);
ofs = (*ip++) << 8;
ofs += *ip++;
ref = op - ofs - MAX_L2_DISTANCE - 1;
}
FASTLZ_BOUND_CHECK(op + len <= op_limit);
FASTLZ_BOUND_CHECK(ref >= (uint8_t*)output);
fastlz_memmove(op, ref, len);
op += len;
} else {
ctrl++;
FASTLZ_BOUND_CHECK(op + ctrl <= op_limit);
FASTLZ_BOUND_CHECK(ip + ctrl <= ip_limit);
fastlz_memcpy(op, ip, ctrl);
ip += ctrl;
op += ctrl;
}
if (FASTLZ_UNLIKELY(ip >= ip_limit)) break;
ctrl = *ip++;
}
return op - (uint8_t*)output;
}
int fastlz_compress(const void* input, int length, void* output) {
/* for short block, choose fastlz1 */
if (length < 65536) return fastlz1_compress(input, length, output);
/* else... */
return fastlz2_compress(input, length, output);
}
int fastlz_decompress(const void* input, int length, void* output, int maxout) {
/* magic identifier for compression level */
int level = ((*(const uint8_t*)input) >> 5) + 1;
if (level == 1) return fastlz1_decompress(input, length, output, maxout);
if (level == 2) return fastlz2_decompress(input, length, output, maxout);
/* unknown level, trigger error */
return 0;
}
int fastlz_compress_level(int level, const void* input, int length, void* output) {
if (level == 1) return fastlz1_compress(input, length, output);
if (level == 2) return fastlz2_compress(input, length, output);
return 0;
}
#pragma GCC diagnostic pop
package fastlz
// #include <stdlib.h>
// #include "fastlz.h"
import "C"
import (
"errors"
"runtime"
"unsafe"
)
// Compress compresses the input data using the FastLZ algorithm.
// The version of FastLZ used is FastLZ level 1 with the implementation from
// this commit: https://github.com/ariya/FastLZ/commit/344eb4025f9ae866ebf7a2ec48850f7113a97a42
// Which is the same commit that Solady uses: https://github.com/Vectorized/solady/blob/main/src/utils/LibZip.sol#L19
// Note the FastLZ compression ratio does vary between different versions of the library.
func Compress(input []byte) ([]byte, error) {
length := len(input)
if length == 0 {
return nil, errors.New("no input provided")
}
result := make([]byte, length*2)
size := C.fastlz_compress(unsafe.Pointer(&input[0]), C.int(length), unsafe.Pointer(&result[0]))
runtime.KeepAlive(input)
if size == 0 {
return nil, errors.New("error compressing data")
}
return result[:size], nil
}
/*
FastLZ - Byte-aligned LZ77 compression library
Copyright (C) 2005-2020 Ariya Hidayat <ariya.hidayat@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
This implementation is taken from the following repository/commit:
https://github.com/ariya/FastLZ/tree/344eb4025f9ae866ebf7a2ec48850f7113a97a42
*/
#ifndef FASTLZ_H
#define FASTLZ_H
#define FASTLZ_VERSION 0x000500
#define FASTLZ_VERSION_MAJOR 0
#define FASTLZ_VERSION_MINOR 5
#define FASTLZ_VERSION_REVISION 0
#define FASTLZ_VERSION_STRING "0.5.0"
#if defined(__cplusplus)
extern "C" {
#endif
/**
Compress a block of data in the input buffer and returns the size of
compressed block. The size of input buffer is specified by length. The
minimum input buffer size is 16.
The output buffer must be at least 5% larger than the input buffer
and can not be smaller than 66 bytes.
If the input is not compressible, the return value might be larger than
length (input buffer size).
The input buffer and the output buffer can not overlap.
Compression level can be specified in parameter level. At the moment,
only level 1 and level 2 are supported.
Level 1 is the fastest compression and generally useful for short data.
Level 2 is slightly slower but it gives better compression ratio.
Note that the compressed data, regardless of the level, can always be
decompressed using the function fastlz_decompress below.
*/
int fastlz_compress_level(int level, const void* input, int length, void* output);
/**
Decompress a block of compressed data and returns the size of the
decompressed block. If error occurs, e.g. the compressed data is
corrupted or the output buffer is not large enough, then 0 (zero)
will be returned instead.
The input buffer and the output buffer can not overlap.
Decompression is memory safe and guaranteed not to write the output buffer
more than what is specified in maxout.
Note that the decompression will always work, regardless of the
compression level specified in fastlz_compress_level above (when
producing the compressed block).
*/
int fastlz_decompress(const void* input, int length, void* output, int maxout);
/**
DEPRECATED.
This is similar to fastlz_compress_level above, but with the level
automatically chosen.
This function is deprecated and it will be completely removed in some future
version.
*/
int fastlz_compress(const void* input, int length, void* output);
#if defined(__cplusplus)
}
#endif
#endif /* FASTLZ_H */
package op_e2e
import (
"context"
"encoding/binary"
"fmt"
"math/big"
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-e2e/fastlz"
"github.com/ethereum-optimism/optimism/op-service/predeploys"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient/simulated"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
)
var (
// This bytecode and ABI is for a contract, which wraps the LibZip library for easier fuzz testing.
// The source of this contract is here: https://github.com/danyalprout/fastlz/blob/main/src/FastLz.sol#L6-L10
contract = &bind.MetaData{
ABI: "[{\"type\":\"function\",\"name\":\"fastLz\",\"inputs\":[{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"pure\"}]",
}
fastLzBytecode = "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063920a769114610030575b600080fd5b61004361003e366004610374565b610055565b60405190815260200160405180910390f35b600061006082610067565b5192915050565b60606101e0565b818153600101919050565b600082840393505b838110156100a25782810151828201511860001a1590930292600101610081565b9392505050565b825b602082106100d75782516100c0601f8361006e565b5260209290920191601f19909101906021016100ab565b81156100a25782516100ec600184038361006e565b520160010192915050565b60006001830392505b61010782106101385761012a8360ff1661012560fd6101258760081c60e0018961006e565b61006e565b935061010682039150610100565b600782106101655761015e8360ff16610125600785036101258760081c60e0018961006e565b90506100a2565b61017e8360ff166101258560081c8560051b018761006e565b949350505050565b80516101d890838303906101bc90600081901a600182901a60081b1760029190911a60101b17639e3779b90260131c611fff1690565b8060021b6040510182815160e01c1860e01b8151188152505050565b600101919050565b5060405161800038823961800081016020830180600d8551820103826002015b81811015610313576000805b50508051604051600082901a600183901a60081b1760029290921a60101b91909117639e3779b9810260111c617ffc16909101805160e081811c878603811890911b9091189091528401908183039084841061026857506102a3565b600184019350611fff821161029d578251600081901a600182901a60081b1760029190911a60101b17810361029d57506102a3565b5061020c565b8383106102b1575050610313565b600183039250858311156102cf576102cc87878886036100a9565b96505b6102e3600985016003850160038501610079565b91506102f08782846100f7565b9650506103088461030386848601610186565b610186565b915050809350610200565b5050617fe061032884848589518601036100a9565b03925050506020820180820383525b81811161034e57617fe08101518152602001610337565b5060008152602001604052919050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561038657600080fd5b813567ffffffffffffffff8082111561039e57600080fd5b818401915084601f8301126103b257600080fd5b8135818111156103c4576103c461035e565b604051601f8201601f19908116603f011681019083821181831017156103ec576103ec61035e565b8160405282815287602084870101111561040557600080fd5b82602086016020830137600092810160200192909252509594505050505056fea264697066735822122000646b2953fc4a6f501bd0456ac52203089443937719e16b3190b7979c39511264736f6c63430008190033"
seeds = [][]byte{
// https: //basescan.org/tx/0x5dadeb52979f29fc7a7494c43fdabc5be1d8ff404f3aafe93d729fa8e5d00769
common.FromHex("0xb9047c02f904788221050883036ee48409c6c87383037f6f941195cf65f83b3a5768f3c496d3a05ad6412c64b78644364c5bb000b90404d123b4d80000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000f6476f90447748c19248ccaa31e6b8bfda4eb9d830f5f47df7f0998f7c2123d9e6137761b75d3184efb0f788e3b14516000000000000000000000000000000000000000000000000000044364c5bb000000000000000000000000000f38e53bd45c8225a7c94b513beadaa7afe5d222d0000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084d6574614d61736b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d656852577a743347745961776343347564745657557233454c587261436746434259416b66507331696f48610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000cd0d83d9e840f8e27d5c2e365fd365ff1c05b2480000000000000000000000000000000000000000000000000000000000000ce40000000000000000000000000000000000000000000000000000000000000041e4480d358dbae20880960a0a464d63b06565a0c9f9b1b37aa94b522247b23ce149c81359bf4239d1a879eeb41047ec710c15f5c0f67453da59a383e6abd742971c00000000000000000000000000000000000000000000000000000000000000c001a0b57f0ff8516ea29cb26a44ac5055a5420847d1e16a8e7b03b70f0c02291ff2d5a00ad3771e5f39ccacfff0faa8c5d25ef7a1c179f79e66e828ffddcb994c8b512e"),
// https://basescan.org/tx/0xfaada76a2dac09fc17f5a28d066aaabefc6d82ef6589b211ed8c9f766b070721
common.FromHex("b87602f873822105528304320f8409cfe5c98252089480c67432656d59144ceff962e8faf8926599bcf888011dfe52d06b633f80c001a08632f069f837aea7a28bab0affee14dda116956bd5a850a355c045d25afedd17a0084b8f273efffe17ece527116053e5781a4915ff89ab9c379f1e62c25b697687"),
// https://basescan.org/tx/0x112864e9b971af6a1dac840018833c5a5a659acc187cfdaba919ad1da013678d
common.FromHex("b8b302f8b0822105308304320f8409cfe5c9827496944ed4e862860bed51a9570b96d89af5e1b0efefed80b844095ea7b3000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba300000000000000000000000000000000000000000000015e10fb0973595fffffc001a02020e39f07917c1a852feb131c857e12478c7e88a20772b91a8bf5cee38c5aeea06055981727f9aaa3471c1af800555b35a77916c154be3f9d02ad1a63029455ab"),
// https://basescan.org/tx/0x6905051352691641888d0c427fb137c5b95afb5870d5169ff014eff1d0952195
common.FromHex("b87202f86f8221058303dc6c8310db1f84068fa8d7838954409436af2ff952a7355c8045fcd5e88bc9f6c8257f7b8080c001a0b89e7ff3d7694109e73e7f4244e032581670313c36e48e485c9c94b853bd81d2a038ffaf8f10859ce21d1f7f7046c3d08027fb8aa15b69038f6102be97aaa1179a"),
// https://basescan.org/tx/0x6a38e9a26d7202a2268de69d2d47531c1a9829867579a483fb48d78e9e0b080d
common.FromHex("b9049b02f904978221058201618506fc23ac008506fc23ac008306ddd0943fc91a3afd70395cd496c647d5a6cc9d4b2b7fad80b904243593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000006641d67b00000000000000000000000000000000000000000000000000000000000000030a000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000088487bd8c3222d64d1d0b3fa7098dcf9d94d79e000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000006669635d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fad000000000000000000000000000000000000000000000000000000006641d78900000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000418661369ca026f92ff88347bd0e3625a7b5ed65071b366368c68ad7c55aed136c18659b34f9246e30a784227a53dd374fbd3d2124696808c678cd987c4e954a681b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000549e5c020c764dbfffff00000000000000000000000000000000000000000000000002e5a629c093a2b600000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002b088487bd8c3222d64d1d0b3fa7098dcf9d94d79e0027104200000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000c001a014a3acef764ff6d3bb9bd81e420bfa94171a5734ab997dfbc9b41b653ce018a4a01ff5fccb01ef5c60ba3aef67d4e74f3f47312dd78bfbbff9e5090fbf2d3d62bb"),
}
)
type testStateGetter struct {
baseFee, blobBaseFee, overhead, scalar *big.Int
baseFeeScalar, blobBaseFeeScalar uint32
}
func (sg *testStateGetter) GetState(addr common.Address, slot common.Hash) common.Hash {
buf := common.Hash{}
switch slot {
case types.L1BaseFeeSlot:
sg.baseFee.FillBytes(buf[:])
case types.OverheadSlot:
sg.overhead.FillBytes(buf[:])
case types.ScalarSlot:
sg.scalar.FillBytes(buf[:])
case types.L1BlobBaseFeeSlot:
sg.blobBaseFee.FillBytes(buf[:])
case types.L1FeeScalarsSlot:
// fetch Ecotone fee sclars
offset := 32 - types.BaseFeeScalarSlotOffset - 4 // todo maybe make scalarSelectSTartPublic
binary.BigEndian.PutUint32(buf[offset:offset+4], sg.baseFeeScalar)
binary.BigEndian.PutUint32(buf[offset+4:offset+8], sg.blobBaseFeeScalar)
default:
panic("unknown slot")
}
return buf
}
func FuzzFjordCostFunction(f *testing.F) {
for _, seed := range seeds {
f.Add(seed)
}
cfg := DefaultSystemConfig(f)
s := hexutil.Uint64(0)
cfg.DeployConfig.L2GenesisCanyonTimeOffset = &s
cfg.DeployConfig.L2GenesisDeltaTimeOffset = &s
cfg.DeployConfig.L2GenesisEcotoneTimeOffset = &s
cfg.DeployConfig.L2GenesisFjordTimeOffset = &s
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
opGeth, err := NewOpGeth(f, ctx, &cfg)
require.NoError(f, err)
defer opGeth.Close()
gpoCaller, err := bindings.NewGasPriceOracleCaller(predeploys.GasPriceOracleAddr, opGeth.L2Client)
require.NoError(f, err)
isFjord, err := gpoCaller.IsFjord(&bind.CallOpts{})
require.NoError(f, err)
require.True(f, isFjord)
_, err = opGeth.AddL2Block(context.Background())
require.NoError(f, err)
baseFee, err := gpoCaller.L1BaseFee(&bind.CallOpts{})
require.NoError(f, err)
require.Greater(f, baseFee.Uint64(), uint64(0))
blobBaseFee, err := gpoCaller.BlobBaseFee(&bind.CallOpts{})
require.NoError(f, err)
require.Greater(f, blobBaseFee.Uint64(), uint64(0))
baseFeeScalar, err := gpoCaller.BaseFeeScalar(&bind.CallOpts{})
require.NoError(f, err)
require.Greater(f, baseFeeScalar, uint32(0))
blobBaseFeeScalar, err := gpoCaller.BlobBaseFeeScalar(&bind.CallOpts{})
require.NoError(f, err)
require.Equal(f, blobBaseFeeScalar, uint32(0))
// we can ignore the blobbasefee, as the scalar is set to zero.
feeScaled := big.NewInt(16)
feeScaled.Mul(feeScaled, baseFee)
feeScaled.Mul(feeScaled, big.NewInt(int64(baseFeeScalar)))
db := &testStateGetter{
baseFee: baseFee,
blobBaseFee: blobBaseFee,
overhead: big.NewInt(0), // not used for fjord
scalar: big.NewInt(0), // not used for fjord
baseFeeScalar: baseFeeScalar,
blobBaseFeeScalar: blobBaseFeeScalar,
}
zeroTime := uint64(0)
// create a config where ecotone/fjord upgrades are active
config := &params.ChainConfig{
Optimism: params.OptimismTestConfig.Optimism,
RegolithTime: &zeroTime,
EcotoneTime: &zeroTime,
FjordTime: &zeroTime,
}
require.True(f, config.IsOptimismEcotone(zeroTime))
require.True(f, config.IsOptimismFjord(zeroTime))
costFunc := types.NewL1CostFunc(config, db)
f.Fuzz(func(t *testing.T, fuzzedData []byte) {
flzSize := types.FlzCompressLen(fuzzedData)
// Skip transactions that will be clamped to the minimum or less. These will fuzz to different values
// due to the solidity l1BlockGenesis adding 68 extra bytes to account for the signature.
estimatedSize := big.NewInt(int64(flzSize))
estimatedSize.Mul(estimatedSize, types.L1CostFastlzCoef)
estimatedSize.Add(estimatedSize, types.L1CostIntercept)
if estimatedSize.Cmp(types.MinTransactionSizeScaled) < 0 {
t.Skip()
return
}
l1FeeSolidity, err := gpoCaller.GetL1Fee(&bind.CallOpts{}, fuzzedData)
require.NoError(t, err)
// remove the adjustment
l1FeeSolidity.Mul(l1FeeSolidity, big.NewInt(1e12))
l1FeeSolidity.Div(l1FeeSolidity, feeScaled)
totalAdjustment := new(big.Int).Mul(big.NewInt(68), big.NewInt(836_500))
l1FeeSolidity.Sub(l1FeeSolidity, totalAdjustment)
l1FeeSolidity.Mul(l1FeeSolidity, feeScaled)
l1FeeSolidity.Div(l1FeeSolidity, big.NewInt(1e12))
costData := types.NewRollupCostData(fuzzedData)
l1FeeGeth := costFunc(costData, zeroTime)
require.Equal(t, l1FeeGeth.Uint64(), l1FeeSolidity.Uint64(), fmt.Sprintf("fuzzedData: %x", common.Bytes2Hex(fuzzedData)))
})
}
func FuzzFastLzGethSolidity(f *testing.F) {
for _, seed := range seeds {
f.Add(seed)
}
contractAbi, err := contract.GetAbi()
require.NoError(f, err)
b := simulated.NewBackend(map[common.Address]types.Account{
predeploys.GasPriceOracleAddr: {
Code: common.FromHex(fastLzBytecode),
},
})
defer func() {
require.NoError(f, b.Close())
}()
client := b.Client()
f.Fuzz(func(t *testing.T, data []byte) {
req, err := contractAbi.Pack("fastLz", data)
require.NoError(t, err)
response, err := client.CallContract(context.Background(), ethereum.CallMsg{
To: &predeploys.GasPriceOracleAddr,
Data: req,
}, nil)
require.NoError(t, err)
result, err := contractAbi.Unpack("fastLz", response)
require.NoError(t, err)
gethCompressedLen := types.FlzCompressLen(data)
require.Equal(t, result[0].(*big.Int).Uint64(), uint64(gethCompressedLen))
})
}
func FuzzFastLzCgo(f *testing.F) {
for _, seed := range seeds {
f.Add(seed)
}
f.Fuzz(func(t *testing.T, data []byte) {
if len(data) == 0 {
t.Skip()
return
}
// Our implementation in go-ethereum
compressedLen := types.FlzCompressLen(data)
out, err := fastlz.Compress(data)
require.NoError(t, err)
require.Equal(t, int(compressedLen), len(out))
})
}
...@@ -51,7 +51,7 @@ type OpGeth struct { ...@@ -51,7 +51,7 @@ type OpGeth struct {
lgr log.Logger lgr log.Logger
} }
func NewOpGeth(t *testing.T, ctx context.Context, cfg *SystemConfig) (*OpGeth, error) { func NewOpGeth(t testing.TB, ctx context.Context, cfg *SystemConfig) (*OpGeth, error) {
logger := testlog.Logger(t, log.LevelCrit) logger := testlog.Logger(t, log.LevelCrit)
l1Genesis, err := genesis.BuildL1DeveloperGenesis(cfg.DeployConfig, config.L1Allocs, config.L1Deployments) l1Genesis, err := genesis.BuildL1DeveloperGenesis(cfg.DeployConfig, config.L1Allocs, config.L1Deployments)
......
...@@ -84,7 +84,7 @@ func newTxMgrConfig(l1Addr string, privKey *ecdsa.PrivateKey) txmgr.CLIConfig { ...@@ -84,7 +84,7 @@ func newTxMgrConfig(l1Addr string, privKey *ecdsa.PrivateKey) txmgr.CLIConfig {
} }
} }
func DefaultSystemConfig(t *testing.T) SystemConfig { func DefaultSystemConfig(t testing.TB) SystemConfig {
config.ExternalL2TestParms.SkipIfNecessary(t) config.ExternalL2TestParms.SkipIfNecessary(t)
secrets, err := e2eutils.DefaultMnemonicConfig.Secrets() secrets, err := e2eutils.DefaultMnemonicConfig.Secrets()
...@@ -161,7 +161,7 @@ func DefaultSystemConfig(t *testing.T) SystemConfig { ...@@ -161,7 +161,7 @@ func DefaultSystemConfig(t *testing.T) SystemConfig {
} }
} }
func writeDefaultJWT(t *testing.T) string { func writeDefaultJWT(t testing.TB) string {
// Sadly the geth node config cannot load JWT secret from memory, it has to be a file // Sadly the geth node config cannot load JWT secret from memory, it has to be a file
jwtPath := path.Join(t.TempDir(), "jwt_secret") jwtPath := path.Join(t.TempDir(), "jwt_secret")
if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(testingJWTSecret[:])), 0o600); err != nil { if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(testingJWTSecret[:])), 0o600); err != nil {
......
...@@ -1211,6 +1211,18 @@ func TestFees(t *testing.T) { ...@@ -1211,6 +1211,18 @@ func TestFees(t *testing.T) {
cfg.DeployConfig.L2GenesisEcotoneTimeOffset = new(hexutil.Uint64) cfg.DeployConfig.L2GenesisEcotoneTimeOffset = new(hexutil.Uint64)
testFees(t, cfg) testFees(t, cfg)
}) })
t.Run("fjord", func(t *testing.T) {
InitParallel(t)
cfg := DefaultSystemConfig(t)
cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7))
cfg.DeployConfig.L2GenesisRegolithTimeOffset = new(hexutil.Uint64)
cfg.DeployConfig.L2GenesisCanyonTimeOffset = new(hexutil.Uint64)
cfg.DeployConfig.L2GenesisDeltaTimeOffset = new(hexutil.Uint64)
cfg.DeployConfig.L2GenesisEcotoneTimeOffset = new(hexutil.Uint64)
cfg.DeployConfig.L2GenesisFjordTimeOffset = new(hexutil.Uint64)
testFees(t, cfg)
})
} }
func testFees(t *testing.T, cfg SystemConfig) { func testFees(t *testing.T, cfg SystemConfig) {
...@@ -1352,11 +1364,25 @@ func testFees(t *testing.T, cfg SystemConfig) { ...@@ -1352,11 +1364,25 @@ func testFees(t *testing.T, cfg SystemConfig) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, sys.RollupConfig.IsEcotone(header.Time), gpoEcotone, "GPO and chain must have same ecotone view") require.Equal(t, sys.RollupConfig.IsEcotone(header.Time), gpoEcotone, "GPO and chain must have same ecotone view")
gpoFjord, err := gpoContract.IsFjord(nil)
require.NoError(t, err)
require.Equal(t, sys.RollupConfig.IsFjord(header.Time), gpoFjord, "GPO and chain must have same fjord view")
gpoL1Fee, err := gpoContract.GetL1Fee(&bind.CallOpts{}, bytes) gpoL1Fee, err := gpoContract.GetL1Fee(&bind.CallOpts{}, bytes)
require.Nil(t, err) require.Nil(t, err)
adjustedGPOFee := gpoL1Fee adjustedGPOFee := gpoL1Fee
if sys.RollupConfig.IsRegolith(header.Time) { if sys.RollupConfig.IsFjord(header.Time) {
// The fastlz size of the transaction is 102 bytes
require.Equal(t, uint64(102), tx.RollupCostData().FastLzSize)
// Which results in both the fjord cost function and GPO using the minimum value for the fastlz regression:
// Geth Linear Regression: -42.5856 + 102 * 0.8365 = 42.7374
// GPO Linear Regression: -42.5856 + 170 * 0.8365 = 99.6194
// The additional 68 (170 vs. 102) is due to the GPO adding 68 bytes to account for the signature.
require.Greater(t, types.MinTransactionSize.Uint64(), uint64(99))
// Because of this, we don't need to do any adjustment as the GPO and cost func are both bounded to the minimum value.
// However, if the fastlz regression output is ever larger than the minimum, this will require an adjustment.
} else if sys.RollupConfig.IsRegolith(header.Time) {
// if post-regolith, adjust the GPO fee by removing the overhead it adds because of signature data // if post-regolith, adjust the GPO fee by removing the overhead it adds because of signature data
artificialGPOOverhead := big.NewInt(68 * 16) // it adds 68 bytes to cover signature and RLP data artificialGPOOverhead := big.NewInt(68 * 16) // it adds 68 bytes to cover signature and RLP data
l1BaseFee := big.NewInt(7) // we assume the L1 basefee is the minimum, 7 l1BaseFee := big.NewInt(7) // we assume the L1 basefee is the minimum, 7
......
...@@ -108,6 +108,14 @@ func (ba *FetchingAttributesBuilder) PreparePayloadAttributes(ctx context.Contex ...@@ -108,6 +108,14 @@ func (ba *FetchingAttributesBuilder) PreparePayloadAttributes(ctx context.Contex
} }
} }
if ba.rollupCfg.IsFjordActivationBlock(nextL2Time) {
fjord, err := FjordNetworkUpgradeTransactions()
if err != nil {
return nil, NewCriticalError(fmt.Errorf("failed to build fjord network upgrade txs: %w", err))
}
upgradeTxs = append(upgradeTxs, fjord...)
}
l1InfoTx, err := L1InfoDepositBytes(ba.rollupCfg, sysConfig, seqNumber, l1Info, nextL2Time) l1InfoTx, err := L1InfoDepositBytes(ba.rollupCfg, sysConfig, seqNumber, l1Info, nextL2Time)
if err != nil { if err != nil {
return nil, NewCriticalError(fmt.Errorf("failed to create l1InfoTx: %w", err)) return nil, NewCriticalError(fmt.Errorf("failed to create l1InfoTx: %w", err))
......
package derive
import (
"math/big"
"github.com/ethereum-optimism/optimism/op-service/predeploys"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
)
var (
// Gas Price Oracle Parameters
deployFjordGasPriceOracleSource = UpgradeDepositSource{Intent: "Fjord: Gas Price Oracle Deployment"}
GasPriceOracleFjordDeployerAddress = common.HexToAddress("0x4210000000000000000000000000000000000002")
// Fjord GPO Deployment bytecode generated from:
// 1. git checkout 52abfb507342191ae1f960b443ae8aec7598755c
// 2. pnpm clean && pnpm install && pnpm build
// 3. jq -r ".bytecode.object" packages/contracts-bedrock/forge-artifacts/GasPriceOracle.sol/GasPriceOracle.json
// https://github.com/ethereum-optimism/specs/blob/2dd412ce42171b4041e826fd6b8defacc88e8f56/specs/fjord/derivation.md#gaspriceoracle-deployment
gasPriceOracleFjordDeploymentBytecode = common.FromHex("0x608060405234801561001057600080fd5b506117f6806100206000396000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c80636ef25c3a116100b2578063de26c4a111610081578063f45e65d811610066578063f45e65d81461025b578063f820614014610263578063fe173b971461020d57600080fd5b8063de26c4a114610235578063f1c7a58b1461024857600080fd5b80636ef25c3a1461020d5780638e98b10614610213578063960e3a231461021b578063c59859181461022d57600080fd5b806349948e0e11610109578063519b4bd3116100ee578063519b4bd31461019f57806354fd4d50146101a757806368d5dca6146101f057600080fd5b806349948e0e1461016f5780634ef6e2241461018257600080fd5b80630c18c1621461013b57806322b90ab3146101565780632e0f262514610160578063313ce56714610168575b600080fd5b61014361026b565b6040519081526020015b60405180910390f35b61015e61038c565b005b610143600681565b6006610143565b61014361017d3660046112a1565b610515565b60005461018f9060ff1681565b604051901515815260200161014d565b610143610552565b6101e36040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b60405161014d9190611370565b6101f86105b3565b60405163ffffffff909116815260200161014d565b48610143565b61015e610638565b60005461018f90610100900460ff1681565b6101f8610832565b6101436102433660046112a1565b610893565b6101436102563660046113e3565b61098d565b610143610a69565b610143610b5c565b6000805460ff1615610304576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f47617350726963654f7261636c653a206f76657268656164282920697320646560448201527f707265636174656400000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610363573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061038791906113fc565b905090565b3373deaddeaddeaddeaddeaddeaddeaddeaddead000114610455576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f47617350726963654f7261636c653a206f6e6c7920746865206465706f73697460448201527f6f72206163636f756e742063616e2073657420697345636f746f6e6520666c6160648201527f6700000000000000000000000000000000000000000000000000000000000000608482015260a4016102fb565b60005460ff16156104e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f47617350726963654f7261636c653a2045636f746f6e6520616c72656164792060448201527f616374697665000000000000000000000000000000000000000000000000000060648201526084016102fb565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b60008054610100900460ff16156105355761052f82610bbd565b92915050565b60005460ff16156105495761052f82610bdc565b61052f82610c80565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16635cf249696040518163ffffffff1660e01b8152600401602060405180830381865afa158015610363573d6000803e3d6000fd5b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff166368d5dca66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610614573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103879190611415565b3373deaddeaddeaddeaddeaddeaddeaddeaddead0001146106db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f47617350726963654f7261636c653a206f6e6c7920746865206465706f73697460448201527f6f72206163636f756e742063616e20736574206973466a6f726420666c61670060648201526084016102fb565b60005460ff1661076d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f47617350726963654f7261636c653a20466a6f72642063616e206f6e6c79206260448201527f65206163746976617465642061667465722045636f746f6e650000000000000060648201526084016102fb565b600054610100900460ff1615610804576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f47617350726963654f7261636c653a20466a6f726420616c726561647920616360448201527f746976650000000000000000000000000000000000000000000000000000000060648201526084016102fb565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663c59859186040518163ffffffff1660e01b8152600401602060405180830381865afa158015610614573d6000803e3d6000fd5b60008054610100900460ff16156108da57620f42406108c56108b484610dd4565b516108c090604461146a565b6110f1565b6108d0906010611482565b61052f91906114bf565b60006108e583611150565b60005490915060ff16156108f95792915050565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610958573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097c91906113fc565b610986908261146a565b9392505050565b60008054610100900460ff16610a25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f47617350726963654f7261636c653a206765744c314665655570706572426f7560448201527f6e64206f6e6c7920737570706f72747320466a6f72640000000000000000000060648201526084016102fb565b6000610a3283604461146a565b90506000610a4160ff836114bf565b610a4b908361146a565b610a5690601061146a565b9050610a61816111e0565b949350505050565b6000805460ff1615610afd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f47617350726963654f7261636c653a207363616c61722829206973206465707260448201527f656361746564000000000000000000000000000000000000000000000000000060648201526084016102fb565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16639e8c49666040518163ffffffff1660e01b8152600401602060405180830381865afa158015610363573d6000803e3d6000fd5b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663f82061406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610363573d6000803e3d6000fd5b600061052f610bcb83610dd4565b51610bd790604461146a565b6111e0565b600080610be883611150565b90506000610bf4610552565b610bfc610832565b610c079060106114fa565b63ffffffff16610c179190611482565b90506000610c23610b5c565b610c2b6105b3565b63ffffffff16610c3b9190611482565b90506000610c49828461146a565b610c539085611482565b9050610c616006600a611646565b610c6c906010611482565b610c7690826114bf565b9695505050505050565b600080610c8c83611150565b9050600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16639e8c49666040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1391906113fc565b610d1b610552565b73420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638b239f736040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9e91906113fc565b610da8908561146a565b610db29190611482565b610dbc9190611482565b9050610dca6006600a611646565b610a6190826114bf565b6060610f63565b818153600101919050565b600082840393505b838110156109865782810151828201511860001a1590930292600101610dee565b825b60208210610e5b578251610e26601f83610ddb565b52602092909201917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090910190602101610e11565b8115610986578251610e706001840383610ddb565b520160010192915050565b60006001830392505b6101078210610ebc57610eae8360ff16610ea960fd610ea98760081c60e00189610ddb565b610ddb565b935061010682039150610e84565b60078210610ee957610ee28360ff16610ea960078503610ea98760081c60e00189610ddb565b9050610986565b610a618360ff16610ea98560081c8560051b0187610ddb565b610f5b828203610f3f610f2f84600081518060001a8160011a60081b178160021a60101b17915050919050565b639e3779b90260131c611fff1690565b8060021b6040510182815160e01c1860e01b8151188152505050565b600101919050565b6180003860405139618000604051016020830180600d8551820103826002015b81811015611096576000805b50508051604051600082901a600183901a60081b1760029290921a60101b91909117639e3779b9810260111c617ffc16909101805160e081811c878603811890911b90911890915284019081830390848410610feb5750611026565b600184019350611fff8211611020578251600081901a600182901a60081b1760029190911a60101b1781036110205750611026565b50610f8f565b838310611034575050611096565b600183039250858311156110525761104f8787888603610e0f565b96505b611066600985016003850160038501610de6565b9150611073878284610e7b565b96505061108b8461108686848601610f02565b610f02565b915050809350610f83565b50506110a88383848851850103610e0f565b925050506040519150618000820180820391508183526020830160005b838110156110dd5782810151828201526020016110c5565b506000920191825250602001604052919050565b60008061110183620cc394611482565b61112b907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd763200611652565b905061113b6064620f42406116c6565b81121561052f576109866064620f42406116c6565b80516000908190815b818110156111d35784818151811061117357611173611782565b01602001517fff00000000000000000000000000000000000000000000000000000000000000166000036111b3576111ac60048461146a565b92506111c1565b6111be60108461146a565b92505b806111cb816117b1565b915050611159565b50610a618261044061146a565b6000806111ec836110f1565b905060006111f8610b5c565b6112006105b3565b63ffffffff166112109190611482565b611218610552565b611220610832565b61122b9060106114fa565b63ffffffff1661123b9190611482565b611245919061146a565b905061125360066002611482565b61125e90600a611646565b6112688284611482565b610a6191906114bf565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156112b357600080fd5b813567ffffffffffffffff808211156112cb57600080fd5b818401915084601f8301126112df57600080fd5b8135818111156112f1576112f1611272565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561133757611337611272565b8160405282815287602084870101111561135057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208083528351808285015260005b8181101561139d57858101830151858201604001528201611381565b818111156113af576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b6000602082840312156113f557600080fd5b5035919050565b60006020828403121561140e57600080fd5b5051919050565b60006020828403121561142757600080fd5b815163ffffffff8116811461098657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561147d5761147d61143b565b500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156114ba576114ba61143b565b500290565b6000826114f5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600063ffffffff8083168185168183048111821515161561151d5761151d61143b565b02949350505050565b600181815b8085111561157f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156115655761156561143b565b8085161561157257918102915b93841c939080029061152b565b509250929050565b6000826115965750600161052f565b816115a35750600061052f565b81600181146115b957600281146115c3576115df565b600191505061052f565b60ff8411156115d4576115d461143b565b50506001821b61052f565b5060208310610133831016604e8410600b8410161715611602575081810a61052f565b61160c8383611526565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561163e5761163e61143b565b029392505050565b60006109868383611587565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0384138115161561168c5761168c61143b565b827f80000000000000000000000000000000000000000000000000000000000000000384128116156116c0576116c061143b565b50500190565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156117075761170761143b565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156117425761174261143b565b6000871292508782058712848416161561175e5761175e61143b565b878505871281841616156117745761177461143b565b505050929093029392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036117e2576117e261143b565b506001019056fea164736f6c634300080f000a")
// Update GasPricePriceOracle Proxy Parameters
updateFjordGasPriceOracleSource = UpgradeDepositSource{Intent: "Fjord: Gas Price Oracle Proxy Update"}
fjordGasPriceOracleAddress = common.HexToAddress("0xa919894851548179A0750865e7974DA599C0Fac7")
// Enable Fjord Parameters
enableFjordSource = UpgradeDepositSource{Intent: "Fjord: Gas Price Oracle Set Fjord"}
enableFjordInput = crypto.Keccak256([]byte("setFjord()"))[:4]
)
// FjordNetworkUpgradeTransactions returns the transactions required to upgrade the Fjord network.
func FjordNetworkUpgradeTransactions() ([]hexutil.Bytes, error) {
upgradeTxns := make([]hexutil.Bytes, 0, 3)
// Deploy Gas Price Oracle transaction
deployGasPriceOracle, err := types.NewTx(&types.DepositTx{
SourceHash: deployFjordGasPriceOracleSource.SourceHash(),
From: GasPriceOracleFjordDeployerAddress,
To: nil,
Mint: big.NewInt(0),
Value: big.NewInt(0),
Gas: 1_450_000,
IsSystemTransaction: false,
Data: gasPriceOracleFjordDeploymentBytecode,
}).MarshalBinary()
if err != nil {
return nil, err
}
upgradeTxns = append(upgradeTxns, deployGasPriceOracle)
updateGasPriceOracleProxy, err := types.NewTx(&types.DepositTx{
SourceHash: updateFjordGasPriceOracleSource.SourceHash(),
From: common.Address{},
To: &predeploys.GasPriceOracleAddr,
Mint: big.NewInt(0),
Value: big.NewInt(0),
Gas: 50_000,
IsSystemTransaction: false,
Data: upgradeToCalldata(fjordGasPriceOracleAddress),
}).MarshalBinary()
if err != nil {
return nil, err
}
upgradeTxns = append(upgradeTxns, updateGasPriceOracleProxy)
enableFjord, err := types.NewTx(&types.DepositTx{
SourceHash: enableFjordSource.SourceHash(),
From: L1InfoDepositerAddress,
To: &predeploys.GasPriceOracleAddr,
Mint: big.NewInt(0),
Value: big.NewInt(0),
Gas: 90_000,
IsSystemTransaction: false,
Data: enableFjordInput,
}).MarshalBinary()
if err != nil {
return nil, err
}
upgradeTxns = append(upgradeTxns, enableFjord)
return upgradeTxns, nil
}
package derive
import (
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
func TestFjordSourcesMatchSpec(t *testing.T) {
for _, test := range []struct {
source UpgradeDepositSource
expectedHash string
}{
{
source: deployFjordGasPriceOracleSource,
expectedHash: "0x86122c533fdcb89b16d8713174625e44578a89751d96c098ec19ab40a51a8ea3",
},
{
source: updateFjordGasPriceOracleSource,
expectedHash: "0x1e6bb0c28bfab3dc9b36ffb0f721f00d6937f33577606325692db0965a7d58c6",
},
{
source: enableFjordSource,
expectedHash: "0xbac7bb0d5961cad209a345408b0280a0d4686b1b20665e1b0f9cdafd73b19b6b",
},
} {
require.Equal(t, common.HexToHash(test.expectedHash), test.source.SourceHash())
}
}
func TestFjordNetworkTransactions(t *testing.T) {
upgradeTxns, err := FjordNetworkUpgradeTransactions()
require.NoError(t, err)
require.Len(t, upgradeTxns, 3)
deployGasPriceOracleSender, deployGasPriceOracle := toDepositTxn(t, upgradeTxns[0])
require.Equal(t, deployGasPriceOracleSender, common.HexToAddress("0x4210000000000000000000000000000000000002"))
require.Equal(t, deployFjordGasPriceOracleSource.SourceHash(), deployGasPriceOracle.SourceHash())
require.Nil(t, deployGasPriceOracle.To())
require.Equal(t, uint64(1_450_000), deployGasPriceOracle.Gas())
require.Equal(t, gasPriceOracleFjordDeploymentBytecode, deployGasPriceOracle.Data())
updateGasPriceOracleSender, updateGasPriceOracle := toDepositTxn(t, upgradeTxns[1])
require.Equal(t, updateGasPriceOracleSender, common.Address{})
require.Equal(t, updateFjordGasPriceOracleSource.SourceHash(), updateGasPriceOracle.SourceHash())
require.NotNil(t, updateGasPriceOracle.To())
require.Equal(t, *updateGasPriceOracle.To(), common.HexToAddress("0x420000000000000000000000000000000000000F"))
require.Equal(t, uint64(50_000), updateGasPriceOracle.Gas())
require.Equal(t, common.FromHex("0x3659cfe6000000000000000000000000a919894851548179A0750865e7974DA599C0Fac7"), updateGasPriceOracle.Data())
gpoSetFjordSender, gpoSetFjord := toDepositTxn(t, upgradeTxns[2])
require.Equal(t, gpoSetFjordSender, common.HexToAddress("0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001"))
require.Equal(t, enableFjordSource.SourceHash(), gpoSetFjord.SourceHash())
require.NotNil(t, gpoSetFjord.To())
require.Equal(t, *gpoSetFjord.To(), common.HexToAddress("0x420000000000000000000000000000000000000F"))
require.Equal(t, uint64(90_000), gpoSetFjord.Gas())
require.Equal(t, common.FromHex("0x8e98b106"), gpoSetFjord.Data())
}
...@@ -101,6 +101,12 @@ func (d *Sequencer) StartBuildingBlock(ctx context.Context) error { ...@@ -101,6 +101,12 @@ func (d *Sequencer) StartBuildingBlock(ctx context.Context) error {
d.log.Info("Sequencing Ecotone upgrade block") d.log.Info("Sequencing Ecotone upgrade block")
} }
// For the Fjord activation block we shouldn't include any sequencer transactions.
if d.rollupCfg.IsFjordActivationBlock(uint64(attrs.Timestamp)) {
attrs.NoTxPool = true
d.log.Info("Sequencing Fjord upgrade block")
}
d.log.Debug("prepared attributes for new block", d.log.Debug("prepared attributes for new block",
"num", l2Head.Number+1, "time", uint64(attrs.Timestamp), "num", l2Head.Number+1, "time", uint64(attrs.Timestamp),
"origin", l1Origin, "origin_time", l1Origin.Time, "noTxPool", attrs.NoTxPool) "origin", l1Origin, "origin_time", l1Origin.Time, "noTxPool", attrs.NoTxPool)
......
...@@ -407,6 +407,14 @@ func (c *Config) IsFjord(timestamp uint64) bool { ...@@ -407,6 +407,14 @@ func (c *Config) IsFjord(timestamp uint64) bool {
return c.FjordTime != nil && timestamp >= *c.FjordTime return c.FjordTime != nil && timestamp >= *c.FjordTime
} }
// IsFjordActivationBlock returns whether the specified block is the first block subject to the
// Fjord upgrade.
func (c *Config) IsFjordActivationBlock(l2BlockTime uint64) bool {
return c.IsFjord(l2BlockTime) &&
l2BlockTime >= c.BlockTime &&
!c.IsFjord(l2BlockTime-c.BlockTime)
}
// IsInterop returns true if the Interop hardfork is active at or past the given timestamp. // IsInterop returns true if the Interop hardfork is active at or past the given timestamp.
func (c *Config) IsInterop(timestamp uint64) bool { func (c *Config) IsInterop(timestamp uint64) bool {
return c.InteropTime != nil && timestamp >= *c.InteropTime return c.InteropTime != nil && timestamp >= *c.InteropTime
......
...@@ -180,21 +180,87 @@ func TestRandomConfigDescription(t *testing.T) { ...@@ -180,21 +180,87 @@ func TestRandomConfigDescription(t *testing.T) {
}) })
} }
// TestRegolithActivation tests the activation condition of the Regolith upgrade. // TestActivations tests the activation condition of the various upgrades.
func TestRegolithActivation(t *testing.T) { func TestActivations(t *testing.T) {
config := randConfig() for _, test := range []struct {
config.RegolithTime = nil name string
require.False(t, config.IsRegolith(0), "false if nil time, even if checking 0") setUpgradeTime func(t *uint64, c *Config)
require.False(t, config.IsRegolith(123456), "false if nil time") checkEnabled func(t uint64, c *Config) bool
config.RegolithTime = new(uint64) }{
require.True(t, config.IsRegolith(0), "true at zero") {
require.True(t, config.IsRegolith(123456), "true for any") name: "Regolith",
x := uint64(123) setUpgradeTime: func(t *uint64, c *Config) {
config.RegolithTime = &x c.RegolithTime = t
require.False(t, config.IsRegolith(0)) },
require.False(t, config.IsRegolith(122)) checkEnabled: func(t uint64, c *Config) bool {
require.True(t, config.IsRegolith(123)) return c.IsRegolith(t)
require.True(t, config.IsRegolith(124)) },
},
{
name: "Canyon",
setUpgradeTime: func(t *uint64, c *Config) {
c.CanyonTime = t
},
checkEnabled: func(t uint64, c *Config) bool {
return c.IsCanyon(t)
},
},
{
name: "Delta",
setUpgradeTime: func(t *uint64, c *Config) {
c.DeltaTime = t
},
checkEnabled: func(t uint64, c *Config) bool {
return c.IsDelta(t)
},
},
{
name: "Ecotone",
setUpgradeTime: func(t *uint64, c *Config) {
c.EcotoneTime = t
},
checkEnabled: func(t uint64, c *Config) bool {
return c.IsEcotone(t)
},
},
{
name: "Fjord",
setUpgradeTime: func(t *uint64, c *Config) {
c.FjordTime = t
},
checkEnabled: func(t uint64, c *Config) bool {
return c.IsFjord(t)
},
},
{
name: "Interop",
setUpgradeTime: func(t *uint64, c *Config) {
c.InteropTime = t
},
checkEnabled: func(t uint64, c *Config) bool {
return c.IsInterop(t)
},
},
} {
tt := test
t.Run(fmt.Sprintf("TestActivations_%s", tt.name), func(t *testing.T) {
config := randConfig()
test.setUpgradeTime(nil, config)
require.False(t, tt.checkEnabled(0, config), "false if nil time, even if checking 0")
require.False(t, tt.checkEnabled(123456, config), "false if nil time")
test.setUpgradeTime(new(uint64), config)
require.True(t, tt.checkEnabled(0, config), "true at zero")
require.True(t, tt.checkEnabled(123456, config), "true for any")
x := uint64(123)
test.setUpgradeTime(&x, config)
require.False(t, tt.checkEnabled(0, config))
require.False(t, tt.checkEnabled(122, config))
require.True(t, tt.checkEnabled(123, config))
require.True(t, tt.checkEnabled(124, config))
})
}
} }
type mockL2Client struct { type mockL2Client struct {
......
...@@ -393,45 +393,45 @@ const ( ...@@ -393,45 +393,45 @@ const (
L1ScalarEcotone = byte(1) L1ScalarEcotone = byte(1)
) )
type EcostoneScalars struct { type EcotoneScalars struct {
BlobBaseFeeScalar uint32 BlobBaseFeeScalar uint32
BaseFeeScalar uint32 BaseFeeScalar uint32
} }
func (sysCfg *SystemConfig) EcotoneScalars() (EcostoneScalars, error) { func (sysCfg *SystemConfig) EcotoneScalars() (EcotoneScalars, error) {
if err := CheckEcotoneL1SystemConfigScalar(sysCfg.Scalar); err != nil { if err := CheckEcotoneL1SystemConfigScalar(sysCfg.Scalar); err != nil {
if errors.Is(err, ErrBedrockScalarPaddingNotEmpty) { if errors.Is(err, ErrBedrockScalarPaddingNotEmpty) {
// L2 spec mandates we set baseFeeScalar to MaxUint32 if there are non-zero bytes in // L2 spec mandates we set baseFeeScalar to MaxUint32 if there are non-zero bytes in
// the padding area. // the padding area.
return EcostoneScalars{BlobBaseFeeScalar: 0, BaseFeeScalar: math.MaxUint32}, nil return EcotoneScalars{BlobBaseFeeScalar: 0, BaseFeeScalar: math.MaxUint32}, nil
} }
return EcostoneScalars{}, err return EcotoneScalars{}, err
} }
return DecodeScalar(sysCfg.Scalar) return DecodeScalar(sysCfg.Scalar)
} }
// DecodeScalar decodes the blobBaseFeeScalar and baseFeeScalar from a 32-byte scalar value. // DecodeScalar decodes the blobBaseFeeScalar and baseFeeScalar from a 32-byte scalar value.
// It uses the first byte to determine the scalar format. // It uses the first byte to determine the scalar format.
func DecodeScalar(scalar [32]byte) (EcostoneScalars, error) { func DecodeScalar(scalar [32]byte) (EcotoneScalars, error) {
switch scalar[0] { switch scalar[0] {
case L1ScalarBedrock: case L1ScalarBedrock:
return EcostoneScalars{ return EcotoneScalars{
BlobBaseFeeScalar: 0, BlobBaseFeeScalar: 0,
BaseFeeScalar: binary.BigEndian.Uint32(scalar[28:32]), BaseFeeScalar: binary.BigEndian.Uint32(scalar[28:32]),
}, nil }, nil
case L1ScalarEcotone: case L1ScalarEcotone:
return EcostoneScalars{ return EcotoneScalars{
BlobBaseFeeScalar: binary.BigEndian.Uint32(scalar[24:28]), BlobBaseFeeScalar: binary.BigEndian.Uint32(scalar[24:28]),
BaseFeeScalar: binary.BigEndian.Uint32(scalar[28:32]), BaseFeeScalar: binary.BigEndian.Uint32(scalar[28:32]),
}, nil }, nil
default: default:
return EcostoneScalars{}, fmt.Errorf("unexpected system config scalar: %x", scalar) return EcotoneScalars{}, fmt.Errorf("unexpected system config scalar: %x", scalar)
} }
} }
// EncodeScalar encodes the EcostoneScalars into a 32-byte scalar value // EncodeScalar encodes the EcotoneScalars into a 32-byte scalar value
// for the Ecotone serialization format. // for the Ecotone serialization format.
func EncodeScalar(scalars EcostoneScalars) (scalar [32]byte) { func EncodeScalar(scalars EcotoneScalars) (scalar [32]byte) {
scalar[0] = L1ScalarEcotone scalar[0] = L1ScalarEcotone
binary.BigEndian.PutUint32(scalar[24:28], scalars.BlobBaseFeeScalar) binary.BigEndian.PutUint32(scalar[24:28], scalars.BlobBaseFeeScalar)
binary.BigEndian.PutUint32(scalar[28:32], scalars.BaseFeeScalar) binary.BigEndian.PutUint32(scalar[28:32], scalars.BaseFeeScalar)
......
...@@ -59,7 +59,7 @@ func TestEcotoneScalars(t *testing.T) { ...@@ -59,7 +59,7 @@ func TestEcotoneScalars(t *testing.T) {
func FuzzEncodeScalar(f *testing.F) { func FuzzEncodeScalar(f *testing.F) {
f.Fuzz(func(t *testing.T, blobBaseFeeScalar uint32, baseFeeScalar uint32) { f.Fuzz(func(t *testing.T, blobBaseFeeScalar uint32, baseFeeScalar uint32) {
encoded := EncodeScalar(EcostoneScalars{BlobBaseFeeScalar: blobBaseFeeScalar, BaseFeeScalar: baseFeeScalar}) encoded := EncodeScalar(EcotoneScalars{BlobBaseFeeScalar: blobBaseFeeScalar, BaseFeeScalar: baseFeeScalar})
scalars, err := DecodeScalar(encoded) scalars, err := DecodeScalar(encoded)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, blobBaseFeeScalar, scalars.BlobBaseFeeScalar) require.Equal(t, blobBaseFeeScalar, scalars.BlobBaseFeeScalar)
......
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