From c0ea9b43fd72740fcb40dc7b5d5bd07a79770479 Mon Sep 17 00:00:00 2001 From: Stefan Iliev <46542846+StefanIliev545@users.noreply.github.com> Date: Wed, 26 Jun 2024 15:41:10 +0300 Subject: [PATCH 1/8] Bundle submission rework (#1966) * Contract changes. * Synchronization rework. * clear linter issues. * Abi bindings regenerated. * Log level change. * Addressed review comments. * Removed local network test. --------- Co-authored-by: StefanIliev545 --- .../ManagementContract/ManagementContract.go | 92 +++++++-- .../generated/ObscuroBridge/ObscuroBridge.go | 2 +- .../src/management/ManagementContract.sol | 29 ++- contracts/src/management/Structs.sol | 3 + go/common/errutil/errors_util.go | 3 + go/common/host/services.go | 5 +- go/host/enclave/guardian.go | 39 +--- go/host/host.go | 3 + go/host/l1/publisher.go | 49 ++--- go/host/l1/statemachine.go | 193 ++++++++++++++++++ go/host/servicelocator.go | 5 + 11 files changed, 351 insertions(+), 72 deletions(-) create mode 100644 go/host/l1/statemachine.go diff --git a/contracts/generated/ManagementContract/ManagementContract.go b/contracts/generated/ManagementContract/ManagementContract.go index 56c3665803..0ceda27945 100644 --- a/contracts/generated/ManagementContract/ManagementContract.go +++ b/contracts/generated/ManagementContract/ManagementContract.go @@ -61,8 +61,8 @@ type StructsValueTransferMessage struct { // ManagementContractMetaData contains all meta data concerning the ManagementContract contract. var ManagementContractMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"ECDSAInvalidSignatureLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"ECDSAInvalidSignatureS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAddress\",\"type\":\"address\"}],\"name\":\"ImportantContractAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"messageBusAddress\",\"type\":\"address\"}],\"name\":\"LogManagementContractCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"rollupHash\",\"type\":\"bytes32\"}],\"name\":\"RollupAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"enclaveID\",\"type\":\"address\"}],\"name\":\"SequencerEnclaveGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"enclaveID\",\"type\":\"address\"}],\"name\":\"SequencerEnclaveRevoked\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"Hash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"Signature\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"LastSequenceNumber\",\"type\":\"uint256\"}],\"internalType\":\"structStructs.MetaRollup\",\"name\":\"r\",\"type\":\"tuple\"},{\"internalType\":\"string\",\"name\":\"_rollupData\",\"type\":\"string\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"topic\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"consistencyLevel\",\"type\":\"uint8\"}],\"internalType\":\"structStructs.CrossChainMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"}],\"internalType\":\"structStructs.HeaderCrossChainData\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"AddRollup\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"Attested\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"}],\"internalType\":\"structStructs.ValueTransferMessage\",\"name\":\"_msg\",\"type\":\"tuple\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"ExtractNativeValue\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GetImportantContractKeys\",\"outputs\":[{\"internalType\":\"string[]\",\"name\":\"\",\"type\":\"string[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"rollupHash\",\"type\":\"bytes32\"}],\"name\":\"GetRollupByHash\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"Hash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"Signature\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"LastSequenceNumber\",\"type\":\"uint256\"}],\"internalType\":\"structStructs.MetaRollup\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"GrantSequencerEnclave\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_enclaveID\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_initSecret\",\"type\":\"bytes\"},{\"internalType\":\"string\",\"name\":\"_genesisAttestation\",\"type\":\"string\"}],\"name\":\"InitializeNetworkSecret\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"IsSequencerEnclave\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"IsWithdrawalAvailable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"requestReport\",\"type\":\"string\"}],\"name\":\"RequestNetworkSecret\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"attesterID\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"requesterID\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"attesterSig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"responseSecret\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"verifyAttester\",\"type\":\"bool\"}],\"name\":\"RespondNetworkSecret\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RetrieveAllBridgeFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"RevokeSequencerEnclave\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"newAddress\",\"type\":\"address\"}],\"name\":\"SetImportantContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_lastBatchHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"blockNum\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"crossChainHashes\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"name\":\"addCrossChainMessagesRoot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"importantContractAddresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"importantContractKeys\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"isWithdrawalSpent\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBatchHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBatchSeqNo\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleMessageBus\",\"outputs\":[{\"internalType\":\"contractIMerkleTreeMessageBus\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messageBus\",\"outputs\":[{\"internalType\":\"contractIMessageBus\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061001a3361001f565b610090565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b61413e80620000a06000396000f3fe60806040523480156200001157600080fd5b5060043610620001d05760003560e01c8063715018a61162000101578063a1a227fa11620000a3578063db5d91b1116200007a578063db5d91b11462000446578063e34fbfc81462000475578063e874eb20146200048a578063f2fde38b146200049e57600080fd5b8063a1a227fa146200040a578063a52f433c146200041e578063d4fab887146200042f57600080fd5b80638236a7ba11620000d85780638236a7ba146200038c5780638da5cb5b14620003b357806398077e8614620003e457600080fd5b8063715018a6146200036e5780637281099614620003785780638129fc1c146200038257600080fd5b806343348b2f11620001775780635371a216116200014e5780635371a216146200031057806368e1038314620003275780636a30d26c146200033e5780636b9707d6146200035757600080fd5b806343348b2f14620002c0578063440c953b14620002ef5780634766573814620002f957600080fd5b80632f0cb9e311620001ac5780632f0cb9e314620002225780633e60a22f14620002595780633f3f6a1814620002a957600080fd5b80620ddd2714620001d557806303e72e4814620001f25780632c77c81f146200020b575b600080fd5b620001df600a5481565b6040519081526020015b60405180910390f35b620002096200020336600462001c1b565b620004b5565b005b620002096200021c36600462001cbb565b620005c8565b620002486200023336600462001d5e565b60096020526000908152604090205460ff1681565b6040519015158152602001620001e9565b620002906200026a36600462001d78565b80516020818301810180516003825292820191909301209152546001600160a01b031681565b6040516001600160a01b039091168152602001620001e9565b62000209620002ba36600462001db9565b6200073c565b62000248620002d136600462001ed3565b6001600160a01b031660009081526020819052604090205460ff1690565b620001df60055481565b620002096200030a36600462001ed3565b620009c2565b620002096200032136600462001ef8565b62000a92565b620002096200033836600462001f92565b62000c9b565b6200034862000d88565b604051620001e9919062002070565b620002096200036836600462001ed3565b62000e6b565b6200020962000f31565b6200020962000f49565b6200020962000fcd565b620003a36200039d36600462001d5e565b620011ac565b604051620001e9929190620020d6565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031662000290565b620003fb620003f536600462001d5e565b6200129c565b604051620001e991906200211c565b60075462000290906001600160a01b031681565b600454610100900460ff1662000248565b620002096200044036600462002131565b62001351565b620002486200045736600462001ed3565b6001600160a01b031660009081526001602052604090205460ff1690565b6200020962000486366004620021dc565b5050565b60085462000290906001600160a01b031681565b62000209620004af36600462001ed3565b620014e4565b620004bf62001541565b60006001600160a01b0316600383604051620004dc919062002222565b908152604051908190036020019020546001600160a01b0316036200053b57600280546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace01620005398382620022cf565b505b806003836040516200054e919062002222565b90815260405190819003602001812080546001600160a01b039390931673ffffffffffffffffffffffffffffffffffffffff19909316929092179091557f17b2f9f5748931099ffee882b5b64f4a560b5c55da9b4f4e396dae3bb9f98cb590620005bc90849084906200239c565b60405180910390a15050565b60006200061a8535620005df6020880188620023c9565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620015b892505050565b6001600160a01b03811660009081526020819052604090205490915060ff166200068b5760405162461bcd60e51b815260206004820152601660248201527f656e636c6176654944206e6f742061747465737465640000000000000000000060448201526064015b60405180910390fd5b6001600160a01b03811660009081526001602052604090205460ff16620006f55760405162461bcd60e51b815260206004820152601960248201527f656e636c6176654944206e6f7420612073657175656e63657200000000000000604482015260640162000682565b6200070085620015e8565b604051853581527fd6555bff8670bd3008dc064c30bb56d6ac7cb14ae801e36146fe4e7c6a504a58906020015b60405180910390a15050505050565b620007498460ff62002429565b4311156200079a5760405162461bcd60e51b815260206004820152601560248201527f426c6f636b2062696e64696e6720746f6f206f6c640000000000000000000000604482015260640162000682565b848440146200080157620007ae4362001620565b620007b98662001620565b620007c5864062001620565b604051602001620007d9939291906200243f565b60408051601f198184030181529082905262461bcd60e51b825262000682916004016200211c565b60006200087387878787604051602001620008209493929190620024e4565b6040516020818303038152906040528051906020012084848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620015b892505050565b6001600160a01b03811660009081526020819052604090205490915060ff16620008e05760405162461bcd60e51b815260206004820152601660248201527f656e636c6176654944206e6f7420617474657374656400000000000000000000604482015260640162000682565b600a87905560005b8451811015620009b85760085485516001600160a01b039091169063b6aed0cb908790849081106200091e576200091e62002560565b6020026020010151620009319062002576565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526004810191909152426024820152604401600060405180830381600087803b1580156200098957600080fd5b505af11580156200099e573d6000803e3d6000fd5b505050508080620009af906200259b565b915050620008e8565b5050505050505050565b620009cc62001541565b6001600160a01b03811660009081526020819052604090205460ff1662000a365760405162461bcd60e51b815260206004820152601660248201527f656e636c6176654944206e6f7420617474657374656400000000000000000000604482015260640162000682565b6001600160a01b038116600081815260016020818152604092839020805460ff191690921790915590519182527ffe64c7181f0fc60e300dc02cca368cdfa94d7ca45902de3b9a9d80070e76093691015b60405180910390a150565b6008546040517fb201246f0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063b201246f9062000ae390879087908790879060040162002617565b60006040518083038186803b15801562000afc57600080fd5b505afa15801562000b11573d6000803e3d6000fd5b5050505060008460405160200162000b2a91906200267f565b60408051601f1981840301815291815281516020928301206000818152600990935291205490915060ff161562000ba45760405162461bcd60e51b815260206004820152601860248201527f7769746864726177616c20616c7265616479207370656e740000000000000000604482015260640162000682565b6001600960008760405160200162000bbd91906200267f565b60408051808303601f190181529181528151602092830120835282820193909352908201600020805460ff1916931515939093179092556007546001600160a01b0316916399a3ad219162000c189190890190890162001ed3565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b0390921660048301528801356024820152604401600060405180830381600087803b15801562000c7b57600080fd5b505af115801562000c90573d6000803e3d6000fd5b505050505050505050565b60045460ff161562000d165760405162461bcd60e51b815260206004820152602260248201527f6e6574776f726b2073656372657420616c726561647920696e697469616c697a60448201527f6564000000000000000000000000000000000000000000000000000000000000606482015260840162000682565b60048054600160ff1991821681179092556001600160a01b038716600081815260208181526040808320805486168717905585825291829020805490941690941790925590519081527ffe64c7181f0fc60e300dc02cca368cdfa94d7ca45902de3b9a9d80070e76093691016200072d565b60606002805480602002602001604051908101604052809291908181526020016000905b8282101562000e6257838290600052602060002001805462000dce9062002240565b80601f016020809104026020016040519081016040528092919081815260200182805462000dfc9062002240565b801562000e4d5780601f1062000e215761010080835404028352916020019162000e4d565b820191906000526020600020905b81548152906001019060200180831162000e2f57829003601f168201915b50505050508152602001906001019062000dac565b50505050905090565b62000e7562001541565b6001600160a01b03811660009081526001602052604090205460ff1662000edf5760405162461bcd60e51b815260206004820152601960248201527f656e636c6176654944206e6f7420612073657175656e63657200000000000000604482015260640162000682565b6001600160a01b038116600081815260016020908152604091829020805460ff1916905590519182527f0f279980343c7ca542fde9fa5396555068efb5cd560d9cf9c191aa2911079b47910162000a87565b62000f3b62001541565b62000f476000620016c7565b565b62000f5362001541565b6007546040517f36d2da900000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03909116906336d2da9090602401600060405180830381600087803b15801562000fb257600080fd5b505af115801562000fc7573d6000803e3d6000fd5b50505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015620010195750825b905060008267ffffffffffffffff166001148015620010375750303b155b90508115801562001046575080155b156200107e576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff191660011785558315620010b357845468ff00000000000000001916680100000000000000001785555b620010be3362001745565b6000600555604051620010d19062001b2f565b604051809103906000f080158015620010ee573d6000803e3d6000fd5b506008805473ffffffffffffffffffffffffffffffffffffffff199081166001600160a01b039390931692831790915560078054909116821790556040519081527fbd726cf82ac9c3260b1495107182e336e0654b25c10915648c0cc15b2bb72cbf9060200160405180910390a18315620011a557845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2906020016200072d565b5050505050565b604080516060808201835260008083526020808401839052838501829052858252600681528482208551938401909552845483526001850180549295869493909284019190620011fc9062002240565b80601f01602080910402602001604051908101604052809291908181526020018280546200122a9062002240565b80156200127b5780601f106200124f576101008083540402835291602001916200127b565b820191906000526020600020905b8154815290600101906020018083116200125d57829003601f168201915b50505091835250506002919091015460209091015280519094149492505050565b60028181548110620012ad57600080fd5b906000526020600020016000915090508054620012ca9062002240565b80601f0160208091040260200160405190810160405280929190818152602001828054620012f89062002240565b8015620013495780601f106200131d5761010080835404028352916020019162001349565b820191906000526020600020905b8154815290600101906020018083116200132b57829003601f168201915b505050505081565b6001600160a01b03851660009081526020819052604090205460ff1680620013e25760405162461bcd60e51b815260206004820152602360248201527f726573706f6e64696e67206174746573746572206973206e6f7420617474657360448201527f7465640000000000000000000000000000000000000000000000000000000000606482015260840162000682565b8115620014b95760006200141b87878660405160200162001406939291906200268f565b6040516020818303038152906040526200175a565b905060006200142b8287620015b8565b9050876001600160a01b0316816001600160a01b031614620014b65760405162461bcd60e51b815260206004820152602c60248201527f63616c63756c61746564206164647265737320616e642061747465737465724960448201527f4420646f6e74206d617463680000000000000000000000000000000000000000606482015260840162000682565b50505b5050506001600160a01b039091166000908152602081905260409020805460ff191660011790555050565b620014ee62001541565b6001600160a01b03811662001533576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526000600482015260240162000682565b6200153e81620016c7565b50565b33620015747f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03161462000f47576040517f118cdaa700000000000000000000000000000000000000000000000000000000815233600482015260240162000682565b600080600080620015ca868662001799565b925092509250620015dc8282620017ea565b50909150505b92915050565b803560009081526006602052604090208190620016068282620026d7565b5050600554604082013511156200153e5760400135600555565b606060006200162f8362001900565b600101905060008167ffffffffffffffff81111562001652576200165262001b3d565b6040519080825280601f01601f1916602001820160405280156200167d576020820181803683370190505b5090508181016020015b600019017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85049450846200168757509392505050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6200174f620019e9565b6200153e8162001a51565b600062001768825162001620565b826040516020016200177c929190620027e7565b604051602081830303815290604052805190602001209050919050565b60008060008351604103620017d75760208401516040850151606086015160001a620017c88882858562001a5b565b955095509550505050620017e3565b50508151600091506002905b9250925092565b600082600381111562001801576200180162002846565b036200180b575050565b600182600381111562001822576200182262002846565b036200185a576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600282600381111562001871576200187162002846565b03620018ad576040517ffce698f70000000000000000000000000000000000000000000000000000000081526004810182905260240162000682565b6003826003811115620018c457620018c462002846565b0362000486576040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004810182905260240162000682565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106200194a577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef8100000000831062001977576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106200199657662386f26fc10000830492506010015b6305f5e1008310620019af576305f5e100830492506008015b6127108310620019c457612710830492506004015b60648310620019d7576064830492506002015b600a8310620015e25760010192915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1662000f47576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620014ee620019e9565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111562001a98575060009150600390508262001b25565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801562001aed573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811662001b1b5750600092506001915082905062001b25565b9250600091508190505b9450945094915050565b6118ac806200285d83390190565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171562001b7f5762001b7f62001b3d565b604052919050565b600082601f83011262001b9957600080fd5b813567ffffffffffffffff81111562001bb65762001bb662001b3d565b62001bcb601f8201601f191660200162001b53565b81815284602083860101111562001be157600080fd5b816020850160208301376000918101602001919091529392505050565b80356001600160a01b038116811462001c1657600080fd5b919050565b6000806040838503121562001c2f57600080fd5b823567ffffffffffffffff81111562001c4757600080fd5b62001c558582860162001b87565b92505062001c666020840162001bfe565b90509250929050565b60008083601f84011262001c8257600080fd5b50813567ffffffffffffffff81111562001c9b57600080fd5b60208301915083602082850101111562001cb457600080fd5b9250929050565b6000806000806060858703121562001cd257600080fd5b843567ffffffffffffffff8082111562001ceb57600080fd5b908601906060828903121562001d0057600080fd5b9094506020860135908082111562001d1757600080fd5b62001d258883890162001c6f565b9095509350604087013591508082111562001d3f57600080fd5b5085016020818803121562001d5357600080fd5b939692955090935050565b60006020828403121562001d7157600080fd5b5035919050565b60006020828403121562001d8b57600080fd5b813567ffffffffffffffff81111562001da357600080fd5b62001db18482850162001b87565b949350505050565b60008060008060008060a0878903121562001dd357600080fd5b86359550602080880135955060408801359450606088013567ffffffffffffffff8082111562001e0257600080fd5b818a0191508a601f83011262001e1757600080fd5b81358181111562001e2c5762001e2c62001b3d565b8060051b62001e3d85820162001b53565b918252838101850191858101908e84111562001e5857600080fd5b86860192505b8383101562001e9757848335111562001e7657600080fd5b62001e878f88853589010162001b87565b8252918601919086019062001e5e565b985050505060808a013592508083111562001eb157600080fd5b505062001ec189828a0162001c6f565b979a9699509497509295939492505050565b60006020828403121562001ee657600080fd5b62001ef18262001bfe565b9392505050565b60008060008084860360c081121562001f1057600080fd5b608081121562001f1f57600080fd5b50849350608085013567ffffffffffffffff8082111562001f3f57600080fd5b818701915087601f83011262001f5457600080fd5b81358181111562001f6457600080fd5b8860208260051b850101111562001f7a57600080fd5b95986020929092019750949560a00135945092505050565b60008060008060006060868803121562001fab57600080fd5b62001fb68662001bfe565b9450602086013567ffffffffffffffff8082111562001fd457600080fd5b62001fe289838a0162001c6f565b9096509450604088013591508082111562001ffc57600080fd5b506200200b8882890162001c6f565b969995985093965092949392505050565b60005b83811015620020395781810151838201526020016200201f565b50506000910152565b600081518084526200205c8160208601602086016200201c565b601f01601f19169290920160200192915050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015620020c957603f19888603018452620020b685835162002042565b9450928501929085019060010162002097565b5092979650505050505050565b82151581526040602082015281516040820152600060208301516060808401526200210560a084018262002042565b905060408401516080840152809150509392505050565b60208152600062001ef1602083018462002042565b600080600080600060a086880312156200214a57600080fd5b620021558662001bfe565b9450620021656020870162001bfe565b9350604086013567ffffffffffffffff808211156200218357600080fd5b6200219189838a0162001b87565b94506060880135915080821115620021a857600080fd5b50620021b78882890162001b87565b92505060808601358015158114620021ce57600080fd5b809150509295509295909350565b60008060208385031215620021f057600080fd5b823567ffffffffffffffff8111156200220857600080fd5b620022168582860162001c6f565b90969095509350505050565b60008251620022368184602087016200201c565b9190910192915050565b600181811c908216806200225557607f821691505b6020821081036200227657634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620022ca57600081815260208120601f850160051c81016020861015620022a55750805b601f850160051c820191505b81811015620022c657828155600101620022b1565b5050505b505050565b815167ffffffffffffffff811115620022ec57620022ec62001b3d565b6200230481620022fd845462002240565b846200227c565b602080601f8311600181146200233c5760008415620023235750858301515b600019600386901b1c1916600185901b178555620022c6565b600085815260208120601f198616915b828110156200236d578886015182559484019460019091019084016200234c565b50858210156200238c5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b604081526000620023b1604083018562002042565b90506001600160a01b03831660208301529392505050565b6000808335601e19843603018112620023e157600080fd5b83018035915067ffffffffffffffff821115620023fd57600080fd5b60200191503681900382131562001cb457600080fd5b634e487b7160e01b600052601160045260246000fd5b80820180821115620015e257620015e262002413565b7f496e76616c696420626c6f636b2062696e64696e673a00000000000000000000815260008451620024798160168501602089016200201c565b80830190507f3a000000000000000000000000000000000000000000000000000000000000008060168301528551620024ba816017850160208a016200201c565b60179201918201528351620024d78160188401602088016200201c565b0160180195945050505050565b600060808201868352602086818501528560408501526080606085015281855180845260a08601915060a08160051b870101935082870160005b828110156200255057609f198887030184526200253d86835162002042565b955092840192908401906001016200251e565b50939a9950505050505050505050565b634e487b7160e01b600052603260045260246000fd5b80516020808301519190811015620022765760001960209190910360031b1b16919050565b600060018201620025b057620025b062002413565b5060010190565b6001600160a01b0380620025cb8362001bfe565b16835280620025dd6020840162001bfe565b1660208401525060408101356040830152606081013567ffffffffffffffff81168082146200260b57600080fd5b80606085015250505050565b620026238186620025b7565b60c060808201528260c082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8411156200266057600080fd5b8360051b808660e085013760a0830193909352500160e0019392505050565b60808101620015e28284620025b7565b60006bffffffffffffffffffffffff19808660601b168352808560601b166014840152508251620026c88160288501602087016200201c565b91909101602801949350505050565b813581556001808201602080850135601e19863603018112620026f957600080fd5b8501803567ffffffffffffffff8111156200271357600080fd5b80360383830113156200272557600080fd5b6200273d8162002736865462002240565b866200227c565b6000601f8211600181146200277657600083156200275d57508382018501355b600019600385901b1c1916600184901b178655620027d2565b600086815260209020601f19841690835b82811015620027a85786850188013582559387019390890190870162002787565b5084821015620027c85760001960f88660031b161c198785880101351681555b50508683881b0186555b50505050505050604082013560028201555050565b7f19457468657265756d205369676e6564204d6573736167653a0a0000000000008152600083516200282181601a8501602088016200201c565b8351908301906200283a81601a8401602088016200201c565b01601a01949350505050565b634e487b7160e01b600052602160045260246000fdfe608060405234801561001057600080fd5b50338061003757604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61004081610046565b50610096565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611807806100a56000396000f3fe6080604052600436106100e15760003560e01c80639730886d1161007f578063b201246f11610059578063b201246f1461030e578063b6aed0cb1461032e578063e138a8d21461034e578063f2fde38b1461036e57610155565b80639730886d1461029557806399a3ad21146102b5578063b1454caa146102d557610155565b8063346633fb116100bb578063346633fb1461022557806336d2da9014610238578063715018a6146102585780638da5cb5b1461026d57610155565b80630fcfbd11146101a25780630fe9188e146101d557806333a88c72146101f557610155565b36610155576040517f346633fb0000000000000000000000000000000000000000000000000000000081523360048201523460248201819052309163346633fb91906044016000604051808303818588803b15801561013f57600080fd5b505af1158015610153573d6000803e3d6000fd5b005b60405162461bcd60e51b815260206004820152600b60248201527f756e737570706f7274656400000000000000000000000000000000000000000060448201526064015b60405180910390fd5b3480156101ae57600080fd5b506101c26101bd366004610f80565b61038e565b6040519081526020015b60405180910390f35b3480156101e157600080fd5b506101536101f0366004610fb5565b610428565b34801561020157600080fd5b50610215610210366004610f80565b61049e565b60405190151581526020016101cc565b610153610233366004610fe3565b6104f1565b34801561024457600080fd5b5061015361025336600461100f565b6105d4565b34801561026457600080fd5b50610153610683565b34801561027957600080fd5b506000546040516001600160a01b0390911681526020016101cc565b3480156102a157600080fd5b506101536102b036600461102c565b610697565b3480156102c157600080fd5b506101536102d0366004610fe3565b6107e9565b3480156102e157600080fd5b506102f56102f03660046110a2565b610899565b60405167ffffffffffffffff90911681526020016101cc565b34801561031a57600080fd5b5061015361032936600461119b565b6108fa565b34801561033a57600080fd5b506101536103493660046111fd565b610afc565b34801561035a57600080fd5b5061015361036936600461121f565b610b98565b34801561037a57600080fd5b5061015361038936600461100f565b610d78565b600080826040516020016103a291906112ce565b60408051601f19818403018152918152815160209283012060008181526001909352912054909150806104215760405162461bcd60e51b815260206004820152602160248201527f54686973206d65737361676520776173206e65766572207375626d69747465646044820152601760f91b6064820152608401610199565b9392505050565b610430610dcf565b600081815260046020526040812054900361048d5760405162461bcd60e51b815260206004820152601a60248201527f537461746520726f6f7420646f6573206e6f742065786973742e0000000000006044820152606401610199565b600090815260046020526040812055565b600080826040516020016104b291906112ce565b60408051601f1981840301815291815281516020928301206000818152600190935291205490915080158015906104e95750428111155b949350505050565b60003411801561050057508034145b6105725760405162461bcd60e51b815260206004820152603060248201527f417474656d7074696e6720746f2073656e642076616c756520776974686f757460448201527f2070726f766964696e67204574686572000000000000000000000000000000006064820152608401610199565b600061057d33610e15565b6040805134815267ffffffffffffffff831660208201529192506001600160a01b0385169133917f50c536ac33a920f00755865b831d17bf4cff0b2e0345f65b16d52bfc004068b6910160405180910390a3505050565b6105dc610dcf565b6000816001600160a01b03164760405160006040518083038185875af1925050503d8060008114610629576040519150601f19603f3d011682016040523d82523d6000602084013e61062e565b606091505b505090508061067f5760405162461bcd60e51b815260206004820152601460248201527f6661696c65642073656e64696e672076616c75650000000000000000000000006044820152606401610199565b5050565b61068b610dcf565b6106956000610e73565b565b61069f610dcf565b60006106ab82426113cf565b90506000836040516020016106c091906112ce565b60408051601f198184030181529181528151602092830120600081815260019093529120549091501561075b5760405162461bcd60e51b815260206004820152602160248201527f4d657373616765207375626d6974746564206d6f7265207468616e206f6e636560448201527f21000000000000000000000000000000000000000000000000000000000000006064820152608401610199565b600081815260016020908152604082208490556002919061077e9087018761100f565b6001600160a01b0316815260208101919091526040016000908120906107aa60808701606088016113e2565b63ffffffff168152602080820192909252604001600090812080546001810182559082529190208591600402016107e182826115b0565b505050505050565b6107f1610dcf565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461083e576040519150601f19603f3d011682016040523d82523d6000602084013e610843565b606091505b50509050806108945760405162461bcd60e51b815260206004820152601460248201527f6661696c65642073656e64696e672076616c75650000000000000000000000006044820152606401610199565b505050565b60006108a433610e15565b9050336001600160a01b03167fb93c37389233beb85a3a726c3f15c2d15533ee74cb602f20f490dfffef7759378288888888886040516108e9969594939291906116ca565b60405180910390a295945050505050565b600081815260046020526040812054900361096a5760405162461bcd60e51b815260206004820152602a60248201527f526f6f74206973206e6f74207075626c6973686564206f6e2074686973206d6560448201526939b9b0b3b290313ab99760b11b6064820152608401610199565b6000818152600460205260409020544210156109d25760405162461bcd60e51b815260206004820152602160248201527f526f6f74206973206e6f7420636f6e736964657265642066696e616c207965746044820152601760f91b6064820152608401610199565b6000846040516020016109e5919061171a565b60408051601f198184030181528282528051602091820120908301829052600160608401527f760000000000000000000000000000000000000000000000000000000000000060808401529082015260a001604051602081830303815290604052805190602001209050610a8384848484604051602001610a6891815260200190565b60405160208183030381529060405280519060200120610ed0565b610af55760405162461bcd60e51b815260206004820152603360248201527f496e76616c696420696e636c7573696f6e2070726f6f6620666f722076616c7560448201527f65207472616e73666572206d6573736167652e000000000000000000000000006064820152608401610199565b5050505050565b610b04610dcf565b60008281526004602052604090205415610b865760405162461bcd60e51b815260206004820152602560248201527f526f6f7420616c726561647920616464656420746f20746865206d657373616760448201527f65206275730000000000000000000000000000000000000000000000000000006064820152608401610199565b60009182526004602052604090912055565b6000818152600460205260408120549003610c085760405162461bcd60e51b815260206004820152602a60248201527f526f6f74206973206e6f74207075626c6973686564206f6e2074686973206d6560448201526939b9b0b3b290313ab99760b11b6064820152608401610199565b600081815260046020526040902054421015610c705760405162461bcd60e51b815260206004820152602160248201527f526f6f74206973206e6f7420636f6e736964657265642066696e616c207965746044820152601760f91b6064820152608401610199565b600084604051602001610c8391906112ce565b60408051601f198184030181528282528051602091820120908301829052600160608401527f6d0000000000000000000000000000000000000000000000000000000000000060808401529082015260a001604051602081830303815290604052805190602001209050610d0684848484604051602001610a6891815260200190565b610af55760405162461bcd60e51b815260206004820152603060248201527f496e76616c696420696e636c7573696f6e2070726f6f6620666f722063726f7360448201527f7320636861696e206d6573736167652e000000000000000000000000000000006064820152608401610199565b610d80610dcf565b6001600160a01b038116610dc3576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610199565b610dcc81610e73565b50565b6000546001600160a01b03163314610695576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610199565b6001600160a01b0381166000908152600360205260408120805467ffffffffffffffff169160019190610e48838561177a565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550919050565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600082610ede868685610ee8565b1495945050505050565b600081815b84811015610f2b57610f1782878784818110610f0b57610f0b6117a2565b90506020020135610f34565b915080610f23816117b8565b915050610eed565b50949350505050565b6000818310610f50576000828152602084905260409020610f5f565b60008381526020839052604090205b90505b92915050565b600060c08284031215610f7a57600080fd5b50919050565b600060208284031215610f9257600080fd5b813567ffffffffffffffff811115610fa957600080fd5b6104e984828501610f68565b600060208284031215610fc757600080fd5b5035919050565b6001600160a01b0381168114610dcc57600080fd5b60008060408385031215610ff657600080fd5b823561100181610fce565b946020939093013593505050565b60006020828403121561102157600080fd5b813561042181610fce565b6000806040838503121561103f57600080fd5b823567ffffffffffffffff81111561105657600080fd5b61106285828601610f68565b95602094909401359450505050565b63ffffffff81168114610dcc57600080fd5b60ff81168114610dcc57600080fd5b803561109d81611083565b919050565b6000806000806000608086880312156110ba57600080fd5b85356110c581611071565b945060208601356110d581611071565b9350604086013567ffffffffffffffff808211156110f257600080fd5b818801915088601f83011261110657600080fd5b81358181111561111557600080fd5b89602082850101111561112757600080fd5b602083019550809450505050606086013561114181611083565b809150509295509295909350565b60008083601f84011261116157600080fd5b50813567ffffffffffffffff81111561117957600080fd5b6020830191508360208260051b850101111561119457600080fd5b9250929050565b60008060008084860360c08112156111b257600080fd5b60808112156111c057600080fd5b50849350608085013567ffffffffffffffff8111156111de57600080fd5b6111ea8782880161114f565b9598909750949560a00135949350505050565b6000806040838503121561121057600080fd5b50508035926020909101359150565b6000806000806060858703121561123557600080fd5b843567ffffffffffffffff8082111561124d57600080fd5b61125988838901610f68565b9550602087013591508082111561126f57600080fd5b5061127c8782880161114f565b9598909750949560400135949350505050565b67ffffffffffffffff81168114610dcc57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152600082356112df81610fce565b6001600160a01b03811660208401525060208301356112fd8161128f565b67ffffffffffffffff80821660408501526040850135915061131e82611071565b63ffffffff80831660608601526060860135925061133b83611071565b80831660808601525060808501359150601e1985360301821261135d57600080fd5b602091850191820191358181111561137457600080fd5b80360383131561138357600080fd5b60c060a086015261139860e0860182856112a5565b925050506113a860a08501611092565b60ff811660c0850152509392505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610f6257610f626113b9565b6000602082840312156113f457600080fd5b813561042181611071565b60008135610f6281611071565b6000808335601e1984360301811261142357600080fd5b83018035915067ffffffffffffffff82111561143e57600080fd5b60200191503681900382131561119457600080fd5b634e487b7160e01b600052604160045260246000fd5b600181811c9082168061147d57607f821691505b602082108103610f7a57634e487b7160e01b600052602260045260246000fd5b601f82111561089457600081815260208120601f850160051c810160208610156114c45750805b601f850160051c820191505b818110156107e1578281556001016114d0565b67ffffffffffffffff8311156114fb576114fb611453565b61150f836115098354611469565b8361149d565b6000601f841160018114611543576000851561152b5750838201355b600019600387901b1c1916600186901b178355610af5565b600083815260209020601f19861690835b828110156115745786850135825560209485019460019092019101611554565b50868210156115915760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60008135610f6281611083565b81356115bb81610fce565b6001600160a01b038116905081548173ffffffffffffffffffffffffffffffffffffffff19821617835560208401356115f38161128f565b7bffffffffffffffff00000000000000000000000000000000000000008160a01b1690507fffffffff000000000000000000000000000000000000000000000000000000008184828516171785556040860135925061165183611071565b921760e09190911b90911617815561168961166e606084016113ff565b6001830163ffffffff821663ffffffff198254161781555050565b611696608083018361140c565b6116a48183600286016114e3565b505061067f6116b560a084016115a3565b6003830160ff821660ff198254161781555050565b67ffffffffffffffff87168152600063ffffffff808816602084015280871660408401525060a0606083015261170460a0830185876112a5565b905060ff83166080830152979650505050505050565b60808101823561172981610fce565b6001600160a01b03908116835260208401359061174582610fce565b1660208301526040838101359083015260608301356117638161128f565b67ffffffffffffffff811660608401525092915050565b67ffffffffffffffff81811683821601908082111561179b5761179b6113b9565b5092915050565b634e487b7160e01b600052603260045260246000fd5b6000600182016117ca576117ca6113b9565b506001019056fea2646970667358221220a449a197632e1117b118ced8f7cf97a1ae44b160775ee146e59b50cbc1b8dcaa64736f6c63430008140033a264697066735822122004ad9e0c30b943964e74350866e1fd532c6f29760dc01100bb23ad394323ba7064736f6c63430008140033", + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"ECDSAInvalidSignatureLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"ECDSAInvalidSignatureS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAddress\",\"type\":\"address\"}],\"name\":\"ImportantContractAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"messageBusAddress\",\"type\":\"address\"}],\"name\":\"LogManagementContractCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"rollupHash\",\"type\":\"bytes32\"}],\"name\":\"RollupAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"enclaveID\",\"type\":\"address\"}],\"name\":\"SequencerEnclaveGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"enclaveID\",\"type\":\"address\"}],\"name\":\"SequencerEnclaveRevoked\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"Hash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"Signature\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"LastSequenceNumber\",\"type\":\"uint256\"}],\"internalType\":\"structStructs.MetaRollup\",\"name\":\"r\",\"type\":\"tuple\"},{\"internalType\":\"string\",\"name\":\"_rollupData\",\"type\":\"string\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"topic\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"consistencyLevel\",\"type\":\"uint8\"}],\"internalType\":\"structStructs.CrossChainMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"}],\"internalType\":\"structStructs.HeaderCrossChainData\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"AddRollup\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"Attested\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"}],\"internalType\":\"structStructs.ValueTransferMessage\",\"name\":\"_msg\",\"type\":\"tuple\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"ExtractNativeValue\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GetImportantContractKeys\",\"outputs\":[{\"internalType\":\"string[]\",\"name\":\"\",\"type\":\"string[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"rollupHash\",\"type\":\"bytes32\"}],\"name\":\"GetRollupByHash\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"Hash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"Signature\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"LastSequenceNumber\",\"type\":\"uint256\"}],\"internalType\":\"structStructs.MetaRollup\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"GetRollupByNumber\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"Hash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"Signature\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"LastSequenceNumber\",\"type\":\"uint256\"}],\"internalType\":\"structStructs.MetaRollup\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"GetUniqueForkID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"Hash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"Signature\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"LastSequenceNumber\",\"type\":\"uint256\"}],\"internalType\":\"structStructs.MetaRollup\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"GrantSequencerEnclave\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_enclaveID\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_initSecret\",\"type\":\"bytes\"},{\"internalType\":\"string\",\"name\":\"_genesisAttestation\",\"type\":\"string\"}],\"name\":\"InitializeNetworkSecret\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"IsSequencerEnclave\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"IsWithdrawalAvailable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"requestReport\",\"type\":\"string\"}],\"name\":\"RequestNetworkSecret\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"attesterID\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"requesterID\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"attesterSig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"responseSecret\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"verifyAttester\",\"type\":\"bool\"}],\"name\":\"RespondNetworkSecret\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RetrieveAllBridgeFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"RevokeSequencerEnclave\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"newAddress\",\"type\":\"address\"}],\"name\":\"SetImportantContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_lastBatchHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"blockNum\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"crossChainHashes\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"rollupNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"forkID\",\"type\":\"bytes32\"}],\"name\":\"addCrossChainMessagesRoot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"importantContractAddresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"importantContractKeys\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"isWithdrawalSpent\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBatchHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBatchSeqNo\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleMessageBus\",\"outputs\":[{\"internalType\":\"contractIMerkleTreeMessageBus\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messageBus\",\"outputs\":[{\"internalType\":\"contractIMessageBus\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5061001a3361001f565b610090565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6143a180620000a06000396000f3fe60806040523480156200001157600080fd5b5060043610620001e85760003560e01c8063715018a6116200010d578063a1a227fa11620000a3578063db5d91b1116200007a578063db5d91b1146200049c578063e34fbfc814620004cb578063e874eb2014620004e0578063f2fde38b14620004f457600080fd5b8063a1a227fa1462000460578063a52f433c1462000474578063d4fab887146200048557600080fd5b80638236a7ba11620000e45780638236a7ba14620003cb57806387059edb14620003f25780638da5cb5b146200040957806398077e86146200043a57600080fd5b8063715018a614620003ad5780637281099614620003b75780638129fc1c14620003c157600080fd5b8063440c953b1162000183578063568699c8116200015a578063568699c8146200033f57806368e1038314620003665780636a30d26c146200037d5780636b9707d6146200039657600080fd5b8063440c953b14620003075780634766573814620003115780635371a216146200032857600080fd5b80632c77c81f11620001c45780632c77c81f146200023a5780632f0cb9e314620002515780633e60a22f146200028857806343348b2f14620002d857600080fd5b80620ddd2714620001ed57806303e72e48146200020a578063073b6ef31462000223575b600080fd5b620001f7600d5481565b6040519081526020015b60405180910390f35b620002216200021b36600462001e27565b6200050b565b005b620002216200023436600462001ec7565b6200061e565b620002216200024b36600462001ffb565b62000909565b62000277620002623660046200209e565b600c6020526000908152604090205460ff1681565b604051901515815260200162000201565b620002bf62000299366004620020b8565b80516020818301810180516003825292820191909301209152546001600160a01b031681565b6040516001600160a01b03909116815260200162000201565b62000277620002e9366004620020f9565b6001600160a01b031660009081526020819052604090205460ff1690565b620001f760055481565b6200022162000322366004620020f9565b62000a79565b62000221620003393660046200211e565b62000b49565b62000356620003503660046200209e565b62000d52565b6040516200020192919062002241565b62000221620003773660046200225c565b62000dab565b6200038762000e98565b604051620002019190620022e6565b62000221620003a7366004620020f9565b62000f7b565b6200022162001041565b6200022162001059565b62000221620010dd565b620003e2620003dc3660046200209e565b620012c1565b604051620002019291906200234c565b620003e2620004033660046200209e565b620013b1565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b0316620002bf565b620004516200044b3660046200209e565b6200142b565b60405162000201919062002369565b600a54620002bf906001600160a01b031681565b600454610100900460ff1662000277565b62000221620004963660046200237e565b620014e0565b62000277620004ad366004620020f9565b6001600160a01b031660009081526001602052604090205460ff1690565b62000221620004dc36600462002429565b5050565b600b54620002bf906001600160a01b031681565b6200022162000505366004620020f9565b62001673565b62000515620016d0565b60006001600160a01b03166003836040516200053291906200246f565b908152604051908190036020019020546001600160a01b0316036200059157600280546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace016200058f83826200251c565b505b80600383604051620005a491906200246f565b90815260405190819003602001812080546001600160a01b039390931673ffffffffffffffffffffffffffffffffffffffff19909316929092179091557f17b2f9f5748931099ffee882b5b64f4a560b5c55da9b4f4e396dae3bb9f98cb590620006129084908490620025e9565b60405180910390a15050565b6200062b8660ff6200262c565b431115620006805760405162461bcd60e51b815260206004820152601560248201527f426c6f636b2062696e64696e6720746f6f206f6c64000000000000000000000060448201526064015b60405180910390fd5b86864014620006e757620006944362001747565b6200069f8862001747565b620006ab884062001747565b604051602001620006bf9392919062002642565b60408051601f198184030181529082905262461bcd60e51b8252620006779160040162002369565b6000828152600860205260409020548114620007465760405162461bcd60e51b815260206004820152600e60248201527f496e76616c696420666f726b4944000000000000000000000000000000000000604482015260640162000677565b6000620007b889898989604051602001620007659493929190620026e7565b6040516020818303038152906040528051906020012086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620017ee92505050565b6001600160a01b03811660009081526020819052604090205490915060ff16620008255760405162461bcd60e51b815260206004820152601660248201527f656e636c6176654944206e6f7420617474657374656400000000000000000000604482015260640162000677565b600d89905560005b8651811015620008fd57600b5487516001600160a01b039091169063b6aed0cb9089908490811062000863576200086362002763565b6020026020010151620008769062002779565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526004810191909152426024820152604401600060405180830381600087803b158015620008ce57600080fd5b505af1158015620008e3573d6000803e3d6000fd5b505050508080620008f4906200279e565b9150506200082d565b50505050505050505050565b60006200095b8535620009206020880188620027ba565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620017ee92505050565b6001600160a01b03811660009081526020819052604090205490915060ff16620009c85760405162461bcd60e51b815260206004820152601660248201527f656e636c6176654944206e6f7420617474657374656400000000000000000000604482015260640162000677565b6001600160a01b03811660009081526001602052604090205460ff1662000a325760405162461bcd60e51b815260206004820152601960248201527f656e636c6176654944206e6f7420612073657175656e63657200000000000000604482015260640162000677565b62000a3d856200181e565b604051853581527fd6555bff8670bd3008dc064c30bb56d6ac7cb14ae801e36146fe4e7c6a504a58906020015b60405180910390a15050505050565b62000a83620016d0565b6001600160a01b03811660009081526020819052604090205460ff1662000aed5760405162461bcd60e51b815260206004820152601660248201527f656e636c6176654944206e6f7420617474657374656400000000000000000000604482015260640162000677565b6001600160a01b038116600081815260016020818152604092839020805460ff191690921790915590519182527ffe64c7181f0fc60e300dc02cca368cdfa94d7ca45902de3b9a9d80070e76093691015b60405180910390a150565b600b546040517fb201246f0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063b201246f9062000b9a90879087908790879060040162002864565b60006040518083038186803b15801562000bb357600080fd5b505afa15801562000bc8573d6000803e3d6000fd5b5050505060008460405160200162000be19190620028cc565b60408051601f1981840301815291815281516020928301206000818152600c90935291205490915060ff161562000c5b5760405162461bcd60e51b815260206004820152601860248201527f7769746864726177616c20616c7265616479207370656e740000000000000000604482015260640162000677565b6001600c60008760405160200162000c749190620028cc565b60408051808303601f190181529181528151602092830120835282820193909352908201600020805460ff191693151593909317909255600a546001600160a01b0316916399a3ad219162000ccf91908901908901620020f9565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b0390921660048301528801356024820152604401600060405180830381600087803b15801562000d3257600080fd5b505af115801562000d47573d6000803e3d6000fd5b505050505050505050565b60408051606080820183526000808352602083019190915291810182905260008062000d7e85620013b1565b915091508162000d945760009590945092505050565b600094855260086020526040909420549492505050565b60045460ff161562000e265760405162461bcd60e51b815260206004820152602260248201527f6e6574776f726b2073656372657420616c726561647920696e697469616c697a60448201527f6564000000000000000000000000000000000000000000000000000000000000606482015260840162000677565b60048054600160ff1991821681179092556001600160a01b038716600081815260208181526040808320805486168717905585825291829020805490941690941790925590519081527ffe64c7181f0fc60e300dc02cca368cdfa94d7ca45902de3b9a9d80070e760936910162000a6a565b60606002805480602002602001604051908101604052809291908181526020016000905b8282101562000f7257838290600052602060002001805462000ede906200248d565b80601f016020809104026020016040519081016040528092919081815260200182805462000f0c906200248d565b801562000f5d5780601f1062000f315761010080835404028352916020019162000f5d565b820191906000526020600020905b81548152906001019060200180831162000f3f57829003601f168201915b50505050508152602001906001019062000ebc565b50505050905090565b62000f85620016d0565b6001600160a01b03811660009081526001602052604090205460ff1662000fef5760405162461bcd60e51b815260206004820152601960248201527f656e636c6176654944206e6f7420612073657175656e63657200000000000000604482015260640162000677565b6001600160a01b038116600081815260016020908152604091829020805460ff1916905590519182527f0f279980343c7ca542fde9fa5396555068efb5cd560d9cf9c191aa2911079b47910162000b3e565b6200104b620016d0565b620010576000620018d3565b565b62001063620016d0565b600a546040517f36d2da900000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03909116906336d2da9090602401600060405180830381600087803b158015620010c257600080fd5b505af1158015620010d7573d6000803e3d6000fd5b50505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015620011295750825b905060008267ffffffffffffffff166001148015620011475750303b155b90508115801562001156575080155b156200118e576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff191660011785558315620011c357845468ff00000000000000001916680100000000000000001785555b620011ce3362001951565b60006005819055600955604051620011e69062001d3b565b604051809103906000f08015801562001203573d6000803e3d6000fd5b50600b805473ffffffffffffffffffffffffffffffffffffffff199081166001600160a01b0393909316928317909155600a8054909116821790556040519081527fbd726cf82ac9c3260b1495107182e336e0654b25c10915648c0cc15b2bb72cbf9060200160405180910390a18315620012ba57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200162000a6a565b5050505050565b60408051606080820183526000808352602080840183905283850182905285825260068152848220855193840190955284548352600185018054929586949390928401919062001311906200248d565b80601f01602080910402602001604051908101604052809291908181526020018280546200133f906200248d565b8015620013905780601f10620013645761010080835404028352916020019162001390565b820191906000526020600020905b8154815290600101906020018083116200137257829003601f168201915b50505091835250506002919091015460209091015280519094149492505050565b604080516060808201835260008083526020830191909152918101829052600083815260076020526040812054908190036200141657505060408051606081018252600080825282516020818101855282825283015291810182905290939092509050565b6200142181620012c1565b9250925050915091565b600281815481106200143c57600080fd5b90600052602060002001600091509050805462001459906200248d565b80601f016020809104026020016040519081016040528092919081815260200182805462001487906200248d565b8015620014d85780601f10620014ac57610100808354040283529160200191620014d8565b820191906000526020600020905b815481529060010190602001808311620014ba57829003601f168201915b505050505081565b6001600160a01b03851660009081526020819052604090205460ff1680620015715760405162461bcd60e51b815260206004820152602360248201527f726573706f6e64696e67206174746573746572206973206e6f7420617474657360448201527f7465640000000000000000000000000000000000000000000000000000000000606482015260840162000677565b811562001648576000620015aa8787866040516020016200159593929190620028dc565b60405160208183030381529060405262001966565b90506000620015ba8287620017ee565b9050876001600160a01b0316816001600160a01b031614620016455760405162461bcd60e51b815260206004820152602c60248201527f63616c63756c61746564206164647265737320616e642061747465737465724960448201527f4420646f6e74206d617463680000000000000000000000000000000000000000606482015260840162000677565b50505b5050506001600160a01b039091166000908152602081905260409020805460ff191660011790555050565b6200167d620016d0565b6001600160a01b038116620016c2576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526000600482015260240162000677565b620016cd81620018d3565b50565b33620017037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03161462001057576040517f118cdaa700000000000000000000000000000000000000000000000000000000815233600482015260240162000677565b606060006200175683620019a5565b600101905060008167ffffffffffffffff81111562001779576200177962001d49565b6040519080825280601f01601f191660200182016040528015620017a4576020820181803683370190505b5090508181016020015b600019017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8504945084620017ae57509392505050565b60008060008062001800868662001a8e565b92509250925062001812828262001adf565b50909150505b92915050565b8035600090815260066020526040902081906200183c828262002924565b505060095460009081526007602052604090208135908190556200186260014362002a34565b406040516020016200187e929190918252602082015260400190565b60408051601f198184030181529181528151602092830120600980546000908152600890945291832055805491620018b6836200279e565b919050555060055481604001351115620016cd5760400135600555565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6200195b62001bf5565b620016cd8162001c5d565b600062001974825162001747565b826040516020016200198892919062002a4a565b604051602081830303815290604052805190602001209050919050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310620019ef577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef8100000000831062001a1c576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831062001a3b57662386f26fc10000830492506010015b6305f5e100831062001a54576305f5e100830492506008015b612710831062001a6957612710830492506004015b6064831062001a7c576064830492506002015b600a8310620018185760010192915050565b6000806000835160410362001acc5760208401516040850151606086015160001a62001abd8882858562001c67565b95509550955050505062001ad8565b50508151600091506002905b9250925092565b600082600381111562001af65762001af662002aa9565b0362001b00575050565b600182600381111562001b175762001b1762002aa9565b0362001b4f576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600282600381111562001b665762001b6662002aa9565b0362001ba2576040517ffce698f70000000000000000000000000000000000000000000000000000000081526004810182905260240162000677565b600382600381111562001bb95762001bb962002aa9565b03620004dc576040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004810182905260240162000677565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1662001057576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200167d62001bf5565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111562001ca4575060009150600390508262001d31565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801562001cf9573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811662001d275750600092506001915082905062001d31565b9250600091508190505b9450945094915050565b6118ac8062002ac083390190565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171562001d8b5762001d8b62001d49565b604052919050565b600082601f83011262001da557600080fd5b813567ffffffffffffffff81111562001dc25762001dc262001d49565b62001dd7601f8201601f191660200162001d5f565b81815284602083860101111562001ded57600080fd5b816020850160208301376000918101602001919091529392505050565b80356001600160a01b038116811462001e2257600080fd5b919050565b6000806040838503121562001e3b57600080fd5b823567ffffffffffffffff81111562001e5357600080fd5b62001e618582860162001d93565b92505062001e726020840162001e0a565b90509250929050565b60008083601f84011262001e8e57600080fd5b50813567ffffffffffffffff81111562001ea757600080fd5b60208301915083602082850101111562001ec057600080fd5b9250929050565b60008060008060008060008060e0898b03121562001ee457600080fd5b88359750602089013596506040890135955067ffffffffffffffff8060608b0135111562001f1157600080fd5b60608a01358a018b601f82011262001f2857600080fd5b818135111562001f3c5762001f3c62001d49565b62001f4e6020823560051b0162001d5f565b81358082526020808301929160051b8401018e101562001f6d57600080fd5b602083015b6020843560051b85010181101562001fb457848135111562001f9357600080fd5b62001fa58f6020833587010162001d93565b83526020928301920162001f72565b509750505060808a013581101562001fcb57600080fd5b5062001fde8a60808b01358b0162001e7b565b989b979a5095989497959660a08601359560c00135945092505050565b600080600080606085870312156200201257600080fd5b843567ffffffffffffffff808211156200202b57600080fd5b90860190606082890312156200204057600080fd5b909450602086013590808211156200205757600080fd5b620020658883890162001e7b565b909550935060408701359150808211156200207f57600080fd5b508501602081880312156200209357600080fd5b939692955090935050565b600060208284031215620020b157600080fd5b5035919050565b600060208284031215620020cb57600080fd5b813567ffffffffffffffff811115620020e357600080fd5b620020f18482850162001d93565b949350505050565b6000602082840312156200210c57600080fd5b620021178262001e0a565b9392505050565b60008060008084860360c08112156200213657600080fd5b60808112156200214557600080fd5b50849350608085013567ffffffffffffffff808211156200216557600080fd5b818701915087601f8301126200217a57600080fd5b8135818111156200218a57600080fd5b8860208260051b8501011115620021a057600080fd5b95986020929092019750949560a00135945092505050565b60005b83811015620021d5578181015183820152602001620021bb565b50506000910152565b60008151808452620021f8816020860160208601620021b8565b601f01601f19169290920160200192915050565b8051825260006020820151606060208501526200222d6060850182620021de565b604093840151949093019390935250919050565b828152604060208201526000620020f160408301846200220c565b6000806000806000606086880312156200227557600080fd5b620022808662001e0a565b9450602086013567ffffffffffffffff808211156200229e57600080fd5b620022ac89838a0162001e7b565b90965094506040880135915080821115620022c657600080fd5b50620022d58882890162001e7b565b969995985093965092949392505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156200233f57603f198886030184526200232c858351620021de565b945092850192908501906001016200230d565b5092979650505050505050565b8215158152604060208201526000620020f160408301846200220c565b602081526000620021176020830184620021de565b600080600080600060a086880312156200239757600080fd5b620023a28662001e0a565b9450620023b26020870162001e0a565b9350604086013567ffffffffffffffff80821115620023d057600080fd5b620023de89838a0162001d93565b94506060880135915080821115620023f557600080fd5b50620024048882890162001d93565b925050608086013580151581146200241b57600080fd5b809150509295509295909350565b600080602083850312156200243d57600080fd5b823567ffffffffffffffff8111156200245557600080fd5b620024638582860162001e7b565b90969095509350505050565b6000825162002483818460208701620021b8565b9190910192915050565b600181811c90821680620024a257607f821691505b602082108103620024c357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200251757600081815260208120601f850160051c81016020861015620024f25750805b601f850160051c820191505b818110156200251357828155600101620024fe565b5050505b505050565b815167ffffffffffffffff81111562002539576200253962001d49565b62002551816200254a84546200248d565b84620024c9565b602080601f831160018114620025895760008415620025705750858301515b600019600386901b1c1916600185901b17855562002513565b600085815260208120601f198616915b82811015620025ba5788860151825594840194600190910190840162002599565b5085821015620025d95787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b604081526000620025fe6040830185620021de565b90506001600160a01b03831660208301529392505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111562001818576200181862002616565b7f496e76616c696420626c6f636b2062696e64696e673a000000000000000000008152600084516200267c816016850160208901620021b8565b80830190507f3a000000000000000000000000000000000000000000000000000000000000008060168301528551620026bd816017850160208a01620021b8565b60179201918201528351620026da816018840160208801620021b8565b0160180195945050505050565b600060808201868352602086818501528560408501526080606085015281855180845260a08601915060a08160051b870101935082870160005b828110156200275357609f1988870301845262002740868351620021de565b9550928401929084019060010162002721565b50939a9950505050505050505050565b634e487b7160e01b600052603260045260246000fd5b80516020808301519190811015620024c35760001960209190910360031b1b16919050565b600060018201620027b357620027b362002616565b5060010190565b6000808335601e19843603018112620027d257600080fd5b83018035915067ffffffffffffffff821115620027ee57600080fd5b60200191503681900382131562001ec057600080fd5b6001600160a01b0380620028188362001e0a565b168352806200282a6020840162001e0a565b1660208401525060408101356040830152606081013567ffffffffffffffff81168082146200285857600080fd5b80606085015250505050565b62002870818662002804565b60c060808201528260c082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841115620028ad57600080fd5b8360051b808660e085013760a0830193909352500160e0019392505050565b6080810162001818828462002804565b60006bffffffffffffffffffffffff19808660601b168352808560601b16601484015250825162002915816028850160208701620021b8565b91909101602801949350505050565b813581556001808201602080850135601e198636030181126200294657600080fd5b8501803567ffffffffffffffff8111156200296057600080fd5b80360383830113156200297257600080fd5b6200298a816200298386546200248d565b86620024c9565b6000601f821160018114620029c35760008315620029aa57508382018501355b600019600385901b1c1916600184901b17865562002a1f565b600086815260209020601f19841690835b82811015620029f557868501880135825593870193908901908701620029d4565b508482101562002a155760001960f88660031b161c198785880101351681555b50508683881b0186555b50505050505050604082013560028201555050565b8181038181111562001818576200181862002616565b7f19457468657265756d205369676e6564204d6573736167653a0a00000000000081526000835162002a8481601a850160208801620021b8565b83519083019062002a9d81601a840160208801620021b8565b01601a01949350505050565b634e487b7160e01b600052602160045260246000fdfe608060405234801561001057600080fd5b50338061003757604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61004081610046565b50610096565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611807806100a56000396000f3fe6080604052600436106100e15760003560e01c80639730886d1161007f578063b201246f11610059578063b201246f1461030e578063b6aed0cb1461032e578063e138a8d21461034e578063f2fde38b1461036e57610155565b80639730886d1461029557806399a3ad21146102b5578063b1454caa146102d557610155565b8063346633fb116100bb578063346633fb1461022557806336d2da9014610238578063715018a6146102585780638da5cb5b1461026d57610155565b80630fcfbd11146101a25780630fe9188e146101d557806333a88c72146101f557610155565b36610155576040517f346633fb0000000000000000000000000000000000000000000000000000000081523360048201523460248201819052309163346633fb91906044016000604051808303818588803b15801561013f57600080fd5b505af1158015610153573d6000803e3d6000fd5b005b60405162461bcd60e51b815260206004820152600b60248201527f756e737570706f7274656400000000000000000000000000000000000000000060448201526064015b60405180910390fd5b3480156101ae57600080fd5b506101c26101bd366004610f80565b61038e565b6040519081526020015b60405180910390f35b3480156101e157600080fd5b506101536101f0366004610fb5565b610428565b34801561020157600080fd5b50610215610210366004610f80565b61049e565b60405190151581526020016101cc565b610153610233366004610fe3565b6104f1565b34801561024457600080fd5b5061015361025336600461100f565b6105d4565b34801561026457600080fd5b50610153610683565b34801561027957600080fd5b506000546040516001600160a01b0390911681526020016101cc565b3480156102a157600080fd5b506101536102b036600461102c565b610697565b3480156102c157600080fd5b506101536102d0366004610fe3565b6107e9565b3480156102e157600080fd5b506102f56102f03660046110a2565b610899565b60405167ffffffffffffffff90911681526020016101cc565b34801561031a57600080fd5b5061015361032936600461119b565b6108fa565b34801561033a57600080fd5b506101536103493660046111fd565b610afc565b34801561035a57600080fd5b5061015361036936600461121f565b610b98565b34801561037a57600080fd5b5061015361038936600461100f565b610d78565b600080826040516020016103a291906112ce565b60408051601f19818403018152918152815160209283012060008181526001909352912054909150806104215760405162461bcd60e51b815260206004820152602160248201527f54686973206d65737361676520776173206e65766572207375626d69747465646044820152601760f91b6064820152608401610199565b9392505050565b610430610dcf565b600081815260046020526040812054900361048d5760405162461bcd60e51b815260206004820152601a60248201527f537461746520726f6f7420646f6573206e6f742065786973742e0000000000006044820152606401610199565b600090815260046020526040812055565b600080826040516020016104b291906112ce565b60408051601f1981840301815291815281516020928301206000818152600190935291205490915080158015906104e95750428111155b949350505050565b60003411801561050057508034145b6105725760405162461bcd60e51b815260206004820152603060248201527f417474656d7074696e6720746f2073656e642076616c756520776974686f757460448201527f2070726f766964696e67204574686572000000000000000000000000000000006064820152608401610199565b600061057d33610e15565b6040805134815267ffffffffffffffff831660208201529192506001600160a01b0385169133917f50c536ac33a920f00755865b831d17bf4cff0b2e0345f65b16d52bfc004068b6910160405180910390a3505050565b6105dc610dcf565b6000816001600160a01b03164760405160006040518083038185875af1925050503d8060008114610629576040519150601f19603f3d011682016040523d82523d6000602084013e61062e565b606091505b505090508061067f5760405162461bcd60e51b815260206004820152601460248201527f6661696c65642073656e64696e672076616c75650000000000000000000000006044820152606401610199565b5050565b61068b610dcf565b6106956000610e73565b565b61069f610dcf565b60006106ab82426113cf565b90506000836040516020016106c091906112ce565b60408051601f198184030181529181528151602092830120600081815260019093529120549091501561075b5760405162461bcd60e51b815260206004820152602160248201527f4d657373616765207375626d6974746564206d6f7265207468616e206f6e636560448201527f21000000000000000000000000000000000000000000000000000000000000006064820152608401610199565b600081815260016020908152604082208490556002919061077e9087018761100f565b6001600160a01b0316815260208101919091526040016000908120906107aa60808701606088016113e2565b63ffffffff168152602080820192909252604001600090812080546001810182559082529190208591600402016107e182826115b0565b505050505050565b6107f1610dcf565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461083e576040519150601f19603f3d011682016040523d82523d6000602084013e610843565b606091505b50509050806108945760405162461bcd60e51b815260206004820152601460248201527f6661696c65642073656e64696e672076616c75650000000000000000000000006044820152606401610199565b505050565b60006108a433610e15565b9050336001600160a01b03167fb93c37389233beb85a3a726c3f15c2d15533ee74cb602f20f490dfffef7759378288888888886040516108e9969594939291906116ca565b60405180910390a295945050505050565b600081815260046020526040812054900361096a5760405162461bcd60e51b815260206004820152602a60248201527f526f6f74206973206e6f74207075626c6973686564206f6e2074686973206d6560448201526939b9b0b3b290313ab99760b11b6064820152608401610199565b6000818152600460205260409020544210156109d25760405162461bcd60e51b815260206004820152602160248201527f526f6f74206973206e6f7420636f6e736964657265642066696e616c207965746044820152601760f91b6064820152608401610199565b6000846040516020016109e5919061171a565b60408051601f198184030181528282528051602091820120908301829052600160608401527f760000000000000000000000000000000000000000000000000000000000000060808401529082015260a001604051602081830303815290604052805190602001209050610a8384848484604051602001610a6891815260200190565b60405160208183030381529060405280519060200120610ed0565b610af55760405162461bcd60e51b815260206004820152603360248201527f496e76616c696420696e636c7573696f6e2070726f6f6620666f722076616c7560448201527f65207472616e73666572206d6573736167652e000000000000000000000000006064820152608401610199565b5050505050565b610b04610dcf565b60008281526004602052604090205415610b865760405162461bcd60e51b815260206004820152602560248201527f526f6f7420616c726561647920616464656420746f20746865206d657373616760448201527f65206275730000000000000000000000000000000000000000000000000000006064820152608401610199565b60009182526004602052604090912055565b6000818152600460205260408120549003610c085760405162461bcd60e51b815260206004820152602a60248201527f526f6f74206973206e6f74207075626c6973686564206f6e2074686973206d6560448201526939b9b0b3b290313ab99760b11b6064820152608401610199565b600081815260046020526040902054421015610c705760405162461bcd60e51b815260206004820152602160248201527f526f6f74206973206e6f7420636f6e736964657265642066696e616c207965746044820152601760f91b6064820152608401610199565b600084604051602001610c8391906112ce565b60408051601f198184030181528282528051602091820120908301829052600160608401527f6d0000000000000000000000000000000000000000000000000000000000000060808401529082015260a001604051602081830303815290604052805190602001209050610d0684848484604051602001610a6891815260200190565b610af55760405162461bcd60e51b815260206004820152603060248201527f496e76616c696420696e636c7573696f6e2070726f6f6620666f722063726f7360448201527f7320636861696e206d6573736167652e000000000000000000000000000000006064820152608401610199565b610d80610dcf565b6001600160a01b038116610dc3576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610199565b610dcc81610e73565b50565b6000546001600160a01b03163314610695576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610199565b6001600160a01b0381166000908152600360205260408120805467ffffffffffffffff169160019190610e48838561177a565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550919050565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600082610ede868685610ee8565b1495945050505050565b600081815b84811015610f2b57610f1782878784818110610f0b57610f0b6117a2565b90506020020135610f34565b915080610f23816117b8565b915050610eed565b50949350505050565b6000818310610f50576000828152602084905260409020610f5f565b60008381526020839052604090205b90505b92915050565b600060c08284031215610f7a57600080fd5b50919050565b600060208284031215610f9257600080fd5b813567ffffffffffffffff811115610fa957600080fd5b6104e984828501610f68565b600060208284031215610fc757600080fd5b5035919050565b6001600160a01b0381168114610dcc57600080fd5b60008060408385031215610ff657600080fd5b823561100181610fce565b946020939093013593505050565b60006020828403121561102157600080fd5b813561042181610fce565b6000806040838503121561103f57600080fd5b823567ffffffffffffffff81111561105657600080fd5b61106285828601610f68565b95602094909401359450505050565b63ffffffff81168114610dcc57600080fd5b60ff81168114610dcc57600080fd5b803561109d81611083565b919050565b6000806000806000608086880312156110ba57600080fd5b85356110c581611071565b945060208601356110d581611071565b9350604086013567ffffffffffffffff808211156110f257600080fd5b818801915088601f83011261110657600080fd5b81358181111561111557600080fd5b89602082850101111561112757600080fd5b602083019550809450505050606086013561114181611083565b809150509295509295909350565b60008083601f84011261116157600080fd5b50813567ffffffffffffffff81111561117957600080fd5b6020830191508360208260051b850101111561119457600080fd5b9250929050565b60008060008084860360c08112156111b257600080fd5b60808112156111c057600080fd5b50849350608085013567ffffffffffffffff8111156111de57600080fd5b6111ea8782880161114f565b9598909750949560a00135949350505050565b6000806040838503121561121057600080fd5b50508035926020909101359150565b6000806000806060858703121561123557600080fd5b843567ffffffffffffffff8082111561124d57600080fd5b61125988838901610f68565b9550602087013591508082111561126f57600080fd5b5061127c8782880161114f565b9598909750949560400135949350505050565b67ffffffffffffffff81168114610dcc57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152600082356112df81610fce565b6001600160a01b03811660208401525060208301356112fd8161128f565b67ffffffffffffffff80821660408501526040850135915061131e82611071565b63ffffffff80831660608601526060860135925061133b83611071565b80831660808601525060808501359150601e1985360301821261135d57600080fd5b602091850191820191358181111561137457600080fd5b80360383131561138357600080fd5b60c060a086015261139860e0860182856112a5565b925050506113a860a08501611092565b60ff811660c0850152509392505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610f6257610f626113b9565b6000602082840312156113f457600080fd5b813561042181611071565b60008135610f6281611071565b6000808335601e1984360301811261142357600080fd5b83018035915067ffffffffffffffff82111561143e57600080fd5b60200191503681900382131561119457600080fd5b634e487b7160e01b600052604160045260246000fd5b600181811c9082168061147d57607f821691505b602082108103610f7a57634e487b7160e01b600052602260045260246000fd5b601f82111561089457600081815260208120601f850160051c810160208610156114c45750805b601f850160051c820191505b818110156107e1578281556001016114d0565b67ffffffffffffffff8311156114fb576114fb611453565b61150f836115098354611469565b8361149d565b6000601f841160018114611543576000851561152b5750838201355b600019600387901b1c1916600186901b178355610af5565b600083815260209020601f19861690835b828110156115745786850135825560209485019460019092019101611554565b50868210156115915760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60008135610f6281611083565b81356115bb81610fce565b6001600160a01b038116905081548173ffffffffffffffffffffffffffffffffffffffff19821617835560208401356115f38161128f565b7bffffffffffffffff00000000000000000000000000000000000000008160a01b1690507fffffffff000000000000000000000000000000000000000000000000000000008184828516171785556040860135925061165183611071565b921760e09190911b90911617815561168961166e606084016113ff565b6001830163ffffffff821663ffffffff198254161781555050565b611696608083018361140c565b6116a48183600286016114e3565b505061067f6116b560a084016115a3565b6003830160ff821660ff198254161781555050565b67ffffffffffffffff87168152600063ffffffff808816602084015280871660408401525060a0606083015261170460a0830185876112a5565b905060ff83166080830152979650505050505050565b60808101823561172981610fce565b6001600160a01b03908116835260208401359061174582610fce565b1660208301526040838101359083015260608301356117638161128f565b67ffffffffffffffff811660608401525092915050565b67ffffffffffffffff81811683821601908082111561179b5761179b6113b9565b5092915050565b634e487b7160e01b600052603260045260246000fd5b6000600182016117ca576117ca6113b9565b506001019056fea2646970667358221220a449a197632e1117b118ced8f7cf97a1ae44b160775ee146e59b50cbc1b8dcaa64736f6c63430008140033a2646970667358221220309da62fd58df02f8628b3ebd2b6e5d0deb6d76c30954e9cc12c8ee1656f994b64736f6c63430008140033", } // ManagementContractABI is the input ABI used to generate the binding from. @@ -326,6 +326,70 @@ func (_ManagementContract *ManagementContractCallerSession) GetRollupByHash(roll return _ManagementContract.Contract.GetRollupByHash(&_ManagementContract.CallOpts, rollupHash) } +// GetRollupByNumber is a free data retrieval call binding the contract method 0x87059edb. +// +// Solidity: function GetRollupByNumber(uint256 number) view returns(bool, (bytes32,bytes,uint256)) +func (_ManagementContract *ManagementContractCaller) GetRollupByNumber(opts *bind.CallOpts, number *big.Int) (bool, StructsMetaRollup, error) { + var out []interface{} + err := _ManagementContract.contract.Call(opts, &out, "GetRollupByNumber", number) + + if err != nil { + return *new(bool), *new(StructsMetaRollup), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + out1 := *abi.ConvertType(out[1], new(StructsMetaRollup)).(*StructsMetaRollup) + + return out0, out1, err + +} + +// GetRollupByNumber is a free data retrieval call binding the contract method 0x87059edb. +// +// Solidity: function GetRollupByNumber(uint256 number) view returns(bool, (bytes32,bytes,uint256)) +func (_ManagementContract *ManagementContractSession) GetRollupByNumber(number *big.Int) (bool, StructsMetaRollup, error) { + return _ManagementContract.Contract.GetRollupByNumber(&_ManagementContract.CallOpts, number) +} + +// GetRollupByNumber is a free data retrieval call binding the contract method 0x87059edb. +// +// Solidity: function GetRollupByNumber(uint256 number) view returns(bool, (bytes32,bytes,uint256)) +func (_ManagementContract *ManagementContractCallerSession) GetRollupByNumber(number *big.Int) (bool, StructsMetaRollup, error) { + return _ManagementContract.Contract.GetRollupByNumber(&_ManagementContract.CallOpts, number) +} + +// GetUniqueForkID is a free data retrieval call binding the contract method 0x568699c8. +// +// Solidity: function GetUniqueForkID(uint256 number) view returns(bytes32, (bytes32,bytes,uint256)) +func (_ManagementContract *ManagementContractCaller) GetUniqueForkID(opts *bind.CallOpts, number *big.Int) ([32]byte, StructsMetaRollup, error) { + var out []interface{} + err := _ManagementContract.contract.Call(opts, &out, "GetUniqueForkID", number) + + if err != nil { + return *new([32]byte), *new(StructsMetaRollup), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + out1 := *abi.ConvertType(out[1], new(StructsMetaRollup)).(*StructsMetaRollup) + + return out0, out1, err + +} + +// GetUniqueForkID is a free data retrieval call binding the contract method 0x568699c8. +// +// Solidity: function GetUniqueForkID(uint256 number) view returns(bytes32, (bytes32,bytes,uint256)) +func (_ManagementContract *ManagementContractSession) GetUniqueForkID(number *big.Int) ([32]byte, StructsMetaRollup, error) { + return _ManagementContract.Contract.GetUniqueForkID(&_ManagementContract.CallOpts, number) +} + +// GetUniqueForkID is a free data retrieval call binding the contract method 0x568699c8. +// +// Solidity: function GetUniqueForkID(uint256 number) view returns(bytes32, (bytes32,bytes,uint256)) +func (_ManagementContract *ManagementContractCallerSession) GetUniqueForkID(number *big.Int) ([32]byte, StructsMetaRollup, error) { + return _ManagementContract.Contract.GetUniqueForkID(&_ManagementContract.CallOpts, number) +} + // IsSequencerEnclave is a free data retrieval call binding the contract method 0xdb5d91b1. // // Solidity: function IsSequencerEnclave(address _addr) view returns(bool) @@ -825,25 +889,25 @@ func (_ManagementContract *ManagementContractTransactorSession) SetImportantCont return _ManagementContract.Contract.SetImportantContractAddress(&_ManagementContract.TransactOpts, key, newAddress) } -// AddCrossChainMessagesRoot is a paid mutator transaction binding the contract method 0x3f3f6a18. +// AddCrossChainMessagesRoot is a paid mutator transaction binding the contract method 0x073b6ef3. // -// Solidity: function addCrossChainMessagesRoot(bytes32 _lastBatchHash, bytes32 blockHash, uint256 blockNum, bytes[] crossChainHashes, bytes signature) returns() -func (_ManagementContract *ManagementContractTransactor) AddCrossChainMessagesRoot(opts *bind.TransactOpts, _lastBatchHash [32]byte, blockHash [32]byte, blockNum *big.Int, crossChainHashes [][]byte, signature []byte) (*types.Transaction, error) { - return _ManagementContract.contract.Transact(opts, "addCrossChainMessagesRoot", _lastBatchHash, blockHash, blockNum, crossChainHashes, signature) +// Solidity: function addCrossChainMessagesRoot(bytes32 _lastBatchHash, bytes32 blockHash, uint256 blockNum, bytes[] crossChainHashes, bytes signature, uint256 rollupNumber, bytes32 forkID) returns() +func (_ManagementContract *ManagementContractTransactor) AddCrossChainMessagesRoot(opts *bind.TransactOpts, _lastBatchHash [32]byte, blockHash [32]byte, blockNum *big.Int, crossChainHashes [][]byte, signature []byte, rollupNumber *big.Int, forkID [32]byte) (*types.Transaction, error) { + return _ManagementContract.contract.Transact(opts, "addCrossChainMessagesRoot", _lastBatchHash, blockHash, blockNum, crossChainHashes, signature, rollupNumber, forkID) } -// AddCrossChainMessagesRoot is a paid mutator transaction binding the contract method 0x3f3f6a18. +// AddCrossChainMessagesRoot is a paid mutator transaction binding the contract method 0x073b6ef3. // -// Solidity: function addCrossChainMessagesRoot(bytes32 _lastBatchHash, bytes32 blockHash, uint256 blockNum, bytes[] crossChainHashes, bytes signature) returns() -func (_ManagementContract *ManagementContractSession) AddCrossChainMessagesRoot(_lastBatchHash [32]byte, blockHash [32]byte, blockNum *big.Int, crossChainHashes [][]byte, signature []byte) (*types.Transaction, error) { - return _ManagementContract.Contract.AddCrossChainMessagesRoot(&_ManagementContract.TransactOpts, _lastBatchHash, blockHash, blockNum, crossChainHashes, signature) +// Solidity: function addCrossChainMessagesRoot(bytes32 _lastBatchHash, bytes32 blockHash, uint256 blockNum, bytes[] crossChainHashes, bytes signature, uint256 rollupNumber, bytes32 forkID) returns() +func (_ManagementContract *ManagementContractSession) AddCrossChainMessagesRoot(_lastBatchHash [32]byte, blockHash [32]byte, blockNum *big.Int, crossChainHashes [][]byte, signature []byte, rollupNumber *big.Int, forkID [32]byte) (*types.Transaction, error) { + return _ManagementContract.Contract.AddCrossChainMessagesRoot(&_ManagementContract.TransactOpts, _lastBatchHash, blockHash, blockNum, crossChainHashes, signature, rollupNumber, forkID) } -// AddCrossChainMessagesRoot is a paid mutator transaction binding the contract method 0x3f3f6a18. +// AddCrossChainMessagesRoot is a paid mutator transaction binding the contract method 0x073b6ef3. // -// Solidity: function addCrossChainMessagesRoot(bytes32 _lastBatchHash, bytes32 blockHash, uint256 blockNum, bytes[] crossChainHashes, bytes signature) returns() -func (_ManagementContract *ManagementContractTransactorSession) AddCrossChainMessagesRoot(_lastBatchHash [32]byte, blockHash [32]byte, blockNum *big.Int, crossChainHashes [][]byte, signature []byte) (*types.Transaction, error) { - return _ManagementContract.Contract.AddCrossChainMessagesRoot(&_ManagementContract.TransactOpts, _lastBatchHash, blockHash, blockNum, crossChainHashes, signature) +// Solidity: function addCrossChainMessagesRoot(bytes32 _lastBatchHash, bytes32 blockHash, uint256 blockNum, bytes[] crossChainHashes, bytes signature, uint256 rollupNumber, bytes32 forkID) returns() +func (_ManagementContract *ManagementContractTransactorSession) AddCrossChainMessagesRoot(_lastBatchHash [32]byte, blockHash [32]byte, blockNum *big.Int, crossChainHashes [][]byte, signature []byte, rollupNumber *big.Int, forkID [32]byte) (*types.Transaction, error) { + return _ManagementContract.Contract.AddCrossChainMessagesRoot(&_ManagementContract.TransactOpts, _lastBatchHash, blockHash, blockNum, crossChainHashes, signature, rollupNumber, forkID) } // Initialize is a paid mutator transaction binding the contract method 0x8129fc1c. diff --git a/contracts/generated/ObscuroBridge/ObscuroBridge.go b/contracts/generated/ObscuroBridge/ObscuroBridge.go index d683460488..e666104716 100644 --- a/contracts/generated/ObscuroBridge/ObscuroBridge.go +++ b/contracts/generated/ObscuroBridge/ObscuroBridge.go @@ -32,7 +32,7 @@ var ( // ObscuroBridgeMetaData contains all meta data concerning the ObscuroBridge contract. var ObscuroBridgeMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"AddressEmptyCode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"AddressInsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedInnerCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SafeERC20FailedOperation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ERC20_TOKEN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"NATIVE_TOKEN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"messengerAddress\",\"type\":\"address\"}],\"name\":\"configure\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"messenger\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"promoteToAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"receiveAssets\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"removeToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"sendERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"sendNative\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"bridge\",\"type\":\"address\"}],\"name\":\"setRemoteBridge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"}],\"name\":\"whitelistToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60806040526001805463ffffffff60a01b1916905534801561002057600080fd5b50611944806100306000396000f3fe6080604052600436106101445760003560e01c806375b238fc116100c0578063a217fddf11610074578063c4d66de811610059578063c4d66de8146103b4578063d547741f146103d4578063e4c3ebc7146103f457600080fd5b8063a217fddf1461037f578063a381c8e21461039457600080fd5b806383bece4d116100a557806383bece4d146102f957806391d148541461031957806393b374421461035f57600080fd5b806375b238fc146102a557806375cb2672146102d957600080fd5b80632f2ff15d11610117578063498d82ab116100fc578063498d82ab146102315780635d872970146102515780635fa7b5841461028557600080fd5b80632f2ff15d146101f157806336568abe1461021157600080fd5b806301ffc9a71461014957806316ce81491461017e5780631888d712146101a0578063248a9ca3146101b3575b600080fd5b34801561015557600080fd5b5061016961016436600461154f565b610428565b60405190151581526020015b60405180910390f35b34801561018a57600080fd5b5061019e61019936600461158e565b610491565b005b61019e6101ae36600461158e565b6104eb565b3480156101bf57600080fd5b506101e36101ce3660046115ab565b60009081526002602052604090206001015490565b604051908152602001610175565b3480156101fd57600080fd5b5061019e61020c3660046115c4565b610624565b34801561021d57600080fd5b5061019e61022c3660046115c4565b61064f565b34801561023d57600080fd5b5061019e61024c36600461163d565b6106a0565b34801561025d57600080fd5b506101e37f9f225881f6e7ac8a885b63aa2269cbce78dd6a669864ccd2cd2517a8e709d73a81565b34801561029157600080fd5b5061019e6102a036600461158e565b610765565b3480156102b157600080fd5b506101e37fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177581565b3480156102e557600080fd5b5061019e6102f436600461158e565b6107b9565b34801561030557600080fd5b5061019e6103143660046116c0565b610894565b34801561032557600080fd5b506101696103343660046115c4565b60009182526002602090815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561036b57600080fd5b5061019e61037a36600461158e565b610ab0565b34801561038b57600080fd5b506101e3600081565b3480156103a057600080fd5b5061019e6103af3660046116c0565b610b04565b3480156103c057600080fd5b5061019e6103cf36600461158e565b610cb1565b3480156103e057600080fd5b5061019e6103ef3660046115c4565b610e45565b34801561040057600080fd5b506101e37fd2fb17ceaa388942529b17e0006ffc4d559f040dd4f2157b8070f17ad211057881565b60006001600160e01b031982167f7965db0b00000000000000000000000000000000000000000000000000000000148061048b57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756104bb81610e6a565b506003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600034116105405760405162461bcd60e51b815260206004820152600f60248201527f456d707479207472616e736665722e000000000000000000000000000000000060448201526064015b60405180910390fd5b604080518082018252348082526001600160a01b03848116602093840190815284519384019290925290518116828401528251808303840181526060909201909252600354909161059891168260025b600080610e77565b6001546001600160a01b03166040517f346633fb0000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152346024830181905292169163346633fb916044016000604051808303818588803b15801561060757600080fd5b505af115801561061b573d6000803e3d6000fd5b50505050505050565b60008281526002602052604090206001015461063f81610e6a565b6106498383610f83565b50505050565b6001600160a01b0381163314610691576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61069b8282611031565b505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756106ca81610e6a565b6106f47f9f225881f6e7ac8a885b63aa2269cbce78dd6a669864ccd2cd2517a8e709d73a87610f83565b50600063458ffd6360e01b878787878760405160240161071895949392919061172b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915260035490915061061b906001600160a01b0316826001610590565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177561078f81610e6a565b61069b7f9f225881f6e7ac8a885b63aa2269cbce78dd6a669864ccd2cd2517a8e709d73a83611031565b6107c16110b8565b6000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038316908117909155604080517fa1a227fa000000000000000000000000000000000000000000000000000000008152905163a1a227fa916004808201926020929091908290030181865afa158015610840573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610864919061176d565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039290921691909117905550565b6003546000546001600160a01b039182169116331461091b5760405162461bcd60e51b815260206004820152603060248201527f436f6e74726163742063616c6c6572206973206e6f742074686520726567697360448201527f7465726564206d657373656e67657221000000000000000000000000000000006064820152608401610537565b806001600160a01b031661092d611121565b6001600160a01b0316146109a95760405162461bcd60e51b815260206004820152603160248201527f43726f737320636861696e206d65737361676520636f6d696e672066726f6d2060448201527f696e636f72726563742073656e646572210000000000000000000000000000006064820152608401610537565b6001600160a01b03841660009081527f32ef73018533fa188e9e42b313c0a4048c6052342b662fb7510c0d1abcea3413602052604090205460ff16156109f9576109f484848461119e565b610649565b6001600160a01b03841660009081527f13ad2d85210d477fe1a6e25654c8250308cf29b050a4bf0b039d70467486712c602052604090205460ff1615610a42576109f4826111a9565b60405162461bcd60e51b815260206004820152602560248201527f417474656d7074696e6720746f20776974686472617720756e6b6e6f776e206160448201527f737365742e0000000000000000000000000000000000000000000000000000006064820152608401610537565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610ada81610e6a565b61069b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177583610f83565b60008211610b545760405162461bcd60e51b815260206004820152601a60248201527f417474656d7074696e6720656d707479207472616e736665722e0000000000006044820152606401610537565b6001600160a01b03831660009081527f32ef73018533fa188e9e42b313c0a4048c6052342b662fb7510c0d1abcea3413602052604090205460ff16610c275760405162461bcd60e51b815260206004820152604e60248201527f54686973206164647265737320686173206e6f74206265656e20676976656e2060448201527f61207479706520616e64206973207468757320636f6e73696465726564206e6f60648201527f742077686974656c69737465642e000000000000000000000000000000000000608482015260a401610537565b610c338333308561124b565b604080516001600160a01b038581166024830152604482018590528381166064808401919091528351808403909101815260849092019092526020810180516001600160e01b03167f83bece4d0000000000000000000000000000000000000000000000000000000017905260035490916106499116826000610590565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015610cfc5750825b905060008267ffffffffffffffff166001148015610d195750303b155b905081158015610d27575080155b15610d5e576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d9257845468ff00000000000000001916680100000000000000001785555b610d9b866107b9565b610dc57fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177533610f83565b50610df17fd2fb17ceaa388942529b17e0006ffc4d559f040dd4f2157b8070f17ad21105786000610f83565b508315610e3d57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b600082815260026020526040902060010154610e6081610e6a565b6106498383611031565b610e7481336112b2565b50565b60006040518060600160405280876001600160a01b0316815260200186815260200184815250604051602001610ead91906117da565b60408051808303601f19018152919052600180549192506001600160a01b0382169163b1454caa917401000000000000000000000000000000000000000090910463ffffffff16906014610f008361181f565b91906101000a81548163ffffffff021916908363ffffffff1602179055508684866040518563ffffffff1660e01b8152600401610f409493929190611869565b6020604051808303816000875af1158015610f5f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061b91906118a6565b60008281526002602090815260408083206001600160a01b038516845290915281205460ff166110295760008381526002602090815260408083206001600160a01b03861684529091529020805460ff19166001179055610fe13390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161048b565b50600061048b565b60008281526002602090815260408083206001600160a01b038516845290915281205460ff16156110295760008381526002602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161048b565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1661111f576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60008060009054906101000a90046001600160a01b03166001600160a01b03166363012de56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611175573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611199919061176d565b905090565b61069b838284611320565b6040516000906001600160a01b038316908281818181865af19150503d80600081146111f1576040519150601f19603f3d011682016040523d82523d6000602084013e6111f6565b606091505b50509050806112475760405162461bcd60e51b815260206004820152601460248201527f4661696c656420746f2073656e642045746865720000000000000000000000006044820152606401610537565b5050565b6040516001600160a01b0384811660248301528381166044830152606482018390526106499186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611351565b60008281526002602090815260408083206001600160a01b038516845290915290205460ff16611247576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015260248101839052604401610537565b6040516001600160a01b0383811660248301526044820183905261069b91859182169063a9059cbb90606401611280565b60006113666001600160a01b038416836113cd565b9050805160001415801561138b57508080602001905181019061138991906118d0565b155b1561069b576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610537565b60606113db838360006113e2565b9392505050565b606081471015611420576040517fcd786059000000000000000000000000000000000000000000000000000000008152306004820152602401610537565b600080856001600160a01b0316848660405161143c91906118f2565b60006040518083038185875af1925050503d8060008114611479576040519150601f19603f3d011682016040523d82523d6000602084013e61147e565b606091505b509150915061148e868383611498565b9695505050505050565b6060826114ad576114a88261150d565b6113db565b81511580156114c457506001600160a01b0384163b155b15611506576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610537565b50806113db565b80511561151d5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561156157600080fd5b81356001600160e01b0319811681146113db57600080fd5b6001600160a01b0381168114610e7457600080fd5b6000602082840312156115a057600080fd5b81356113db81611579565b6000602082840312156115bd57600080fd5b5035919050565b600080604083850312156115d757600080fd5b8235915060208301356115e981611579565b809150509250929050565b60008083601f84011261160657600080fd5b50813567ffffffffffffffff81111561161e57600080fd5b60208301915083602082850101111561163657600080fd5b9250929050565b60008060008060006060868803121561165557600080fd5b853561166081611579565b9450602086013567ffffffffffffffff8082111561167d57600080fd5b61168989838a016115f4565b909650945060408801359150808211156116a257600080fd5b506116af888289016115f4565b969995985093965092949392505050565b6000806000606084860312156116d557600080fd5b83356116e081611579565b92506020840135915060408401356116f781611579565b809150509250925092565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b038616815260606020820152600061174e606083018688611702565b8281036040840152611761818587611702565b98975050505050505050565b60006020828403121561177f57600080fd5b81516113db81611579565b60005b838110156117a557818101518382015260200161178d565b50506000910152565b600081518084526117c681602086016020860161178a565b601f01601f19169290920160200192915050565b602081526001600160a01b038251166020820152600060208301516060604084015261180960808401826117ae565b9050604084015160608401528091505092915050565b600063ffffffff80831681810361185f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6001019392505050565b600063ffffffff80871683528086166020840152506080604083015261189260808301856117ae565b905060ff8316606083015295945050505050565b6000602082840312156118b857600080fd5b815167ffffffffffffffff811681146113db57600080fd5b6000602082840312156118e257600080fd5b815180151581146113db57600080fd5b6000825161190481846020870161178a565b919091019291505056fea264697066735822122061c41db942ea30cee8f9aa373bbf91f7fb86ce91e5cc4ce247e562fefa3d756864736f6c63430008140033", + Bin: "0x60806040526001805463ffffffff60a01b1916905534801561002057600080fd5b50611944806100306000396000f3fe6080604052600436106101445760003560e01c806375b238fc116100c0578063a217fddf11610074578063c4d66de811610059578063c4d66de8146103b4578063d547741f146103d4578063e4c3ebc7146103f457600080fd5b8063a217fddf1461037f578063a381c8e21461039457600080fd5b806383bece4d116100a557806383bece4d146102f957806391d148541461031957806393b374421461035f57600080fd5b806375b238fc146102a557806375cb2672146102d957600080fd5b80632f2ff15d11610117578063498d82ab116100fc578063498d82ab146102315780635d872970146102515780635fa7b5841461028557600080fd5b80632f2ff15d146101f157806336568abe1461021157600080fd5b806301ffc9a71461014957806316ce81491461017e5780631888d712146101a0578063248a9ca3146101b3575b600080fd5b34801561015557600080fd5b5061016961016436600461154f565b610428565b60405190151581526020015b60405180910390f35b34801561018a57600080fd5b5061019e61019936600461158e565b610491565b005b61019e6101ae36600461158e565b6104eb565b3480156101bf57600080fd5b506101e36101ce3660046115ab565b60009081526002602052604090206001015490565b604051908152602001610175565b3480156101fd57600080fd5b5061019e61020c3660046115c4565b610624565b34801561021d57600080fd5b5061019e61022c3660046115c4565b61064f565b34801561023d57600080fd5b5061019e61024c36600461163d565b6106a0565b34801561025d57600080fd5b506101e37f9f225881f6e7ac8a885b63aa2269cbce78dd6a669864ccd2cd2517a8e709d73a81565b34801561029157600080fd5b5061019e6102a036600461158e565b610765565b3480156102b157600080fd5b506101e37fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177581565b3480156102e557600080fd5b5061019e6102f436600461158e565b6107b9565b34801561030557600080fd5b5061019e6103143660046116c0565b610894565b34801561032557600080fd5b506101696103343660046115c4565b60009182526002602090815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561036b57600080fd5b5061019e61037a36600461158e565b610ab0565b34801561038b57600080fd5b506101e3600081565b3480156103a057600080fd5b5061019e6103af3660046116c0565b610b04565b3480156103c057600080fd5b5061019e6103cf36600461158e565b610cb1565b3480156103e057600080fd5b5061019e6103ef3660046115c4565b610e45565b34801561040057600080fd5b506101e37fd2fb17ceaa388942529b17e0006ffc4d559f040dd4f2157b8070f17ad211057881565b60006001600160e01b031982167f7965db0b00000000000000000000000000000000000000000000000000000000148061048b57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756104bb81610e6a565b506003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600034116105405760405162461bcd60e51b815260206004820152600f60248201527f456d707479207472616e736665722e000000000000000000000000000000000060448201526064015b60405180910390fd5b604080518082018252348082526001600160a01b03848116602093840190815284519384019290925290518116828401528251808303840181526060909201909252600354909161059891168260025b600080610e77565b6001546001600160a01b03166040517f346633fb0000000000000000000000000000000000000000000000000000000081526001600160a01b038481166004830152346024830181905292169163346633fb916044016000604051808303818588803b15801561060757600080fd5b505af115801561061b573d6000803e3d6000fd5b50505050505050565b60008281526002602052604090206001015461063f81610e6a565b6106498383610f83565b50505050565b6001600160a01b0381163314610691576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61069b8282611031565b505050565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c217756106ca81610e6a565b6106f47f9f225881f6e7ac8a885b63aa2269cbce78dd6a669864ccd2cd2517a8e709d73a87610f83565b50600063458ffd6360e01b878787878760405160240161071895949392919061172b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915260035490915061061b906001600160a01b0316826001610590565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177561078f81610e6a565b61069b7f9f225881f6e7ac8a885b63aa2269cbce78dd6a669864ccd2cd2517a8e709d73a83611031565b6107c16110b8565b6000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038316908117909155604080517fa1a227fa000000000000000000000000000000000000000000000000000000008152905163a1a227fa916004808201926020929091908290030181865afa158015610840573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610864919061176d565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039290921691909117905550565b6003546000546001600160a01b039182169116331461091b5760405162461bcd60e51b815260206004820152603060248201527f436f6e74726163742063616c6c6572206973206e6f742074686520726567697360448201527f7465726564206d657373656e67657221000000000000000000000000000000006064820152608401610537565b806001600160a01b031661092d611121565b6001600160a01b0316146109a95760405162461bcd60e51b815260206004820152603160248201527f43726f737320636861696e206d65737361676520636f6d696e672066726f6d2060448201527f696e636f72726563742073656e646572210000000000000000000000000000006064820152608401610537565b6001600160a01b03841660009081527f32ef73018533fa188e9e42b313c0a4048c6052342b662fb7510c0d1abcea3413602052604090205460ff16156109f9576109f484848461119e565b610649565b6001600160a01b03841660009081527f13ad2d85210d477fe1a6e25654c8250308cf29b050a4bf0b039d70467486712c602052604090205460ff1615610a42576109f4826111a9565b60405162461bcd60e51b815260206004820152602560248201527f417474656d7074696e6720746f20776974686472617720756e6b6e6f776e206160448201527f737365742e0000000000000000000000000000000000000000000000000000006064820152608401610537565b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775610ada81610e6a565b61069b7fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177583610f83565b60008211610b545760405162461bcd60e51b815260206004820152601a60248201527f417474656d7074696e6720656d707479207472616e736665722e0000000000006044820152606401610537565b6001600160a01b03831660009081527f32ef73018533fa188e9e42b313c0a4048c6052342b662fb7510c0d1abcea3413602052604090205460ff16610c275760405162461bcd60e51b815260206004820152604e60248201527f54686973206164647265737320686173206e6f74206265656e20676976656e2060448201527f61207479706520616e64206973207468757320636f6e73696465726564206e6f60648201527f742077686974656c69737465642e000000000000000000000000000000000000608482015260a401610537565b610c338333308561124b565b604080516001600160a01b038581166024830152604482018590528381166064808401919091528351808403909101815260849092019092526020810180516001600160e01b03167f83bece4d0000000000000000000000000000000000000000000000000000000017905260035490916106499116826000610590565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015610cfc5750825b905060008267ffffffffffffffff166001148015610d195750303b155b905081158015610d27575080155b15610d5e576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610d9257845468ff00000000000000001916680100000000000000001785555b610d9b866107b9565b610dc57fa49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c2177533610f83565b50610df17fd2fb17ceaa388942529b17e0006ffc4d559f040dd4f2157b8070f17ad21105786000610f83565b508315610e3d57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b600082815260026020526040902060010154610e6081610e6a565b6106498383611031565b610e7481336112b2565b50565b60006040518060600160405280876001600160a01b0316815260200186815260200184815250604051602001610ead91906117da565b60408051808303601f19018152919052600180549192506001600160a01b0382169163b1454caa917401000000000000000000000000000000000000000090910463ffffffff16906014610f008361181f565b91906101000a81548163ffffffff021916908363ffffffff1602179055508684866040518563ffffffff1660e01b8152600401610f409493929190611869565b6020604051808303816000875af1158015610f5f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061b91906118a6565b60008281526002602090815260408083206001600160a01b038516845290915281205460ff166110295760008381526002602090815260408083206001600160a01b03861684529091529020805460ff19166001179055610fe13390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161048b565b50600061048b565b60008281526002602090815260408083206001600160a01b038516845290915281205460ff16156110295760008381526002602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161048b565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1661111f576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60008060009054906101000a90046001600160a01b03166001600160a01b03166363012de56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611175573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611199919061176d565b905090565b61069b838284611320565b6040516000906001600160a01b038316908281818181865af19150503d80600081146111f1576040519150601f19603f3d011682016040523d82523d6000602084013e6111f6565b606091505b50509050806112475760405162461bcd60e51b815260206004820152601460248201527f4661696c656420746f2073656e642045746865720000000000000000000000006044820152606401610537565b5050565b6040516001600160a01b0384811660248301528381166044830152606482018390526106499186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611351565b60008281526002602090815260408083206001600160a01b038516845290915290205460ff16611247576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b038216600482015260248101839052604401610537565b6040516001600160a01b0383811660248301526044820183905261069b91859182169063a9059cbb90606401611280565b60006113666001600160a01b038416836113cd565b9050805160001415801561138b57508080602001905181019061138991906118d0565b155b1561069b576040517f5274afe70000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602401610537565b60606113db838360006113e2565b9392505050565b606081471015611420576040517fcd786059000000000000000000000000000000000000000000000000000000008152306004820152602401610537565b600080856001600160a01b0316848660405161143c91906118f2565b60006040518083038185875af1925050503d8060008114611479576040519150601f19603f3d011682016040523d82523d6000602084013e61147e565b606091505b509150915061148e868383611498565b9695505050505050565b6060826114ad576114a88261150d565b6113db565b81511580156114c457506001600160a01b0384163b155b15611506576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b0385166004820152602401610537565b50806113db565b80511561151d5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006020828403121561156157600080fd5b81356001600160e01b0319811681146113db57600080fd5b6001600160a01b0381168114610e7457600080fd5b6000602082840312156115a057600080fd5b81356113db81611579565b6000602082840312156115bd57600080fd5b5035919050565b600080604083850312156115d757600080fd5b8235915060208301356115e981611579565b809150509250929050565b60008083601f84011261160657600080fd5b50813567ffffffffffffffff81111561161e57600080fd5b60208301915083602082850101111561163657600080fd5b9250929050565b60008060008060006060868803121561165557600080fd5b853561166081611579565b9450602086013567ffffffffffffffff8082111561167d57600080fd5b61168989838a016115f4565b909650945060408801359150808211156116a257600080fd5b506116af888289016115f4565b969995985093965092949392505050565b6000806000606084860312156116d557600080fd5b83356116e081611579565b92506020840135915060408401356116f781611579565b809150509250925092565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b038616815260606020820152600061174e606083018688611702565b8281036040840152611761818587611702565b98975050505050505050565b60006020828403121561177f57600080fd5b81516113db81611579565b60005b838110156117a557818101518382015260200161178d565b50506000910152565b600081518084526117c681602086016020860161178a565b601f01601f19169290920160200192915050565b602081526001600160a01b038251166020820152600060208301516060604084015261180960808401826117ae565b9050604084015160608401528091505092915050565b600063ffffffff80831681810361185f577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6001019392505050565b600063ffffffff80871683528086166020840152506080604083015261189260808301856117ae565b905060ff8316606083015295945050505050565b6000602082840312156118b857600080fd5b815167ffffffffffffffff811681146113db57600080fd5b6000602082840312156118e257600080fd5b815180151581146113db57600080fd5b6000825161190481846020870161178a565b919091019291505056fea2646970667358221220250922b026915b246ec7ed013e9805ea7bb8beecaee481d1c9edd976f5cbaea964736f6c63430008140033", } // ObscuroBridgeABI is the input ABI used to generate the binding from. diff --git a/contracts/src/management/ManagementContract.sol b/contracts/src/management/ManagementContract.sol index 9d8bef28bc..1b538a7c59 100644 --- a/contracts/src/management/ManagementContract.sol +++ b/contracts/src/management/ManagementContract.sol @@ -61,6 +61,7 @@ contract ManagementContract is Initializable, OwnableUpgradeable { function initialize() public initializer { __Ownable_init(msg.sender); lastBatchSeqNo = 0; + rollups.nextFreeSequenceNumber = 0; //redundant as the default is 0, but for clarity merkleMessageBus = new MerkleTreeMessageBus.MerkleTreeMessageBus(); messageBus = MessageBus.IMessageBus(address(merkleMessageBus)); @@ -72,14 +73,36 @@ contract ManagementContract is Initializable, OwnableUpgradeable { return (rol.Hash == rollupHash , rol); } + function GetRollupByNumber(uint256 number) view public returns(bool, Structs.MetaRollup memory) { + bytes32 hash = rollups.byOrder[number]; + if (hash == 0x0) { // ensure we don't try to get rollup for hash zero as that would not pull anything, but the hash would match and return true + return (false, Structs.MetaRollup(0x0, "", 0)); + } + + return GetRollupByHash(hash); + } + + function GetUniqueForkID(uint256 number) view public returns(bytes32, Structs.MetaRollup memory) { + (bool success, Structs.MetaRollup memory rollup) = GetRollupByNumber(number); + if (!success) { + return (0x0, rollup); + } + + return (rollups.toUniqueForkID[number], rollup); + } + function AppendRollup(Structs.MetaRollup calldata _r) internal { rollups.byHash[_r.Hash] = _r; + rollups.byOrder[rollups.nextFreeSequenceNumber] = _r.Hash; + rollups.toUniqueForkID[rollups.nextFreeSequenceNumber] = keccak256(abi.encode(_r.Hash, blockhash(block.number-1))); + rollups.nextFreeSequenceNumber++; + if (_r.LastSequenceNumber > lastBatchSeqNo) { lastBatchSeqNo = _r.LastSequenceNumber; } } - function addCrossChainMessagesRoot(bytes32 _lastBatchHash, bytes32 blockHash, uint256 blockNum, bytes[] memory crossChainHashes, bytes calldata signature) external { + function addCrossChainMessagesRoot(bytes32 _lastBatchHash, bytes32 blockHash, uint256 blockNum, bytes[] memory crossChainHashes, bytes calldata signature, uint256 rollupNumber, bytes32 forkID) external { if (block.number > blockNum + 255) { revert("Block binding too old"); } @@ -88,6 +111,10 @@ contract ManagementContract is Initializable, OwnableUpgradeable { revert(string(abi.encodePacked("Invalid block binding:", Strings.toString(block.number),":", Strings.toString(uint256(blockHash)), ":", Strings.toString(uint256(blockhash(blockNum)))))); } + if (rollups.toUniqueForkID[rollupNumber] != forkID) { + revert("Invalid forkID"); + } + address enclaveID = ECDSA.recover(keccak256(abi.encode(_lastBatchHash, blockHash, blockNum, crossChainHashes)), signature); require(attested[enclaveID], "enclaveID not attested"); //todo: only sequencer, rather than everyone who has attested. diff --git a/contracts/src/management/Structs.sol b/contracts/src/management/Structs.sol index 7261d55e28..336fed12a1 100644 --- a/contracts/src/management/Structs.sol +++ b/contracts/src/management/Structs.sol @@ -12,6 +12,9 @@ interface Structs { struct RollupStorage { mapping(bytes32=>MetaRollup) byHash; + mapping(uint256=>bytes32) byOrder; + mapping(uint256=>bytes32) toUniqueForkID; + uint256 nextFreeSequenceNumber; } struct HeaderCrossChainData { diff --git a/go/common/errutil/errors_util.go b/go/common/errutil/errors_util.go index 2e72aeb154..bbac791733 100644 --- a/go/common/errutil/errors_util.go +++ b/go/common/errutil/errors_util.go @@ -25,6 +25,9 @@ var ( ErrAncestorBatchNotFound = errors.New("parent for batch not found") ErrCrossChainBundleRepublished = errors.New("root already added to the message bus") ErrCrossChainBundleNoBatches = errors.New("no batches for cross chain bundle") + ErrNoNextRollup = errors.New("no next rollup") + ErrRollupForkMismatch = errors.New("rollup fork mismatch") + ErrNoBundleToPublish = errors.New("no bundle to publish") ) // BlockRejectError is used as a standard format for error response from enclave for block submission errors diff --git a/go/common/host/services.go b/go/common/host/services.go index 5a6be435db..970ebf22f2 100644 --- a/go/common/host/services.go +++ b/go/common/host/services.go @@ -22,6 +22,7 @@ const ( EnclaveServiceName = "enclaves" LogSubscriptionServiceName = "log-subs" FilterAPIServiceName = "filter-api" + CrossChainServiceName = "cross-chain" ) // The host has a number of services that encapsulate the various responsibilities of the host. @@ -109,7 +110,7 @@ type L1Publisher interface { PublishSecretResponse(secretResponse *common.ProducedSecretResponse) error // PublishCrossChainBundle will create and publish a cross-chain bundle tx to the management contract - PublishCrossChainBundle(bundle *common.ExtCrossChainBundle) error + PublishCrossChainBundle(*common.ExtCrossChainBundle, *big.Int, gethcommon.Hash) error FetchLatestSeqNo() (*big.Int, error) @@ -119,7 +120,7 @@ type L1Publisher interface { ResyncImportantContracts() error // GetBundleRangeFromManagementContract returns the range of batches for which to build a bundle - GetBundleRangeFromManagementContract() (*big.Int, *big.Int, error) + GetBundleRangeFromManagementContract(lastRollupNumber *big.Int, lastRollupUID gethcommon.Hash) (*gethcommon.Hash, *big.Int, *big.Int, error) } // L2BatchRepository provides an interface for the host to request L2 batch data (live-streaming and historical) diff --git a/go/host/enclave/guardian.go b/go/host/enclave/guardian.go index 9fcf7852f9..f8818e9224 100644 --- a/go/host/enclave/guardian.go +++ b/go/host/enclave/guardian.go @@ -46,6 +46,7 @@ type guardianServiceLocator interface { L1Repo() host.L1BlockRepository L2Repo() host.L2BatchRepository LogSubs() host.LogSubscriptionManager + CrossChainMachine() l1.CrossChainStateMachine } // Guardian is a host service which monitors an enclave, it's responsibilities include: @@ -634,48 +635,24 @@ func (g *Guardian) periodicBundleSubmission() { bundleSubmissionTicker := time.NewTicker(interval) - fromSequenceNumber, _, err := g.sl.L1Publisher().GetBundleRangeFromManagementContract() - if err != nil { - g.logger.Error(`Unable to get bundle range from management contract and initialize cross chain publishing`, log.ErrKey, err) - return - } - for { select { case <-bundleSubmissionTicker.C: - from, to, err := g.sl.L1Publisher().GetBundleRangeFromManagementContract() + err := g.sl.CrossChainMachine().Synchronize() if err != nil { - g.logger.Error("Unable to get bundle range from management contract", log.ErrKey, err) + g.logger.Error("Failed to synchronize cross chain state machine", log.ErrKey, err) continue } - if from.Uint64() > fromSequenceNumber.Uint64() { - fromSequenceNumber.Set(from) - } - - bundle, err := g.enclaveClient.ExportCrossChainData(context.Background(), fromSequenceNumber.Uint64(), to.Uint64()) + err = g.sl.CrossChainMachine().PublishNextBundle() if err != nil { - if !errors.Is(err, errutil.ErrCrossChainBundleNoBatches) { - g.logger.Error("Unable to export cross chain bundle from enclave", log.ErrKey, err) - } - if errors.Is(err, context.DeadlineExceeded) { - g.logger.Error(`Cross chain bundle export timed out.`, log.ErrKey, err) - return // stop the process - if we are timing out we are not going to catch up + if errors.Is(err, errutil.ErrCrossChainBundleNoBatches) { + g.logger.Debug("No batches to publish") + } else { + g.logger.Error("Failed to publish next bundle", log.ErrKey, err) } continue } - - if len(bundle.CrossChainRootHashes) == 0 { - g.logger.Debug("No cross chain data to submit") - fromSequenceNumber.SetUint64(to.Uint64() + 1) - continue - } - - err = g.sl.L1Publisher().PublishCrossChainBundle(bundle) - if err != nil { - g.logger.Error("Unable to publish cross chain bundle", log.ErrKey, err) - continue - } case <-g.hostInterrupter.Done(): bundleSubmissionTicker.Stop() return diff --git a/go/host/host.go b/go/host/host.go index 985e791676..3d2dfa1f98 100644 --- a/go/host/host.go +++ b/go/host/host.go @@ -114,10 +114,13 @@ func NewHost(config *config.HostConfig, hostServices *ServicesRegistry, p2p host retryIntervalForL1Receipt, hostStorage, ) + hostServices.RegisterService(hostcommon.L1PublisherName, l1Publisher) hostServices.RegisterService(hostcommon.L2BatchRepositoryName, l2Repo) hostServices.RegisterService(hostcommon.EnclaveServiceName, enclService) hostServices.RegisterService(hostcommon.LogSubscriptionServiceName, subsService) + l1StateMachine := l1.NewCrossChainStateMachine(l1Publisher, mgmtContractLib, ethClient, hostServices.Enclaves().GetEnclaveClient(), logger, host.stopControl) + hostServices.RegisterService(hostcommon.CrossChainServiceName, l1StateMachine) var prof *profiler.Profiler if config.ProfilerEnabled { diff --git a/go/host/l1/publisher.go b/go/host/l1/publisher.go index 5971f92bda..cfc077456f 100644 --- a/go/host/l1/publisher.go +++ b/go/host/l1/publisher.go @@ -99,43 +99,46 @@ func (p *Publisher) Start() error { return nil } -func (p *Publisher) GetBundleRangeFromManagementContract() (*big.Int, *big.Int, error) { +func (p *Publisher) GetBundleRangeFromManagementContract(lastRollupNumber *big.Int, lastRollupUID gethcommon.Hash) (*gethcommon.Hash, *big.Int, *big.Int, error) { if p.mgmtContractLib.IsMock() { - return nil, nil, fmt.Errorf("bundle publishing unavailable for mocked environments") + return nil, nil, nil, fmt.Errorf("bundle publishing unavailable for mocked environments") } managementCtr, err := ManagementContract.NewManagementContract(*p.mgmtContractLib.GetContractAddr(), p.ethClient.EthClient()) if err != nil { p.logger.Error("Unable to instantiate management contract client") - return nil, nil, err + return nil, nil, nil, err } - lastBatchHash, err := managementCtr.LastBatchHash(&bind.CallOpts{}) + hashBytes, rollup, err := managementCtr.GetUniqueForkID(&bind.CallOpts{}, lastRollupNumber) if err != nil { - p.logger.Error("Unable to fetch last batch hash from management contract", log.ErrKey, err) - return nil, nil, err + p.logger.Error("Unable to get unique fork ID from management contract") + return nil, nil, nil, err } - var fromSeqNo *big.Int - if lastBatchHash == [32]byte{} { - fromSeqNo = big.NewInt(0) - } else { - batch, err := p.storage.FetchBatch(lastBatchHash) - if err != nil { - p.logger.Error("Unable to fetch last batch from host db", log.ErrKey, err) - return nil, nil, err - } - fromSeqNo = batch.SeqNo() - fromSeqNo = batch.SeqNo().Add(fromSeqNo, big.NewInt(1)) + rollupUid := gethcommon.BytesToHash(hashBytes[:]) + if rollupUid != lastRollupUID { + return nil, nil, nil, errutil.ErrRollupForkMismatch } - lastBatchRolledUpSeqNo, err := managementCtr.LastBatchSeqNo(&bind.CallOpts{}) + fromSeqNo := big.NewInt(0) + if lastRollupNumber.Cmp(big.NewInt(0)) != 0 { + fromSeqNo = big.NewInt(0).SetUint64(rollup.LastSequenceNumber.Uint64() + 1) + } + + nextRollupNumber := big.NewInt(0).SetUint64(lastRollupNumber.Uint64() + 1) + nextHashBytes, nextRollup, err := managementCtr.GetUniqueForkID(&bind.CallOpts{}, nextRollupNumber) if err != nil { - p.logger.Error("Unable to fetch last batch seq no from management contract", log.ErrKey, err) - return nil, nil, err + p.logger.Error("Unable to get unique fork ID from management contract") + return nil, nil, nil, err + } + + nextRollupUID := gethcommon.BytesToHash(nextHashBytes[:]) + if nextRollupUID.Big().Cmp(gethcommon.Big0) == 0 { + return nil, nil, nil, errutil.ErrNoNextRollup } - return fromSeqNo, lastBatchRolledUpSeqNo, nil + return &nextRollupUID, fromSeqNo, nextRollup.LastSequenceNumber, nil } func (p *Publisher) Stop() error { @@ -281,7 +284,7 @@ func (p *Publisher) PublishRollup(producedRollup *common.ExtRollup) { } } -func (p *Publisher) PublishCrossChainBundle(bundle *common.ExtCrossChainBundle) error { +func (p *Publisher) PublishCrossChainBundle(bundle *common.ExtCrossChainBundle, rollupNum *big.Int, forkID gethcommon.Hash) error { if p.mgmtContractLib.IsMock() { return nil } @@ -310,7 +313,7 @@ func (p *Publisher) PublishCrossChainBundle(bundle *common.ExtCrossChainBundle) transactor.Nonce = big.NewInt(0).SetUint64(nonce) - tx, err := managementCtr.AddCrossChainMessagesRoot(transactor, [32]byte(bundle.LastBatchHash.Bytes()), bundle.L1BlockHash, bundle.L1BlockNum, bundle.CrossChainRootHashes, bundle.Signature) + tx, err := managementCtr.AddCrossChainMessagesRoot(transactor, [32]byte(bundle.LastBatchHash.Bytes()), bundle.L1BlockHash, bundle.L1BlockNum, bundle.CrossChainRootHashes, bundle.Signature, rollupNum, forkID) if err != nil { if !errors.Is(err, errutil.ErrCrossChainBundleRepublished) { p.logger.Error("Error with submitting cross chain bundle transaction.", log.ErrKey, err, log.BundleHashKey, bundle.LastBatchHash) diff --git a/go/host/l1/statemachine.go b/go/host/l1/statemachine.go new file mode 100644 index 0000000000..d941e91c9e --- /dev/null +++ b/go/host/l1/statemachine.go @@ -0,0 +1,193 @@ +package l1 + +import ( + "context" + "errors" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + gethcommon "github.com/ethereum/go-ethereum/common" + gethlog "github.com/ethereum/go-ethereum/log" + "github.com/ten-protocol/go-ten/contracts/generated/ManagementContract" + "github.com/ten-protocol/go-ten/go/common" + "github.com/ten-protocol/go-ten/go/common/errutil" + "github.com/ten-protocol/go-ten/go/common/host" + "github.com/ten-protocol/go-ten/go/common/stopcontrol" + "github.com/ten-protocol/go-ten/go/ethadapter" + "github.com/ten-protocol/go-ten/go/ethadapter/mgmtcontractlib" +) + +type ForkUniqueID = gethcommon.Hash +type RollupNumber = uint64 + +type CrossChainStateMachine interface { + GetRollupData(number RollupNumber) (RollupInfo, error) + Synchronize() error + PublishNextBundle() error + host.Service +} + +// crossChainStateMachine - responsible for maintaining a view of the submitted cross chain bundles for the rollups on the L1. +// Whenever a reorg happens, the state machine will revert to the latest known common ancestor rollup. +// Bundles are only submitted after a rollup is pushed on the L1. The state machine will keep track of the latest rollup and the bundles that have been submitted. +type crossChainStateMachine struct { + latestRollup RollupInfo + rollupHistory map[RollupNumber]RollupInfo + currentRollup RollupNumber + + enclaveClient common.Enclave + publisher host.L1Publisher + ethClient ethadapter.EthClient + mgmtContractLib mgmtcontractlib.MgmtContractLib // Library to handle Management Contract lib operations + logger gethlog.Logger + hostStopper *stopcontrol.StopControl +} + +type RollupInfo struct { + ForkUID ForkUniqueID + Number RollupNumber +} + +func NewCrossChainStateMachine( + publisher host.L1Publisher, + mgmtContractLib mgmtcontractlib.MgmtContractLib, + ethClient ethadapter.EthClient, + enclaveClient common.Enclave, + logger gethlog.Logger, + hostStopper *stopcontrol.StopControl, +) CrossChainStateMachine { + return &crossChainStateMachine{ + latestRollup: RollupInfo{ + ForkUID: gethcommon.Hash{}, + Number: 0, + }, + rollupHistory: make(map[RollupNumber]RollupInfo), + currentRollup: 0, + publisher: publisher, + ethClient: ethClient, + mgmtContractLib: mgmtContractLib, + enclaveClient: enclaveClient, + logger: logger, + hostStopper: hostStopper, + } +} + +func (c *crossChainStateMachine) Start() error { + return nil +} +func (c *crossChainStateMachine) Stop() error { + return nil +} +func (c *crossChainStateMachine) HealthStatus(context.Context) host.HealthStatus { + errMsg := "" + if c.hostStopper.IsStopping() { + errMsg = "not running" + } + return &host.BasicErrHealthStatus{ErrMsg: errMsg} +} + +func (c *crossChainStateMachine) GetRollupData(number RollupNumber) (RollupInfo, error) { + if number == c.latestRollup.Number { + return c.latestRollup, nil + } else if number > c.latestRollup.Number { + return RollupInfo{}, errutil.ErrNotFound + } else { + return c.rollupHistory[number], nil + } +} + +func (c *crossChainStateMachine) PublishNextBundle() error { + // If all bundles for the rollups have been published, there is nothing to do. + if c.currentRollup >= c.latestRollup.Number { + return nil + } + + // Get the bundle range from the management contract + nextForkUID, begin, end, err := c.publisher.GetBundleRangeFromManagementContract(big.NewInt(0).SetUint64(c.currentRollup), c.latestRollup.ForkUID) + if err != nil { + return err + } + + data, err := c.GetRollupData(c.currentRollup + 1) + if err != nil { + return err + } + if data.ForkUID != *nextForkUID { + return errutil.ErrRollupForkMismatch + } + + bundle, err := c.enclaveClient.ExportCrossChainData(context.Background(), begin.Uint64(), end.Uint64()) + if err != nil { + return err + } + + err = c.publisher.PublishCrossChainBundle(bundle, big.NewInt(0).SetUint64(data.Number), data.ForkUID) + if err != nil { + return err + } + + // Move the current rollup to the next rollup + c.currentRollup++ + + return nil +} + +// Synchronize - checks if there are any new rollups or forks and moves the tracking needle to the latest common ancestor. +func (c *crossChainStateMachine) Synchronize() error { + forkUID, _, _, err := c.publisher.GetBundleRangeFromManagementContract(big.NewInt(0).SetUint64(c.latestRollup.Number), c.latestRollup.ForkUID) + if err != nil { + if errors.Is(err, errutil.ErrNoNextRollup) { + c.logger.Debug("No new rollup or fork found") + return nil + } + + if errors.Is(err, errutil.ErrRollupForkMismatch) { + return c.revertToLatestKnownCommonAncestorRollup() + } + + c.logger.Error("Failed to get bundle range from management contract", "error", err) + return err + } + + c.rollupHistory[c.latestRollup.Number] = c.latestRollup + c.latestRollup = RollupInfo{ + ForkUID: *forkUID, + Number: c.latestRollup.Number + 1, + } + + return nil +} + +func (c *crossChainStateMachine) revertToLatestKnownCommonAncestorRollup() error { + managementContract, err := ManagementContract.NewManagementContract(*c.mgmtContractLib.GetContractAddr(), c.ethClient.EthClient()) + if err != nil { + return err + } + + hashBytes, _, err := managementContract.GetUniqueForkID(&bind.CallOpts{}, big.NewInt(0).SetUint64(c.latestRollup.Number)) + if err != nil { + return err + } + + var forkHash gethcommon.Hash + forkHash = gethcommon.BytesToHash(hashBytes[:]) + + for forkHash != c.latestRollup.ForkUID { + // Revert to previous rollup; No need to wipe the map as the synchronization reinserts the latest rollup + c.latestRollup = c.rollupHistory[c.latestRollup.Number-1] //go to previous rollup + + hashBytes, _, err = managementContract.GetUniqueForkID(&bind.CallOpts{}, big.NewInt(0).SetUint64(c.latestRollup.Number)) + if err != nil { + return err + } + + forkHash = gethcommon.BytesToHash(hashBytes[:]) + } + + // Rollback current rollup if it was dumped due to a fork. + if c.currentRollup > c.latestRollup.Number { + c.currentRollup = c.latestRollup.Number + } + + return nil +} diff --git a/go/host/servicelocator.go b/go/host/servicelocator.go index d88cd86231..a5067617c8 100644 --- a/go/host/servicelocator.go +++ b/go/host/servicelocator.go @@ -3,6 +3,7 @@ package host import ( "github.com/ethereum/go-ethereum/log" hostcommon "github.com/ten-protocol/go-ten/go/common/host" + "github.com/ten-protocol/go-ten/go/host/l1" ) type ServicesRegistry struct { @@ -59,3 +60,7 @@ func (s *ServicesRegistry) Enclaves() hostcommon.EnclaveService { func (s *ServicesRegistry) LogSubs() hostcommon.LogSubscriptionManager { return s.getService(hostcommon.LogSubscriptionServiceName).(hostcommon.LogSubscriptionManager) } + +func (s *ServicesRegistry) CrossChainMachine() l1.CrossChainStateMachine { + return s.getService(hostcommon.CrossChainServiceName).(l1.CrossChainStateMachine) +} From 186bc2c32969c82760542884e31280467a9a6a7f Mon Sep 17 00:00:00 2001 From: Tudor Malene Date: Wed, 26 Jun 2024 15:11:22 +0100 Subject: [PATCH 2/8] host db performance fixes (#1969) * host db performance fixes * test fix * fix * fix --- go/common/query_types.go | 1 - go/host/enclave/guardian.go | 11 +-- go/host/storage/hostdb/batch.go | 55 +++++++------- go/host/storage/hostdb/block.go | 18 ++--- go/host/storage/hostdb/rollup.go | 34 +++++---- go/host/storage/hostdb/rollup_test.go | 86 ++++++++++++++++------ go/host/storage/hostdb/sql_statements.go | 27 ++++--- go/host/storage/hostdb/transaction.go | 6 +- go/host/storage/hostdb/utils.go | 50 ------------- go/host/storage/init/postgres/001_init.sql | 18 ++--- go/host/storage/init/sqlite/001_init.sql | 15 ++-- go/host/storage/interfaces.go | 2 +- go/host/storage/storage.go | 4 +- 13 files changed, 162 insertions(+), 165 deletions(-) diff --git a/go/common/query_types.go b/go/common/query_types.go index eb6ed1f89c..b222fbab2a 100644 --- a/go/common/query_types.go +++ b/go/common/query_types.go @@ -49,7 +49,6 @@ type PublicTransaction struct { type PublicBatch struct { SequencerOrderNo *big.Int `json:"sequence"` - Hash string `json:"hash"` FullHash common.Hash `json:"fullHash"` Height *big.Int `json:"height"` TxCount *big.Int `json:"txCount"` diff --git a/go/host/enclave/guardian.go b/go/host/enclave/guardian.go index f8818e9224..ce7e9e8b2c 100644 --- a/go/host/enclave/guardian.go +++ b/go/host/enclave/guardian.go @@ -463,6 +463,12 @@ func (g *Guardian) processL1BlockTransactions(block *common.L1Block) { // if there are any secret responses in the block we should refresh our P2P list to re-sync with the network _, rollupTxs, contractAddressTxs := g.sl.L1Publisher().ExtractObscuroRelevantTransactions(block) + // TODO (@will) this should be removed and pulled from the L1 + err := g.storage.AddBlock(block.Header()) + if err != nil { + g.logger.Error("Could not add block to host db.", log.ErrKey, err) + } + for _, rollup := range rollupTxs { r, err := common.DecodeRollup(rollup.Rollup) if err != nil { @@ -482,11 +488,6 @@ func (g *Guardian) processL1BlockTransactions(block *common.L1Block) { g.logger.Error("Could not store rollup.", log.ErrKey, err) } } - // TODO (@will) this should be removed and pulled from the L1 - err = g.storage.AddBlock(block.Header(), r.Header.Hash()) - if err != nil { - g.logger.Error("Could not add block to host db.", log.ErrKey, err) - } } if len(contractAddressTxs) > 0 { diff --git a/go/host/storage/hostdb/batch.go b/go/host/storage/hostdb/batch.go index 1d1cfd69cb..735f89ed76 100644 --- a/go/host/storage/hostdb/batch.go +++ b/go/host/storage/hostdb/batch.go @@ -14,13 +14,13 @@ import ( ) const ( - selectBatch = "SELECT sequence, full_hash, hash, height, ext_batch FROM batch_host" + selectBatch = "SELECT sequence, hash, height, ext_batch FROM batch_host" selectExtBatch = "SELECT ext_batch FROM batch_host" - selectLatestBatch = "SELECT sequence, full_hash, hash, height, ext_batch FROM batch_host ORDER BY sequence DESC LIMIT 1" + selectLatestBatch = "SELECT sequence, hash, height, ext_batch FROM batch_host ORDER BY sequence DESC LIMIT 1" selectTxsAndBatch = "SELECT t.hash FROM transaction_host t JOIN batch_host b ON t.b_sequence = b.sequence WHERE b.hash = " selectBatchSeqByTx = "SELECT b_sequence FROM transaction_host WHERE hash = " - selectTxBySeq = "SELECT full_hash FROM transaction_host WHERE b_sequence = " - selectBatchTxs = "SELECT t.full_hash, b.sequence, b.height, b.ext_batch FROM transaction_host t JOIN batch_host b ON t.b_sequence = b.sequence" + selectTxBySeq = "SELECT hash FROM transaction_host WHERE b_sequence = " + selectBatchTxs = "SELECT t.hash, b.sequence, b.height, b.ext_batch FROM transaction_host t JOIN batch_host b ON t.b_sequence = b.sequence" ) // AddBatch adds a batch and its header to the DB @@ -33,7 +33,6 @@ func AddBatch(dbtx *dbTransaction, statements *SQLStatements, batch *common.ExtB _, err = dbtx.tx.Exec(statements.InsertBatch, batch.SeqNo().Uint64(), // sequence batch.Hash(), // full hash - truncTo16(batch.Hash()), // shortened hash batch.Header.Number.Uint64(), // height extBatch, // ext_batch ) @@ -45,11 +44,16 @@ func AddBatch(dbtx *dbTransaction, statements *SQLStatements, batch *common.ExtB } if len(batch.TxHashes) > 0 { - for _, txHash := range batch.TxHashes { - _, err = dbtx.tx.Exec(statements.InsertTransactions, truncTo16(txHash), txHash.Bytes(), batch.SeqNo().Uint64()) - if err != nil { - return fmt.Errorf("failed to insert transaction with hash: %d", err) - } + insert := statements.InsertTransactions + args := make([]any, 0) + for i, txHash := range batch.TxHashes { + insert += fmt.Sprintf(" (%s, %s),", statements.GetPlaceHolder(i*2+1), statements.GetPlaceHolder(i*2+2)) + args = append(args, txHash.Bytes(), batch.SeqNo().Uint64()) + } + insert = strings.TrimRight(insert, ",") + _, err = dbtx.tx.Exec(insert, args...) + if err != nil { + return fmt.Errorf("failed to insert transactions. cause: %w", err) } } @@ -60,7 +64,7 @@ func AddBatch(dbtx *dbTransaction, statements *SQLStatements, batch *common.ExtB } newTotal := currentTotal + len(batch.TxHashes) - _, err = dbtx.tx.Exec(statements.InsertTxCount, 1, newTotal) + _, err = dbtx.tx.Exec(statements.UpdateTxCount, newTotal) if err != nil { return fmt.Errorf("failed to update transaction count: %w", err) } @@ -170,7 +174,7 @@ func GetCurrentHeadBatch(db HostDB) (*common.PublicBatch, error) { // GetBatchHeader returns the batch header given the hash. func GetBatchHeader(db HostDB, hash gethcommon.Hash) (*common.BatchHeader, error) { whereQuery := " WHERE hash=" + db.GetSQLStatement().Placeholder - return fetchBatchHeader(db.GetSQLDB(), whereQuery, truncTo16(hash)) + return fetchBatchHeader(db.GetSQLDB(), whereQuery, hash.Bytes()) } // GetBatchHashByNumber returns the hash of a batch given its number. @@ -195,7 +199,7 @@ func GetHeadBatchHeader(db HostDB) (*common.BatchHeader, error) { // GetBatchNumber returns the height of the batch containing the given transaction hash. func GetBatchNumber(db HostDB, txHash gethcommon.Hash) (*big.Int, error) { - batchHeight, err := fetchBatchNumber(db, truncTo16(txHash)) + batchHeight, err := fetchBatchNumber(db, txHash.Bytes()) if err != nil { return nil, fmt.Errorf("failed to fetch batch height - %w", err) } @@ -205,7 +209,7 @@ func GetBatchNumber(db HostDB, txHash gethcommon.Hash) (*big.Int, error) { // GetBatchTxHashes returns the transaction hashes of the batch with the given hash. func GetBatchTxHashes(db HostDB, batchHash gethcommon.Hash) ([]gethcommon.Hash, error) { query := selectTxsAndBatch + db.GetSQLStatement().Placeholder - rows, err := db.GetSQLDB().Query(query, truncTo16(batchHash)) + rows, err := db.GetSQLDB().Query(query, batchHash.Bytes()) if err != nil { return nil, fmt.Errorf("query execution failed: %w", err) } @@ -231,14 +235,14 @@ func GetBatchTxHashes(db HostDB, batchHash gethcommon.Hash) ([]gethcommon.Hash, // GetPublicBatch returns the batch with the given hash. func GetPublicBatch(db HostDB, hash common.L2BatchHash) (*common.PublicBatch, error) { whereQuery := " WHERE b.hash=" + db.GetSQLStatement().Placeholder - return fetchPublicBatch(db.GetSQLDB(), whereQuery, truncTo16(hash)) + return fetchPublicBatch(db.GetSQLDB(), whereQuery, hash.Bytes()) } // GetBatchByTx returns the batch with the given hash. func GetBatchByTx(db HostDB, txHash gethcommon.Hash) (*common.ExtBatch, error) { var seqNo uint64 query := selectBatchSeqByTx + db.GetSQLStatement().Placeholder - err := db.GetSQLDB().QueryRow(query, truncTo16(txHash)).Scan(&seqNo) + err := db.GetSQLDB().QueryRow(query, txHash.Bytes()).Scan(&seqNo) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, errutil.ErrNotFound @@ -251,7 +255,7 @@ func GetBatchByTx(db HostDB, txHash gethcommon.Hash) (*common.ExtBatch, error) { // GetBatchByHash returns the batch with the given hash. func GetBatchByHash(db HostDB, hash common.L2BatchHash) (*common.ExtBatch, error) { whereQuery := " WHERE hash=" + db.GetSQLStatement().Placeholder - return fetchFullBatch(db.GetSQLDB(), whereQuery, truncTo16(hash)) + return fetchFullBatch(db.GetSQLDB(), whereQuery, hash.Bytes()) } // GetLatestBatch returns the head batch header @@ -278,7 +282,7 @@ func GetBatchByHeight(db HostDB, height *big.Int) (*common.PublicBatch, error) { // GetBatchTransactions returns the TransactionListingResponse for a given batch hash func GetBatchTransactions(db HostDB, batchHash gethcommon.Hash) (*common.TransactionListingResponse, error) { whereQuery := " WHERE b.hash=" + db.GetSQLStatement().Placeholder - return fetchBatchTxs(db.GetSQLDB(), whereQuery, truncTo16(batchHash)) + return fetchBatchTxs(db.GetSQLDB(), whereQuery, batchHash.Bytes()) } func fetchBatchHeader(db *sql.DB, whereQuery string, args ...any) (*common.BatchHeader, error) { @@ -330,7 +334,6 @@ func fetchBatchNumber(db HostDB, args ...any) (*big.Int, error) { func fetchPublicBatch(db *sql.DB, whereQuery string, args ...any) (*common.PublicBatch, error) { var sequenceInt64 uint64 var fullHash common.TxHash - var hash []byte var heightInt64 int var extBatch []byte @@ -338,9 +341,9 @@ func fetchPublicBatch(db *sql.DB, whereQuery string, args ...any) (*common.Publi var err error if len(args) > 0 { - err = db.QueryRow(query, args...).Scan(&sequenceInt64, &fullHash, &hash, &heightInt64, &extBatch) + err = db.QueryRow(query, args...).Scan(&sequenceInt64, &fullHash, &heightInt64, &extBatch) } else { - err = db.QueryRow(query).Scan(&sequenceInt64, &fullHash, &hash, &heightInt64, &extBatch) + err = db.QueryRow(query).Scan(&sequenceInt64, &fullHash, &heightInt64, &extBatch) } if err != nil { if errors.Is(err, sql.ErrNoRows) { @@ -356,7 +359,6 @@ func fetchPublicBatch(db *sql.DB, whereQuery string, args ...any) (*common.Publi batch := &common.PublicBatch{ SequencerOrderNo: new(big.Int).SetInt64(int64(sequenceInt64)), - Hash: bytesToHexString(hash), FullHash: fullHash, Height: new(big.Int).SetInt64(int64(heightInt64)), TxCount: new(big.Int).SetInt64(int64(len(b.TxHashes))), @@ -370,7 +372,6 @@ func fetchPublicBatch(db *sql.DB, whereQuery string, args ...any) (*common.Publi func fetchFullBatch(db *sql.DB, whereQuery string, args ...any) (*common.ExtBatch, error) { var sequenceInt64 uint64 var fullHash common.TxHash - var hash []byte var heightInt64 int var extBatch []byte @@ -378,9 +379,9 @@ func fetchFullBatch(db *sql.DB, whereQuery string, args ...any) (*common.ExtBatc var err error if len(args) > 0 { - err = db.QueryRow(query, args...).Scan(&sequenceInt64, &fullHash, &hash, &heightInt64, &extBatch) + err = db.QueryRow(query, args...).Scan(&sequenceInt64, &fullHash, &heightInt64, &extBatch) } else { - err = db.QueryRow(query).Scan(&sequenceInt64, &fullHash, &hash, &heightInt64, &extBatch) + err = db.QueryRow(query).Scan(&sequenceInt64, &fullHash, &heightInt64, &extBatch) } if err != nil { if errors.Is(err, sql.ErrNoRows) { @@ -400,11 +401,10 @@ func fetchFullBatch(db *sql.DB, whereQuery string, args ...any) (*common.ExtBatc func fetchHeadBatch(db *sql.DB) (*common.PublicBatch, error) { var sequenceInt64 int var fullHash gethcommon.Hash // common.Hash - var hash []byte var heightInt64 int var extBatch []byte - err := db.QueryRow(selectLatestBatch).Scan(&sequenceInt64, &fullHash, &hash, &heightInt64, &extBatch) + err := db.QueryRow(selectLatestBatch).Scan(&sequenceInt64, &fullHash, &heightInt64, &extBatch) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, errutil.ErrNotFound @@ -420,7 +420,6 @@ func fetchHeadBatch(db *sql.DB) (*common.PublicBatch, error) { batch := &common.PublicBatch{ SequencerOrderNo: new(big.Int).SetInt64(int64(sequenceInt64)), - Hash: bytesToHexString(hash), FullHash: fullHash, Height: new(big.Int).SetInt64(int64(heightInt64)), TxCount: new(big.Int).SetInt64(int64(len(b.TxHashes))), diff --git a/go/host/storage/hostdb/block.go b/go/host/storage/hostdb/block.go index 922551d9c5..96022e8f31 100644 --- a/go/host/storage/hostdb/block.go +++ b/go/host/storage/hostdb/block.go @@ -9,25 +9,19 @@ import ( ) const ( - selectBlocks = "SELECT id, hash, header, rollup_hash FROM block_host ORDER BY id DESC " + selectBlocks = "SELECT b.id, b.hash, b.header, r.hash FROM block_host b join rollup_host r on r.compression_block=b.id ORDER BY b.id DESC " ) // AddBlock stores a block header with the given rollupHash it contains in the host DB -func AddBlock(dbtx *dbTransaction, statements *SQLStatements, b *types.Header, rollupHash common.L2RollupHash) error { +func AddBlock(dbtx *dbTransaction, statements *SQLStatements, b *types.Header) error { header, err := rlp.EncodeToBytes(b) if err != nil { return fmt.Errorf("could not encode block header. Cause: %w", err) } - r, err := rlp.EncodeToBytes(rollupHash) - if err != nil { - return fmt.Errorf("could not encode rollup hash transactions: %w", err) - } - _, err = dbtx.tx.Exec(statements.InsertBlock, - b.Hash(), // hash - header, // l1 block header - r, // rollup hash + b.Hash().Bytes(), // hash + header, // l1 block header ) if err != nil { return fmt.Errorf("could not insert block. Cause: %w", err) @@ -60,9 +54,7 @@ func GetBlockListing(db HostDB, pagination *common.QueryPagination) (*common.Blo return nil, fmt.Errorf("could not decode block header. Cause: %w", err) } r := new(common.L2RollupHash) - if err := rlp.DecodeBytes(rollupHash, r); err != nil { - return nil, fmt.Errorf("could not decode rollup hash. Cause: %w", err) - } + r.SetBytes(rollupHash) block := common.PublicBlock{ BlockHeader: *blockHeader, RollupHash: *r, diff --git a/go/host/storage/hostdb/rollup.go b/go/host/storage/hostdb/rollup.go index a07edea92d..7b80057ddc 100644 --- a/go/host/storage/hostdb/rollup.go +++ b/go/host/storage/hostdb/rollup.go @@ -14,10 +14,10 @@ import ( ) const ( - selectExtRollup = "SELECT ext_rollup from rollup_host r" + selectExtRollup = "SELECT ext_rollup from rollup_host r join block_host b on r.compression_block=b.id " selectLatestRollup = "SELECT ext_rollup FROM rollup_host ORDER BY time_stamp DESC LIMIT 1" - selectRollupBatches = "SELECT b.sequence, b.hash, b.full_hash, b.height, b.ext_batch FROM rollup_host r JOIN batch_host b ON r.start_seq <= b.sequence AND r.end_seq >= b.sequence" - selectRollups = "SELECT id, hash, start_seq, end_seq, time_stamp, ext_rollup, compression_block FROM rollup_host" + selectRollupBatches = "SELECT b.sequence, b.hash, b.height, b.ext_batch FROM rollup_host r JOIN batch_host b ON r.start_seq <= b.sequence AND r.end_seq >= b.sequence" + selectRollups = "SELECT rh.id, rh.hash, rh.start_seq, rh.end_seq, rh.time_stamp, rh.ext_rollup, bh.hash FROM rollup_host rh join block_host bh on rh.compression_block=bh.id " ) // AddRollup adds a rollup to the DB @@ -27,13 +27,19 @@ func AddRollup(dbtx *dbTransaction, statements *SQLStatements, rollup *common.Ex return fmt.Errorf("could not encode rollup: %w", err) } + var blockId int + err = dbtx.tx.QueryRow("select id from block_host where hash="+statements.Placeholder, block.Hash().Bytes()).Scan(&blockId) + if err != nil { + return fmt.Errorf("could not read block id: %w", err) + } + _, err = dbtx.tx.Exec(statements.InsertRollup, - truncTo16(rollup.Header.Hash()), // short hash + rollup.Header.Hash().Bytes(), // hash metadata.FirstBatchSequence.Uint64(), // first batch sequence rollup.Header.LastBatchSeqNo, // last batch sequence metadata.StartTime, // timestamp extRollup, // rollup blob - block.Hash(), // l1 block hash + blockId, // l1 block hash ) if err != nil { return fmt.Errorf("could not insert rollup. Cause: %w", err) @@ -44,7 +50,7 @@ func AddRollup(dbtx *dbTransaction, statements *SQLStatements, rollup *common.Ex // GetRollupListing returns latest rollups given a pagination. // For example, offset 1, size 10 will return the latest 11-20 rollups. func GetRollupListing(db HostDB, pagination *common.QueryPagination) (*common.RollupListingResponse, error) { - orderQuery := " ORDER BY id DESC " + orderQuery := " ORDER BY rh.id DESC " query := selectRollups + orderQuery + db.GetSQLStatement().Pagination rows, err := db.GetSQLDB().Query(query, pagination.Size, pagination.Offset) @@ -92,18 +98,18 @@ func GetRollupListing(db HostDB, pagination *common.QueryPagination) (*common.Ro func GetExtRollup(db HostDB, hash gethcommon.Hash) (*common.ExtRollup, error) { whereQuery := " WHERE r.hash=" + db.GetSQLStatement().Placeholder - return fetchExtRollup(db.GetSQLDB(), whereQuery, truncTo16(hash)) + return fetchExtRollup(db.GetSQLDB(), whereQuery, hash.Bytes()) } // GetRollupHeader returns the rollup with the given hash. func GetRollupHeader(db HostDB, hash gethcommon.Hash) (*common.RollupHeader, error) { whereQuery := " WHERE r.hash=" + db.GetSQLStatement().Placeholder - return fetchRollupHeader(db.GetSQLDB(), whereQuery, truncTo16(hash)) + return fetchRollupHeader(db.GetSQLDB(), whereQuery, hash.Bytes()) } // GetRollupHeaderByBlock returns the rollup for the given block func GetRollupHeaderByBlock(db HostDB, blockHash gethcommon.Hash) (*common.RollupHeader, error) { - whereQuery := " WHERE r.compression_block=" + db.GetSQLStatement().Placeholder + whereQuery := " WHERE b.hash=" + db.GetSQLStatement().Placeholder return fetchRollupHeader(db.GetSQLDB(), whereQuery, blockHash) } @@ -117,8 +123,8 @@ func GetLatestRollup(db HostDB) (*common.RollupHeader, error) { } func GetRollupByHash(db HostDB, rollupHash gethcommon.Hash) (*common.PublicRollup, error) { - whereQuery := " WHERE hash=" + db.GetSQLStatement().Placeholder - return fetchPublicRollup(db.GetSQLDB(), whereQuery, truncTo16(rollupHash)) + whereQuery := " WHERE rh.hash=" + db.GetSQLStatement().Placeholder + return fetchPublicRollup(db.GetSQLDB(), whereQuery, rollupHash.Bytes()) } func GetRollupBySeqNo(db HostDB, seqNo uint64) (*common.PublicRollup, error) { @@ -130,7 +136,7 @@ func GetRollupBatches(db HostDB, rollupHash gethcommon.Hash) (*common.BatchListi whereQuery := " WHERE r.hash=" + db.GetSQLStatement().Placeholder orderQuery := " ORDER BY b.height DESC" query := selectRollupBatches + whereQuery + orderQuery - rows, err := db.GetSQLDB().Query(query, truncTo16(rollupHash)) + rows, err := db.GetSQLDB().Query(query, rollupHash.Bytes()) if err != nil { return nil, fmt.Errorf("query execution for select rollup batches failed: %w", err) } @@ -140,12 +146,11 @@ func GetRollupBatches(db HostDB, rollupHash gethcommon.Hash) (*common.BatchListi for rows.Next() { var ( sequenceInt64 int - hash []byte fullHash gethcommon.Hash heightInt64 int extBatch []byte ) - err := rows.Scan(&sequenceInt64, &hash, &fullHash, &heightInt64, &extBatch) + err := rows.Scan(&sequenceInt64, &fullHash, &heightInt64, &extBatch) if err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, errutil.ErrNotFound @@ -160,7 +165,6 @@ func GetRollupBatches(db HostDB, rollupHash gethcommon.Hash) (*common.BatchListi batch := common.PublicBatch{ SequencerOrderNo: new(big.Int).SetInt64(int64(sequenceInt64)), - Hash: bytesToHexString(hash), FullHash: fullHash, Height: new(big.Int).SetInt64(int64(heightInt64)), TxCount: new(big.Int).SetInt64(int64(len(b.TxHashes))), diff --git a/go/host/storage/hostdb/rollup_test.go b/go/host/storage/hostdb/rollup_test.go index b72b3254b8..b5320c6139 100644 --- a/go/host/storage/hostdb/rollup_test.go +++ b/go/host/storage/hostdb/rollup_test.go @@ -5,6 +5,8 @@ import ( "testing" "time" + "github.com/ethereum/go-ethereum/core/types" + gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ten-protocol/go-ten/go/common" @@ -18,9 +20,15 @@ func TestCanStoreAndRetrieveRollup(t *testing.T) { metadata := createRollupMetadata(batchNumber - 10) rollup := createRollup(batchNumber) - block := common.L1Block{} + block := types.NewBlock(&types.Header{}, nil, nil, nil, nil) dbtx, _ := db.NewDBTransaction() - err = AddRollup(dbtx, db.GetSQLStatement(), &rollup, &metadata, &block) + err = AddBlock(dbtx, db.GetSQLStatement(), block.Header()) + if err != nil { + t.Errorf("could not store block. Cause: %s", err) + } + dbtx.Write() + dbtx, _ = db.NewDBTransaction() + err = AddRollup(dbtx, db.GetSQLStatement(), &rollup, &metadata, block) if err != nil { t.Errorf("could not store rollup. Cause: %s", err) } @@ -52,9 +60,15 @@ func TestGetRollupByBlockHash(t *testing.T) { metadata := createRollupMetadata(batchNumber - 10) rollup := createRollup(batchNumber) - block := common.L1Block{} + block := types.NewBlock(&types.Header{}, nil, nil, nil, nil) dbtx, _ := db.NewDBTransaction() - err = AddRollup(dbtx, db.GetSQLStatement(), &rollup, &metadata, &block) + err = AddBlock(dbtx, db.GetSQLStatement(), block.Header()) + if err != nil { + t.Errorf("could not store block. Cause: %s", err) + } + dbtx.Write() + dbtx, _ = db.NewDBTransaction() + err = AddRollup(dbtx, db.GetSQLStatement(), &rollup, &metadata, block) if err != nil { t.Errorf("could not store rollup. Cause: %s", err) } @@ -78,9 +92,15 @@ func TestGetLatestRollup(t *testing.T) { rollup1LastSeq := int64(batchNumber) metadata1 := createRollupMetadata(rollup1FirstSeq) rollup1 := createRollup(rollup1LastSeq) - block := common.L1Block{} + block := types.NewBlock(&types.Header{}, nil, nil, nil, nil) dbtx, _ := db.NewDBTransaction() - err = AddRollup(dbtx, db.GetSQLStatement(), &rollup1, &metadata1, &block) + err = AddBlock(dbtx, db.GetSQLStatement(), block.Header()) + if err != nil { + t.Errorf("could not store block. Cause: %s", err) + } + dbtx.Write() + dbtx, _ = db.NewDBTransaction() + err = AddRollup(dbtx, db.GetSQLStatement(), &rollup1, &metadata1, block) if err != nil { t.Errorf("could not store rollup. Cause: %s", err) } @@ -91,7 +111,7 @@ func TestGetLatestRollup(t *testing.T) { rollup2LastSeq := int64(batchNumber + 10) metadata2 := createRollupMetadata(rollup2FirstSeq) rollup2 := createRollup(rollup2LastSeq) - err = AddRollup(dbtx, db.GetSQLStatement(), &rollup2, &metadata2, &block) + err = AddRollup(dbtx, db.GetSQLStatement(), &rollup2, &metadata2, block) if err != nil { t.Errorf("could not store rollup 2. Cause: %s", err) } @@ -117,9 +137,15 @@ func TestGetRollupBySeqNo(t *testing.T) { rollup1LastSeq := int64(batchNumber) metadata1 := createRollupMetadata(rollup1FirstSeq) rollup1 := createRollup(rollup1LastSeq) - block := common.L1Block{} + block := types.NewBlock(&types.Header{}, nil, nil, nil, nil) dbtx, _ := db.NewDBTransaction() - err = AddRollup(dbtx, db.GetSQLStatement(), &rollup1, &metadata1, &block) + err = AddBlock(dbtx, db.GetSQLStatement(), block.Header()) + if err != nil { + t.Errorf("could not store block. Cause: %s", err) + } + dbtx.Write() + dbtx, _ = db.NewDBTransaction() + err = AddRollup(dbtx, db.GetSQLStatement(), &rollup1, &metadata1, block) if err != nil { t.Errorf("could not store rollup. Cause: %s", err) } @@ -130,7 +156,7 @@ func TestGetRollupBySeqNo(t *testing.T) { rollup2LastSeq := int64(batchNumber + 10) // 787 metadata2 := createRollupMetadata(rollup2FirstSeq) rollup2 := createRollup(rollup2LastSeq) - err = AddRollup(dbtx, db.GetSQLStatement(), &rollup2, &metadata2, &block) + err = AddRollup(dbtx, db.GetSQLStatement(), &rollup2, &metadata2, block) if err != nil { t.Errorf("could not store rollup 2. Cause: %s", err) } @@ -166,9 +192,15 @@ func TestGetRollupListing(t *testing.T) { rollup1LastSeq := int64(batchNumber) metadata1 := createRollupMetadata(rollup1FirstSeq) rollup1 := createRollup(rollup1LastSeq) - block := common.L1Block{} + block := types.NewBlock(&types.Header{}, nil, nil, nil, nil) dbtx, _ := db.NewDBTransaction() - err = AddRollup(dbtx, db.GetSQLStatement(), &rollup1, &metadata1, &block) + err = AddBlock(dbtx, db.GetSQLStatement(), block.Header()) + if err != nil { + t.Errorf("could not store block. Cause: %s", err) + } + dbtx.Write() + dbtx, _ = db.NewDBTransaction() + err = AddRollup(dbtx, db.GetSQLStatement(), &rollup1, &metadata1, block) if err != nil { t.Errorf("could not store rollup. Cause: %s", err) } @@ -177,7 +209,7 @@ func TestGetRollupListing(t *testing.T) { rollup2LastSeq := int64(batchNumber + 10) metadata2 := createRollupMetadata(rollup2FirstSeq) rollup2 := createRollup(rollup2LastSeq) - err = AddRollup(dbtx, db.GetSQLStatement(), &rollup2, &metadata2, &block) + err = AddRollup(dbtx, db.GetSQLStatement(), &rollup2, &metadata2, block) if err != nil { t.Errorf("could not store rollup 2. Cause: %s", err) } @@ -186,7 +218,7 @@ func TestGetRollupListing(t *testing.T) { rollup3LastSeq := int64(batchNumber + 20) metadata3 := createRollupMetadata(rollup3FirstSeq) rollup3 := createRollup(rollup3LastSeq) - err = AddRollup(dbtx, db.GetSQLStatement(), &rollup3, &metadata3, &block) + err = AddRollup(dbtx, db.GetSQLStatement(), &rollup3, &metadata3, block) dbtx.Write() if err != nil { t.Errorf("could not store rollup 3. Cause: %s", err) @@ -263,9 +295,15 @@ func TestGetRollupByHash(t *testing.T) { rollup1LastSeq := int64(batchNumber) metadata1 := createRollupMetadata(rollup1FirstSeq) rollup1 := createRollup(rollup1LastSeq) - block := common.L1Block{} + block := types.NewBlock(&types.Header{}, nil, nil, nil, nil) dbtx, _ := db.NewDBTransaction() - err = AddRollup(dbtx, db.GetSQLStatement(), &rollup1, &metadata1, &block) + err = AddBlock(dbtx, db.GetSQLStatement(), block.Header()) + if err != nil { + t.Errorf("could not store block. Cause: %s", err) + } + dbtx.Write() + dbtx, _ = db.NewDBTransaction() + err = AddRollup(dbtx, db.GetSQLStatement(), &rollup1, &metadata1, block) if err != nil { t.Errorf("could not store rollup. Cause: %s", err) } @@ -274,7 +312,7 @@ func TestGetRollupByHash(t *testing.T) { rollup2LastSeq := int64(batchNumber + 10) metadata2 := createRollupMetadata(rollup2FirstSeq) rollup2 := createRollup(rollup2LastSeq) - err = AddRollup(dbtx, db.GetSQLStatement(), &rollup2, &metadata2, &block) + err = AddRollup(dbtx, db.GetSQLStatement(), &rollup2, &metadata2, block) if err != nil { t.Errorf("could not store rollup 2. Cause: %s", err) } @@ -298,8 +336,15 @@ func TestGetRollupBatches(t *testing.T) { db, _ := createSQLiteDB(t) txHashesOne := []common.L2TxHash{gethcommon.BytesToHash([]byte("magicStringOne")), gethcommon.BytesToHash([]byte("magicStringTwo"))} batchOne := createBatch(batchNumber, txHashesOne) + block := types.NewBlock(&types.Header{}, nil, nil, nil, nil) dbtx, _ := db.NewDBTransaction() - err := AddBatch(dbtx, db.GetSQLStatement(), &batchOne) + err := AddBlock(dbtx, db.GetSQLStatement(), block.Header()) + if err != nil { + t.Errorf("could not store block. Cause: %s", err) + } + dbtx.Write() + dbtx, _ = db.NewDBTransaction() + err = AddBatch(dbtx, db.GetSQLStatement(), &batchOne) if err != nil { t.Errorf("could not store batch. Cause: %s", err) } @@ -332,8 +377,7 @@ func TestGetRollupBatches(t *testing.T) { rollup1LastSeq := int64(batchNumber + 1) metadata1 := createRollupMetadata(rollup1FirstSeq) rollup1 := createRollup(rollup1LastSeq) - block := common.L1Block{} - err = AddRollup(dbtx, db.GetSQLStatement(), &rollup1, &metadata1, &block) + err = AddRollup(dbtx, db.GetSQLStatement(), &rollup1, &metadata1, block) if err != nil { t.Errorf("could not store rollup. Cause: %s", err) } @@ -342,7 +386,7 @@ func TestGetRollupBatches(t *testing.T) { rollup2LastSeq := int64(batchNumber + 3) metadata2 := createRollupMetadata(rollup2FirstSeq) rollup2 := createRollup(rollup2LastSeq) - err = AddRollup(dbtx, db.GetSQLStatement(), &rollup2, &metadata2, &block) + err = AddRollup(dbtx, db.GetSQLStatement(), &rollup2, &metadata2, block) if err != nil { t.Errorf("could not store rollup 2. Cause: %s", err) } diff --git a/go/host/storage/hostdb/sql_statements.go b/go/host/storage/hostdb/sql_statements.go index 9a7021c576..ccec07ef4d 100644 --- a/go/host/storage/hostdb/sql_statements.go +++ b/go/host/storage/hostdb/sql_statements.go @@ -1,23 +1,32 @@ package hostdb +import "strconv" + // SQLStatements struct holds SQL statements for a specific database type type SQLStatements struct { InsertBatch string InsertTransactions string - InsertTxCount string + UpdateTxCount string InsertRollup string InsertBlock string Pagination string Placeholder string } +func (s SQLStatements) GetPlaceHolder(pos int) string { + if s.Placeholder == "?" { + return s.Placeholder + } + return "$" + strconv.Itoa(pos) +} + func SQLiteSQLStatements() *SQLStatements { return &SQLStatements{ - InsertBatch: "INSERT INTO batch_host (sequence, full_hash, hash, height, ext_batch) VALUES (?, ?, ?, ?, ?)", - InsertTransactions: "REPLACE INTO transaction_host (hash, full_hash, b_sequence) VALUES (?, ?, ?)", - InsertTxCount: "INSERT INTO transaction_count (id, total) VALUES (?, ?) ON CONFLICT(id) DO UPDATE SET total = EXCLUDED.total", + InsertBatch: "INSERT INTO batch_host (sequence, hash, height, ext_batch) VALUES (?, ?, ?, ?)", + InsertTransactions: "INSERT INTO transaction_host (hash, b_sequence) VALUES ", + UpdateTxCount: "UPDATE transaction_count SET total=? WHERE id=1", InsertRollup: "INSERT INTO rollup_host (hash, start_seq, end_seq, time_stamp, ext_rollup, compression_block) values (?,?,?,?,?,?)", - InsertBlock: "REPLACE INTO block_host (hash, header, rollup_hash) values (?,?,?)", + InsertBlock: "INSERT INTO block_host (hash, header) values (?,?)", Pagination: "LIMIT ? OFFSET ?", Placeholder: "?", } @@ -25,11 +34,11 @@ func SQLiteSQLStatements() *SQLStatements { func PostgresSQLStatements() *SQLStatements { return &SQLStatements{ - InsertBatch: "INSERT INTO batch_host (sequence, full_hash, hash, height, ext_batch) VALUES ($1, $2, $3, $4, $5)", - InsertTransactions: "INSERT INTO transaction_host (hash, full_hash, b_sequence) VALUES ($1, $2, $3) ON CONFLICT (hash) DO NOTHING", - InsertTxCount: "INSERT INTO transaction_count (id, total) VALUES ($1, $2) ON CONFLICT (id) DO UPDATE SET total = EXCLUDED.total", + InsertBatch: "INSERT INTO batch_host (sequence, hash, height, ext_batch) VALUES ($1, $2, $3, $4)", + InsertTransactions: "INSERT INTO transaction_host (hash, b_sequence) VALUES ", + UpdateTxCount: "UPDATE transaction_count SET total=$1 WHERE id=1", InsertRollup: "INSERT INTO rollup_host (hash, start_seq, end_seq, time_stamp, ext_rollup, compression_block) values ($1, $2, $3, $4, $5, $6)", - InsertBlock: "INSERT INTO block_host (hash, header, rollup_hash) VALUES ($1, $2, $3) ON CONFLICT (hash) DO NOTHING", + InsertBlock: "INSERT INTO block_host (hash, header) VALUES ($1, $2)", Pagination: "LIMIT $1 OFFSET $2", Placeholder: "$1", } diff --git a/go/host/storage/hostdb/transaction.go b/go/host/storage/hostdb/transaction.go index 49a4b0507e..f2fb4c53a6 100644 --- a/go/host/storage/hostdb/transaction.go +++ b/go/host/storage/hostdb/transaction.go @@ -11,8 +11,8 @@ import ( const ( selectTxCount = "SELECT total FROM transaction_count WHERE id = 1" - selectTx = "SELECT full_hash, b_sequence FROM transaction_host WHERE hash = " - selectTxs = "SELECT t.full_hash, b.ext_batch FROM transaction_host t JOIN batch_host b ON t.b_sequence = b.sequence ORDER BY b.height DESC " + selectTx = "SELECT hash, b_sequence FROM transaction_host WHERE hash = " + selectTxs = "SELECT t.hash, b.ext_batch FROM transaction_host t JOIN batch_host b ON t.b_sequence = b.sequence ORDER BY b.height DESC " countTxs = "SELECT COUNT(b_sequence) AS row_count FROM transaction_host" ) @@ -63,7 +63,7 @@ func GetTransaction(db HostDB, hash gethcommon.Hash) (*common.PublicTransaction, var fullHash []byte var seq int - err := db.GetSQLDB().QueryRow(query, truncTo16(hash)).Scan(&fullHash, &seq) + err := db.GetSQLDB().QueryRow(query, hash.Bytes()).Scan(&fullHash, &seq) if err != nil { return nil, fmt.Errorf("failed to retrieve transaction sequence number: %w", err) } diff --git a/go/host/storage/hostdb/utils.go b/go/host/storage/hostdb/utils.go index c1e75150f0..b728031ad5 100644 --- a/go/host/storage/hostdb/utils.go +++ b/go/host/storage/hostdb/utils.go @@ -5,62 +5,12 @@ import ( "fmt" "testing" - gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ten-protocol/go-ten/go/host/storage/init/sqlite" ) -const truncHash = 16 - // An arbitrary number to put in the header const batchNumber = 777 -// truncTo16 checks if the leading half of the hash is filled with zeros and decides whether to truncate the first or last 16 bytes. -func truncTo16(hash gethcommon.Hash) []byte { - hashBytes := hash.Bytes() - // Check if the first half of the hash is all zeros - if isLeadingHalfZeros(hashBytes) { - return truncLastTo16(hashBytes) - } - return truncFirstTo16(hashBytes) -} - -// isLeadingHalfZeros checks if the leading half of the hash is all zeros. -func isLeadingHalfZeros(bytes []byte) bool { - halfLength := len(bytes) / 2 - for i := 0; i < halfLength; i++ { - if bytes[i] != 0 { - return false - } - } - return true -} - -// truncLastTo16 truncates the last 16 bytes of the hash. -func truncLastTo16(bytes []byte) []byte { - if len(bytes) == 0 { - return bytes - } - start := len(bytes) - truncHash - if start < 0 { - start = 0 - } - b := bytes[start:] - c := make([]byte, truncHash) - copy(c, b) - return c -} - -// truncFirstTo16 truncates the first 16 bytes of the hash. -func truncFirstTo16(bytes []byte) []byte { - if len(bytes) == 0 { - return bytes - } - b := bytes[0:truncHash] - c := make([]byte, truncHash) - copy(c, b) - return c -} - func createSQLiteDB(t *testing.T) (HostDB, error) { hostDB, err := sqlite.CreateTemporarySQLiteHostDB("", "mode=memory") if err != nil { diff --git a/go/host/storage/init/postgres/001_init.sql b/go/host/storage/init/postgres/001_init.sql index 87eece1b15..8f967f551a 100644 --- a/go/host/storage/init/postgres/001_init.sql +++ b/go/host/storage/init/postgres/001_init.sql @@ -1,9 +1,8 @@ CREATE TABLE IF NOT EXISTS block_host ( id SERIAL PRIMARY KEY, - hash BYTEA NOT NULL UNIQUE, - header BYTEA NOT NULL, - rollup_hash BYTEA NOT NULL + hash BYTEA NOT NULL, + header BYTEA NOT NULL ); CREATE INDEX IF NOT EXISTS IDX_BLOCK_HASH_HOST ON block_host USING HASH (hash); @@ -16,8 +15,9 @@ CREATE TABLE IF NOT EXISTS rollup_host end_seq INT NOT NULL, time_stamp INT NOT NULL, ext_rollup BYTEA NOT NULL, - compression_block BYTEA NOT NULL -); + compression_block INT NOT NULL, + FOREIGN KEY (compression_block) REFERENCES block_host(id) + ); CREATE INDEX IF NOT EXISTS IDX_ROLLUP_HASH_HOST ON rollup_host USING HASH (hash); CREATE INDEX IF NOT EXISTS IDX_ROLLUP_PROOF_HOST ON rollup_host (compression_block); @@ -26,8 +26,7 @@ CREATE INDEX IF NOT EXISTS IDX_ROLLUP_SEQ_HOST ON rollup_host (start_seq, end_se CREATE TABLE IF NOT EXISTS batch_host ( sequence INT PRIMARY KEY, - full_hash BYTEA NOT NULL, - hash BYTEA NOT NULL UNIQUE, + hash BYTEA NOT NULL , height INT NOT NULL, ext_batch BYTEA NOT NULL ); @@ -37,12 +36,13 @@ CREATE INDEX IF NOT EXISTS IDX_BATCH_HEIGHT_HOST ON batch_host (height); CREATE TABLE IF NOT EXISTS transaction_host ( - hash BYTEA PRIMARY KEY, - full_hash BYTEA NOT NULL UNIQUE, + id SERIAL PRIMARY KEY, + hash BYTEA, b_sequence INT, FOREIGN KEY (b_sequence) REFERENCES batch_host(sequence) ); +CREATE INDEX IF NOT EXISTS IDX_TX_HASH_HOST ON transaction_host USING HASH (hash); CREATE INDEX IF NOT EXISTS IDX_TX_SEQ_HOST ON transaction_host (b_sequence); CREATE TABLE IF NOT EXISTS transaction_count diff --git a/go/host/storage/init/sqlite/001_init.sql b/go/host/storage/init/sqlite/001_init.sql index c299176d58..371dad1d0a 100644 --- a/go/host/storage/init/sqlite/001_init.sql +++ b/go/host/storage/init/sqlite/001_init.sql @@ -2,8 +2,7 @@ create table if not exists block_host ( id INTEGER PRIMARY KEY AUTOINCREMENT, hash binary(32) NOT NULL UNIQUE, - header blob NOT NULL, - rollup_hash binary(32) NOT NULL + header blob NOT NULL ); create index IDX_BLOCK_HASH_HOST on block_host (hash); @@ -11,12 +10,12 @@ create index IDX_BLOCK_HASH_HOST on block_host (hash); create table if not exists rollup_host ( id INTEGER PRIMARY KEY AUTOINCREMENT, - hash binary(16) NOT NULL UNIQUE, + hash binary(32) NOT NULL UNIQUE, start_seq int NOT NULL, end_seq int NOT NULL, time_stamp int NOT NULL, ext_rollup blob NOT NULL, - compression_block binary(32) NOT NULL + compression_block int NOT NULL references block_host ); create index IDX_ROLLUP_HASH_HOST on rollup_host (hash); @@ -26,8 +25,7 @@ create index IDX_ROLLUP_SEQ_HOST on rollup_host (start_seq, end_seq); create table if not exists batch_host ( sequence int primary key, - full_hash binary(32) NOT NULL, - hash binary(16) NOT NULL UNIQUE, + hash binary(32) NOT NULL, height int NOT NULL, ext_batch mediumblob NOT NULL ); @@ -36,10 +34,11 @@ create index IDX_BATCH_HEIGHT_HOST on batch_host (height); create table if not exists transaction_host ( - hash binary(16) PRIMARY KEY, - full_hash binary(32) NOT NULL UNIQUE, + id int PRIMARY KEY, + hash binary(32) , b_sequence int REFERENCES batch_host ); +create index TX_HASH_HOST on transaction_host (hash); create table if not exists transaction_count ( diff --git a/go/host/storage/interfaces.go b/go/host/storage/interfaces.go index d7e229c36e..7abbf4fc9e 100644 --- a/go/host/storage/interfaces.go +++ b/go/host/storage/interfaces.go @@ -56,7 +56,7 @@ type BatchResolver interface { type BlockResolver interface { // AddBlock stores block data containing rollups in the host DB - AddBlock(b *types.Header, rollupHash common.L2RollupHash) error + AddBlock(b *types.Header) error // AddRollup stores a rollup in the host DB AddRollup(rollup *common.ExtRollup, metadata *common.PublicRollupMetadata, block *common.L1Block) error // FetchLatestRollupHeader returns the head `RollupHeader` diff --git a/go/host/storage/storage.go b/go/host/storage/storage.go index 6221993513..e1ac74b32b 100644 --- a/go/host/storage/storage.go +++ b/go/host/storage/storage.go @@ -75,13 +75,13 @@ func (s *storageImpl) AddRollup(rollup *common.ExtRollup, metadata *common.Publi return nil } -func (s *storageImpl) AddBlock(b *types.Header, rollupHash common.L2RollupHash) error { +func (s *storageImpl) AddBlock(b *types.Header) error { dbtx, err := s.db.NewDBTransaction() if err != nil { return err } - if err := hostdb.AddBlock(dbtx, s.db.GetSQLStatement(), b, rollupHash); err != nil { + if err := hostdb.AddBlock(dbtx, s.db.GetSQLStatement(), b); err != nil { if err := dbtx.Rollback(); err != nil { return err } From 0dc7d5c5f8525adba30abd1e0b52f0f94b89fb98 Mon Sep 17 00:00:00 2001 From: Stefan Iliev <46542846+StefanIliev545@users.noreply.github.com> Date: Thu, 27 Jun 2024 13:33:12 +0300 Subject: [PATCH 3/8] Fix for integration test. (#1971) Co-authored-by: StefanIliev545 --- contracts/generated/ManagementContract/ManagementContract.go | 2 +- contracts/src/management/ManagementContract.sol | 2 +- go/host/l1/statemachine.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/generated/ManagementContract/ManagementContract.go b/contracts/generated/ManagementContract/ManagementContract.go index 0ceda27945..03db3ed688 100644 --- a/contracts/generated/ManagementContract/ManagementContract.go +++ b/contracts/generated/ManagementContract/ManagementContract.go @@ -62,7 +62,7 @@ type StructsValueTransferMessage struct { // ManagementContractMetaData contains all meta data concerning the ManagementContract contract. var ManagementContractMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ECDSAInvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"ECDSAInvalidSignatureLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"ECDSAInvalidSignatureS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAddress\",\"type\":\"address\"}],\"name\":\"ImportantContractAddressUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"messageBusAddress\",\"type\":\"address\"}],\"name\":\"LogManagementContractCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"rollupHash\",\"type\":\"bytes32\"}],\"name\":\"RollupAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"enclaveID\",\"type\":\"address\"}],\"name\":\"SequencerEnclaveGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"enclaveID\",\"type\":\"address\"}],\"name\":\"SequencerEnclaveRevoked\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"Hash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"Signature\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"LastSequenceNumber\",\"type\":\"uint256\"}],\"internalType\":\"structStructs.MetaRollup\",\"name\":\"r\",\"type\":\"tuple\"},{\"internalType\":\"string\",\"name\":\"_rollupData\",\"type\":\"string\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"topic\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"consistencyLevel\",\"type\":\"uint8\"}],\"internalType\":\"structStructs.CrossChainMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"}],\"internalType\":\"structStructs.HeaderCrossChainData\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"AddRollup\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"Attested\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"sequence\",\"type\":\"uint64\"}],\"internalType\":\"structStructs.ValueTransferMessage\",\"name\":\"_msg\",\"type\":\"tuple\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"ExtractNativeValue\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"GetImportantContractKeys\",\"outputs\":[{\"internalType\":\"string[]\",\"name\":\"\",\"type\":\"string[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"rollupHash\",\"type\":\"bytes32\"}],\"name\":\"GetRollupByHash\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"Hash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"Signature\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"LastSequenceNumber\",\"type\":\"uint256\"}],\"internalType\":\"structStructs.MetaRollup\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"GetRollupByNumber\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"Hash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"Signature\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"LastSequenceNumber\",\"type\":\"uint256\"}],\"internalType\":\"structStructs.MetaRollup\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"}],\"name\":\"GetUniqueForkID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"Hash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"Signature\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"LastSequenceNumber\",\"type\":\"uint256\"}],\"internalType\":\"structStructs.MetaRollup\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"GrantSequencerEnclave\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_enclaveID\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_initSecret\",\"type\":\"bytes\"},{\"internalType\":\"string\",\"name\":\"_genesisAttestation\",\"type\":\"string\"}],\"name\":\"InitializeNetworkSecret\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"IsSequencerEnclave\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"IsWithdrawalAvailable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"requestReport\",\"type\":\"string\"}],\"name\":\"RequestNetworkSecret\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"attesterID\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"requesterID\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"attesterSig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"responseSecret\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"verifyAttester\",\"type\":\"bool\"}],\"name\":\"RespondNetworkSecret\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RetrieveAllBridgeFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"RevokeSequencerEnclave\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"newAddress\",\"type\":\"address\"}],\"name\":\"SetImportantContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_lastBatchHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"blockNum\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"crossChainHashes\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"rollupNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"forkID\",\"type\":\"bytes32\"}],\"name\":\"addCrossChainMessagesRoot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"importantContractAddresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"importantContractKeys\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"isWithdrawalSpent\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBatchHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBatchSeqNo\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleMessageBus\",\"outputs\":[{\"internalType\":\"contractIMerkleTreeMessageBus\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messageBus\",\"outputs\":[{\"internalType\":\"contractIMessageBus\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061001a3361001f565b610090565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6143a180620000a06000396000f3fe60806040523480156200001157600080fd5b5060043610620001e85760003560e01c8063715018a6116200010d578063a1a227fa11620000a3578063db5d91b1116200007a578063db5d91b1146200049c578063e34fbfc814620004cb578063e874eb2014620004e0578063f2fde38b14620004f457600080fd5b8063a1a227fa1462000460578063a52f433c1462000474578063d4fab887146200048557600080fd5b80638236a7ba11620000e45780638236a7ba14620003cb57806387059edb14620003f25780638da5cb5b146200040957806398077e86146200043a57600080fd5b8063715018a614620003ad5780637281099614620003b75780638129fc1c14620003c157600080fd5b8063440c953b1162000183578063568699c8116200015a578063568699c8146200033f57806368e1038314620003665780636a30d26c146200037d5780636b9707d6146200039657600080fd5b8063440c953b14620003075780634766573814620003115780635371a216146200032857600080fd5b80632c77c81f11620001c45780632c77c81f146200023a5780632f0cb9e314620002515780633e60a22f146200028857806343348b2f14620002d857600080fd5b80620ddd2714620001ed57806303e72e48146200020a578063073b6ef31462000223575b600080fd5b620001f7600d5481565b6040519081526020015b60405180910390f35b620002216200021b36600462001e27565b6200050b565b005b620002216200023436600462001ec7565b6200061e565b620002216200024b36600462001ffb565b62000909565b62000277620002623660046200209e565b600c6020526000908152604090205460ff1681565b604051901515815260200162000201565b620002bf62000299366004620020b8565b80516020818301810180516003825292820191909301209152546001600160a01b031681565b6040516001600160a01b03909116815260200162000201565b62000277620002e9366004620020f9565b6001600160a01b031660009081526020819052604090205460ff1690565b620001f760055481565b6200022162000322366004620020f9565b62000a79565b62000221620003393660046200211e565b62000b49565b62000356620003503660046200209e565b62000d52565b6040516200020192919062002241565b62000221620003773660046200225c565b62000dab565b6200038762000e98565b604051620002019190620022e6565b62000221620003a7366004620020f9565b62000f7b565b6200022162001041565b6200022162001059565b62000221620010dd565b620003e2620003dc3660046200209e565b620012c1565b604051620002019291906200234c565b620003e2620004033660046200209e565b620013b1565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b0316620002bf565b620004516200044b3660046200209e565b6200142b565b60405162000201919062002369565b600a54620002bf906001600160a01b031681565b600454610100900460ff1662000277565b62000221620004963660046200237e565b620014e0565b62000277620004ad366004620020f9565b6001600160a01b031660009081526001602052604090205460ff1690565b62000221620004dc36600462002429565b5050565b600b54620002bf906001600160a01b031681565b6200022162000505366004620020f9565b62001673565b62000515620016d0565b60006001600160a01b03166003836040516200053291906200246f565b908152604051908190036020019020546001600160a01b0316036200059157600280546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace016200058f83826200251c565b505b80600383604051620005a491906200246f565b90815260405190819003602001812080546001600160a01b039390931673ffffffffffffffffffffffffffffffffffffffff19909316929092179091557f17b2f9f5748931099ffee882b5b64f4a560b5c55da9b4f4e396dae3bb9f98cb590620006129084908490620025e9565b60405180910390a15050565b6200062b8660ff6200262c565b431115620006805760405162461bcd60e51b815260206004820152601560248201527f426c6f636b2062696e64696e6720746f6f206f6c64000000000000000000000060448201526064015b60405180910390fd5b86864014620006e757620006944362001747565b6200069f8862001747565b620006ab884062001747565b604051602001620006bf9392919062002642565b60408051601f198184030181529082905262461bcd60e51b8252620006779160040162002369565b6000828152600860205260409020548114620007465760405162461bcd60e51b815260206004820152600e60248201527f496e76616c696420666f726b4944000000000000000000000000000000000000604482015260640162000677565b6000620007b889898989604051602001620007659493929190620026e7565b6040516020818303038152906040528051906020012086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620017ee92505050565b6001600160a01b03811660009081526020819052604090205490915060ff16620008255760405162461bcd60e51b815260206004820152601660248201527f656e636c6176654944206e6f7420617474657374656400000000000000000000604482015260640162000677565b600d89905560005b8651811015620008fd57600b5487516001600160a01b039091169063b6aed0cb9089908490811062000863576200086362002763565b6020026020010151620008769062002779565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526004810191909152426024820152604401600060405180830381600087803b158015620008ce57600080fd5b505af1158015620008e3573d6000803e3d6000fd5b505050508080620008f4906200279e565b9150506200082d565b50505050505050505050565b60006200095b8535620009206020880188620027ba565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620017ee92505050565b6001600160a01b03811660009081526020819052604090205490915060ff16620009c85760405162461bcd60e51b815260206004820152601660248201527f656e636c6176654944206e6f7420617474657374656400000000000000000000604482015260640162000677565b6001600160a01b03811660009081526001602052604090205460ff1662000a325760405162461bcd60e51b815260206004820152601960248201527f656e636c6176654944206e6f7420612073657175656e63657200000000000000604482015260640162000677565b62000a3d856200181e565b604051853581527fd6555bff8670bd3008dc064c30bb56d6ac7cb14ae801e36146fe4e7c6a504a58906020015b60405180910390a15050505050565b62000a83620016d0565b6001600160a01b03811660009081526020819052604090205460ff1662000aed5760405162461bcd60e51b815260206004820152601660248201527f656e636c6176654944206e6f7420617474657374656400000000000000000000604482015260640162000677565b6001600160a01b038116600081815260016020818152604092839020805460ff191690921790915590519182527ffe64c7181f0fc60e300dc02cca368cdfa94d7ca45902de3b9a9d80070e76093691015b60405180910390a150565b600b546040517fb201246f0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063b201246f9062000b9a90879087908790879060040162002864565b60006040518083038186803b15801562000bb357600080fd5b505afa15801562000bc8573d6000803e3d6000fd5b5050505060008460405160200162000be19190620028cc565b60408051601f1981840301815291815281516020928301206000818152600c90935291205490915060ff161562000c5b5760405162461bcd60e51b815260206004820152601860248201527f7769746864726177616c20616c7265616479207370656e740000000000000000604482015260640162000677565b6001600c60008760405160200162000c749190620028cc565b60408051808303601f190181529181528151602092830120835282820193909352908201600020805460ff191693151593909317909255600a546001600160a01b0316916399a3ad219162000ccf91908901908901620020f9565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b0390921660048301528801356024820152604401600060405180830381600087803b15801562000d3257600080fd5b505af115801562000d47573d6000803e3d6000fd5b505050505050505050565b60408051606080820183526000808352602083019190915291810182905260008062000d7e85620013b1565b915091508162000d945760009590945092505050565b600094855260086020526040909420549492505050565b60045460ff161562000e265760405162461bcd60e51b815260206004820152602260248201527f6e6574776f726b2073656372657420616c726561647920696e697469616c697a60448201527f6564000000000000000000000000000000000000000000000000000000000000606482015260840162000677565b60048054600160ff1991821681179092556001600160a01b038716600081815260208181526040808320805486168717905585825291829020805490941690941790925590519081527ffe64c7181f0fc60e300dc02cca368cdfa94d7ca45902de3b9a9d80070e760936910162000a6a565b60606002805480602002602001604051908101604052809291908181526020016000905b8282101562000f7257838290600052602060002001805462000ede906200248d565b80601f016020809104026020016040519081016040528092919081815260200182805462000f0c906200248d565b801562000f5d5780601f1062000f315761010080835404028352916020019162000f5d565b820191906000526020600020905b81548152906001019060200180831162000f3f57829003601f168201915b50505050508152602001906001019062000ebc565b50505050905090565b62000f85620016d0565b6001600160a01b03811660009081526001602052604090205460ff1662000fef5760405162461bcd60e51b815260206004820152601960248201527f656e636c6176654944206e6f7420612073657175656e63657200000000000000604482015260640162000677565b6001600160a01b038116600081815260016020908152604091829020805460ff1916905590519182527f0f279980343c7ca542fde9fa5396555068efb5cd560d9cf9c191aa2911079b47910162000b3e565b6200104b620016d0565b620010576000620018d3565b565b62001063620016d0565b600a546040517f36d2da900000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03909116906336d2da9090602401600060405180830381600087803b158015620010c257600080fd5b505af1158015620010d7573d6000803e3d6000fd5b50505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015620011295750825b905060008267ffffffffffffffff166001148015620011475750303b155b90508115801562001156575080155b156200118e576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff191660011785558315620011c357845468ff00000000000000001916680100000000000000001785555b620011ce3362001951565b60006005819055600955604051620011e69062001d3b565b604051809103906000f08015801562001203573d6000803e3d6000fd5b50600b805473ffffffffffffffffffffffffffffffffffffffff199081166001600160a01b0393909316928317909155600a8054909116821790556040519081527fbd726cf82ac9c3260b1495107182e336e0654b25c10915648c0cc15b2bb72cbf9060200160405180910390a18315620012ba57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200162000a6a565b5050505050565b60408051606080820183526000808352602080840183905283850182905285825260068152848220855193840190955284548352600185018054929586949390928401919062001311906200248d565b80601f01602080910402602001604051908101604052809291908181526020018280546200133f906200248d565b8015620013905780601f10620013645761010080835404028352916020019162001390565b820191906000526020600020905b8154815290600101906020018083116200137257829003601f168201915b50505091835250506002919091015460209091015280519094149492505050565b604080516060808201835260008083526020830191909152918101829052600083815260076020526040812054908190036200141657505060408051606081018252600080825282516020818101855282825283015291810182905290939092509050565b6200142181620012c1565b9250925050915091565b600281815481106200143c57600080fd5b90600052602060002001600091509050805462001459906200248d565b80601f016020809104026020016040519081016040528092919081815260200182805462001487906200248d565b8015620014d85780601f10620014ac57610100808354040283529160200191620014d8565b820191906000526020600020905b815481529060010190602001808311620014ba57829003601f168201915b505050505081565b6001600160a01b03851660009081526020819052604090205460ff1680620015715760405162461bcd60e51b815260206004820152602360248201527f726573706f6e64696e67206174746573746572206973206e6f7420617474657360448201527f7465640000000000000000000000000000000000000000000000000000000000606482015260840162000677565b811562001648576000620015aa8787866040516020016200159593929190620028dc565b60405160208183030381529060405262001966565b90506000620015ba8287620017ee565b9050876001600160a01b0316816001600160a01b031614620016455760405162461bcd60e51b815260206004820152602c60248201527f63616c63756c61746564206164647265737320616e642061747465737465724960448201527f4420646f6e74206d617463680000000000000000000000000000000000000000606482015260840162000677565b50505b5050506001600160a01b039091166000908152602081905260409020805460ff191660011790555050565b6200167d620016d0565b6001600160a01b038116620016c2576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526000600482015260240162000677565b620016cd81620018d3565b50565b33620017037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03161462001057576040517f118cdaa700000000000000000000000000000000000000000000000000000000815233600482015260240162000677565b606060006200175683620019a5565b600101905060008167ffffffffffffffff81111562001779576200177962001d49565b6040519080825280601f01601f191660200182016040528015620017a4576020820181803683370190505b5090508181016020015b600019017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8504945084620017ae57509392505050565b60008060008062001800868662001a8e565b92509250925062001812828262001adf565b50909150505b92915050565b8035600090815260066020526040902081906200183c828262002924565b505060095460009081526007602052604090208135908190556200186260014362002a34565b406040516020016200187e929190918252602082015260400190565b60408051601f198184030181529181528151602092830120600980546000908152600890945291832055805491620018b6836200279e565b919050555060055481604001351115620016cd5760400135600555565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6200195b62001bf5565b620016cd8162001c5d565b600062001974825162001747565b826040516020016200198892919062002a4a565b604051602081830303815290604052805190602001209050919050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310620019ef577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef8100000000831062001a1c576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831062001a3b57662386f26fc10000830492506010015b6305f5e100831062001a54576305f5e100830492506008015b612710831062001a6957612710830492506004015b6064831062001a7c576064830492506002015b600a8310620018185760010192915050565b6000806000835160410362001acc5760208401516040850151606086015160001a62001abd8882858562001c67565b95509550955050505062001ad8565b50508151600091506002905b9250925092565b600082600381111562001af65762001af662002aa9565b0362001b00575050565b600182600381111562001b175762001b1762002aa9565b0362001b4f576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600282600381111562001b665762001b6662002aa9565b0362001ba2576040517ffce698f70000000000000000000000000000000000000000000000000000000081526004810182905260240162000677565b600382600381111562001bb95762001bb962002aa9565b03620004dc576040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004810182905260240162000677565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1662001057576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200167d62001bf5565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111562001ca4575060009150600390508262001d31565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801562001cf9573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811662001d275750600092506001915082905062001d31565b9250600091508190505b9450945094915050565b6118ac8062002ac083390190565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171562001d8b5762001d8b62001d49565b604052919050565b600082601f83011262001da557600080fd5b813567ffffffffffffffff81111562001dc25762001dc262001d49565b62001dd7601f8201601f191660200162001d5f565b81815284602083860101111562001ded57600080fd5b816020850160208301376000918101602001919091529392505050565b80356001600160a01b038116811462001e2257600080fd5b919050565b6000806040838503121562001e3b57600080fd5b823567ffffffffffffffff81111562001e5357600080fd5b62001e618582860162001d93565b92505062001e726020840162001e0a565b90509250929050565b60008083601f84011262001e8e57600080fd5b50813567ffffffffffffffff81111562001ea757600080fd5b60208301915083602082850101111562001ec057600080fd5b9250929050565b60008060008060008060008060e0898b03121562001ee457600080fd5b88359750602089013596506040890135955067ffffffffffffffff8060608b0135111562001f1157600080fd5b60608a01358a018b601f82011262001f2857600080fd5b818135111562001f3c5762001f3c62001d49565b62001f4e6020823560051b0162001d5f565b81358082526020808301929160051b8401018e101562001f6d57600080fd5b602083015b6020843560051b85010181101562001fb457848135111562001f9357600080fd5b62001fa58f6020833587010162001d93565b83526020928301920162001f72565b509750505060808a013581101562001fcb57600080fd5b5062001fde8a60808b01358b0162001e7b565b989b979a5095989497959660a08601359560c00135945092505050565b600080600080606085870312156200201257600080fd5b843567ffffffffffffffff808211156200202b57600080fd5b90860190606082890312156200204057600080fd5b909450602086013590808211156200205757600080fd5b620020658883890162001e7b565b909550935060408701359150808211156200207f57600080fd5b508501602081880312156200209357600080fd5b939692955090935050565b600060208284031215620020b157600080fd5b5035919050565b600060208284031215620020cb57600080fd5b813567ffffffffffffffff811115620020e357600080fd5b620020f18482850162001d93565b949350505050565b6000602082840312156200210c57600080fd5b620021178262001e0a565b9392505050565b60008060008084860360c08112156200213657600080fd5b60808112156200214557600080fd5b50849350608085013567ffffffffffffffff808211156200216557600080fd5b818701915087601f8301126200217a57600080fd5b8135818111156200218a57600080fd5b8860208260051b8501011115620021a057600080fd5b95986020929092019750949560a00135945092505050565b60005b83811015620021d5578181015183820152602001620021bb565b50506000910152565b60008151808452620021f8816020860160208601620021b8565b601f01601f19169290920160200192915050565b8051825260006020820151606060208501526200222d6060850182620021de565b604093840151949093019390935250919050565b828152604060208201526000620020f160408301846200220c565b6000806000806000606086880312156200227557600080fd5b620022808662001e0a565b9450602086013567ffffffffffffffff808211156200229e57600080fd5b620022ac89838a0162001e7b565b90965094506040880135915080821115620022c657600080fd5b50620022d58882890162001e7b565b969995985093965092949392505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156200233f57603f198886030184526200232c858351620021de565b945092850192908501906001016200230d565b5092979650505050505050565b8215158152604060208201526000620020f160408301846200220c565b602081526000620021176020830184620021de565b600080600080600060a086880312156200239757600080fd5b620023a28662001e0a565b9450620023b26020870162001e0a565b9350604086013567ffffffffffffffff80821115620023d057600080fd5b620023de89838a0162001d93565b94506060880135915080821115620023f557600080fd5b50620024048882890162001d93565b925050608086013580151581146200241b57600080fd5b809150509295509295909350565b600080602083850312156200243d57600080fd5b823567ffffffffffffffff8111156200245557600080fd5b620024638582860162001e7b565b90969095509350505050565b6000825162002483818460208701620021b8565b9190910192915050565b600181811c90821680620024a257607f821691505b602082108103620024c357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200251757600081815260208120601f850160051c81016020861015620024f25750805b601f850160051c820191505b818110156200251357828155600101620024fe565b5050505b505050565b815167ffffffffffffffff81111562002539576200253962001d49565b62002551816200254a84546200248d565b84620024c9565b602080601f831160018114620025895760008415620025705750858301515b600019600386901b1c1916600185901b17855562002513565b600085815260208120601f198616915b82811015620025ba5788860151825594840194600190910190840162002599565b5085821015620025d95787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b604081526000620025fe6040830185620021de565b90506001600160a01b03831660208301529392505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111562001818576200181862002616565b7f496e76616c696420626c6f636b2062696e64696e673a000000000000000000008152600084516200267c816016850160208901620021b8565b80830190507f3a000000000000000000000000000000000000000000000000000000000000008060168301528551620026bd816017850160208a01620021b8565b60179201918201528351620026da816018840160208801620021b8565b0160180195945050505050565b600060808201868352602086818501528560408501526080606085015281855180845260a08601915060a08160051b870101935082870160005b828110156200275357609f1988870301845262002740868351620021de565b9550928401929084019060010162002721565b50939a9950505050505050505050565b634e487b7160e01b600052603260045260246000fd5b80516020808301519190811015620024c35760001960209190910360031b1b16919050565b600060018201620027b357620027b362002616565b5060010190565b6000808335601e19843603018112620027d257600080fd5b83018035915067ffffffffffffffff821115620027ee57600080fd5b60200191503681900382131562001ec057600080fd5b6001600160a01b0380620028188362001e0a565b168352806200282a6020840162001e0a565b1660208401525060408101356040830152606081013567ffffffffffffffff81168082146200285857600080fd5b80606085015250505050565b62002870818662002804565b60c060808201528260c082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841115620028ad57600080fd5b8360051b808660e085013760a0830193909352500160e0019392505050565b6080810162001818828462002804565b60006bffffffffffffffffffffffff19808660601b168352808560601b16601484015250825162002915816028850160208701620021b8565b91909101602801949350505050565b813581556001808201602080850135601e198636030181126200294657600080fd5b8501803567ffffffffffffffff8111156200296057600080fd5b80360383830113156200297257600080fd5b6200298a816200298386546200248d565b86620024c9565b6000601f821160018114620029c35760008315620029aa57508382018501355b600019600385901b1c1916600184901b17865562002a1f565b600086815260209020601f19841690835b82811015620029f557868501880135825593870193908901908701620029d4565b508482101562002a155760001960f88660031b161c198785880101351681555b50508683881b0186555b50505050505050604082013560028201555050565b8181038181111562001818576200181862002616565b7f19457468657265756d205369676e6564204d6573736167653a0a00000000000081526000835162002a8481601a850160208801620021b8565b83519083019062002a9d81601a840160208801620021b8565b01601a01949350505050565b634e487b7160e01b600052602160045260246000fdfe608060405234801561001057600080fd5b50338061003757604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61004081610046565b50610096565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611807806100a56000396000f3fe6080604052600436106100e15760003560e01c80639730886d1161007f578063b201246f11610059578063b201246f1461030e578063b6aed0cb1461032e578063e138a8d21461034e578063f2fde38b1461036e57610155565b80639730886d1461029557806399a3ad21146102b5578063b1454caa146102d557610155565b8063346633fb116100bb578063346633fb1461022557806336d2da9014610238578063715018a6146102585780638da5cb5b1461026d57610155565b80630fcfbd11146101a25780630fe9188e146101d557806333a88c72146101f557610155565b36610155576040517f346633fb0000000000000000000000000000000000000000000000000000000081523360048201523460248201819052309163346633fb91906044016000604051808303818588803b15801561013f57600080fd5b505af1158015610153573d6000803e3d6000fd5b005b60405162461bcd60e51b815260206004820152600b60248201527f756e737570706f7274656400000000000000000000000000000000000000000060448201526064015b60405180910390fd5b3480156101ae57600080fd5b506101c26101bd366004610f80565b61038e565b6040519081526020015b60405180910390f35b3480156101e157600080fd5b506101536101f0366004610fb5565b610428565b34801561020157600080fd5b50610215610210366004610f80565b61049e565b60405190151581526020016101cc565b610153610233366004610fe3565b6104f1565b34801561024457600080fd5b5061015361025336600461100f565b6105d4565b34801561026457600080fd5b50610153610683565b34801561027957600080fd5b506000546040516001600160a01b0390911681526020016101cc565b3480156102a157600080fd5b506101536102b036600461102c565b610697565b3480156102c157600080fd5b506101536102d0366004610fe3565b6107e9565b3480156102e157600080fd5b506102f56102f03660046110a2565b610899565b60405167ffffffffffffffff90911681526020016101cc565b34801561031a57600080fd5b5061015361032936600461119b565b6108fa565b34801561033a57600080fd5b506101536103493660046111fd565b610afc565b34801561035a57600080fd5b5061015361036936600461121f565b610b98565b34801561037a57600080fd5b5061015361038936600461100f565b610d78565b600080826040516020016103a291906112ce565b60408051601f19818403018152918152815160209283012060008181526001909352912054909150806104215760405162461bcd60e51b815260206004820152602160248201527f54686973206d65737361676520776173206e65766572207375626d69747465646044820152601760f91b6064820152608401610199565b9392505050565b610430610dcf565b600081815260046020526040812054900361048d5760405162461bcd60e51b815260206004820152601a60248201527f537461746520726f6f7420646f6573206e6f742065786973742e0000000000006044820152606401610199565b600090815260046020526040812055565b600080826040516020016104b291906112ce565b60408051601f1981840301815291815281516020928301206000818152600190935291205490915080158015906104e95750428111155b949350505050565b60003411801561050057508034145b6105725760405162461bcd60e51b815260206004820152603060248201527f417474656d7074696e6720746f2073656e642076616c756520776974686f757460448201527f2070726f766964696e67204574686572000000000000000000000000000000006064820152608401610199565b600061057d33610e15565b6040805134815267ffffffffffffffff831660208201529192506001600160a01b0385169133917f50c536ac33a920f00755865b831d17bf4cff0b2e0345f65b16d52bfc004068b6910160405180910390a3505050565b6105dc610dcf565b6000816001600160a01b03164760405160006040518083038185875af1925050503d8060008114610629576040519150601f19603f3d011682016040523d82523d6000602084013e61062e565b606091505b505090508061067f5760405162461bcd60e51b815260206004820152601460248201527f6661696c65642073656e64696e672076616c75650000000000000000000000006044820152606401610199565b5050565b61068b610dcf565b6106956000610e73565b565b61069f610dcf565b60006106ab82426113cf565b90506000836040516020016106c091906112ce565b60408051601f198184030181529181528151602092830120600081815260019093529120549091501561075b5760405162461bcd60e51b815260206004820152602160248201527f4d657373616765207375626d6974746564206d6f7265207468616e206f6e636560448201527f21000000000000000000000000000000000000000000000000000000000000006064820152608401610199565b600081815260016020908152604082208490556002919061077e9087018761100f565b6001600160a01b0316815260208101919091526040016000908120906107aa60808701606088016113e2565b63ffffffff168152602080820192909252604001600090812080546001810182559082529190208591600402016107e182826115b0565b505050505050565b6107f1610dcf565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461083e576040519150601f19603f3d011682016040523d82523d6000602084013e610843565b606091505b50509050806108945760405162461bcd60e51b815260206004820152601460248201527f6661696c65642073656e64696e672076616c75650000000000000000000000006044820152606401610199565b505050565b60006108a433610e15565b9050336001600160a01b03167fb93c37389233beb85a3a726c3f15c2d15533ee74cb602f20f490dfffef7759378288888888886040516108e9969594939291906116ca565b60405180910390a295945050505050565b600081815260046020526040812054900361096a5760405162461bcd60e51b815260206004820152602a60248201527f526f6f74206973206e6f74207075626c6973686564206f6e2074686973206d6560448201526939b9b0b3b290313ab99760b11b6064820152608401610199565b6000818152600460205260409020544210156109d25760405162461bcd60e51b815260206004820152602160248201527f526f6f74206973206e6f7420636f6e736964657265642066696e616c207965746044820152601760f91b6064820152608401610199565b6000846040516020016109e5919061171a565b60408051601f198184030181528282528051602091820120908301829052600160608401527f760000000000000000000000000000000000000000000000000000000000000060808401529082015260a001604051602081830303815290604052805190602001209050610a8384848484604051602001610a6891815260200190565b60405160208183030381529060405280519060200120610ed0565b610af55760405162461bcd60e51b815260206004820152603360248201527f496e76616c696420696e636c7573696f6e2070726f6f6620666f722076616c7560448201527f65207472616e73666572206d6573736167652e000000000000000000000000006064820152608401610199565b5050505050565b610b04610dcf565b60008281526004602052604090205415610b865760405162461bcd60e51b815260206004820152602560248201527f526f6f7420616c726561647920616464656420746f20746865206d657373616760448201527f65206275730000000000000000000000000000000000000000000000000000006064820152608401610199565b60009182526004602052604090912055565b6000818152600460205260408120549003610c085760405162461bcd60e51b815260206004820152602a60248201527f526f6f74206973206e6f74207075626c6973686564206f6e2074686973206d6560448201526939b9b0b3b290313ab99760b11b6064820152608401610199565b600081815260046020526040902054421015610c705760405162461bcd60e51b815260206004820152602160248201527f526f6f74206973206e6f7420636f6e736964657265642066696e616c207965746044820152601760f91b6064820152608401610199565b600084604051602001610c8391906112ce565b60408051601f198184030181528282528051602091820120908301829052600160608401527f6d0000000000000000000000000000000000000000000000000000000000000060808401529082015260a001604051602081830303815290604052805190602001209050610d0684848484604051602001610a6891815260200190565b610af55760405162461bcd60e51b815260206004820152603060248201527f496e76616c696420696e636c7573696f6e2070726f6f6620666f722063726f7360448201527f7320636861696e206d6573736167652e000000000000000000000000000000006064820152608401610199565b610d80610dcf565b6001600160a01b038116610dc3576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610199565b610dcc81610e73565b50565b6000546001600160a01b03163314610695576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610199565b6001600160a01b0381166000908152600360205260408120805467ffffffffffffffff169160019190610e48838561177a565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550919050565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600082610ede868685610ee8565b1495945050505050565b600081815b84811015610f2b57610f1782878784818110610f0b57610f0b6117a2565b90506020020135610f34565b915080610f23816117b8565b915050610eed565b50949350505050565b6000818310610f50576000828152602084905260409020610f5f565b60008381526020839052604090205b90505b92915050565b600060c08284031215610f7a57600080fd5b50919050565b600060208284031215610f9257600080fd5b813567ffffffffffffffff811115610fa957600080fd5b6104e984828501610f68565b600060208284031215610fc757600080fd5b5035919050565b6001600160a01b0381168114610dcc57600080fd5b60008060408385031215610ff657600080fd5b823561100181610fce565b946020939093013593505050565b60006020828403121561102157600080fd5b813561042181610fce565b6000806040838503121561103f57600080fd5b823567ffffffffffffffff81111561105657600080fd5b61106285828601610f68565b95602094909401359450505050565b63ffffffff81168114610dcc57600080fd5b60ff81168114610dcc57600080fd5b803561109d81611083565b919050565b6000806000806000608086880312156110ba57600080fd5b85356110c581611071565b945060208601356110d581611071565b9350604086013567ffffffffffffffff808211156110f257600080fd5b818801915088601f83011261110657600080fd5b81358181111561111557600080fd5b89602082850101111561112757600080fd5b602083019550809450505050606086013561114181611083565b809150509295509295909350565b60008083601f84011261116157600080fd5b50813567ffffffffffffffff81111561117957600080fd5b6020830191508360208260051b850101111561119457600080fd5b9250929050565b60008060008084860360c08112156111b257600080fd5b60808112156111c057600080fd5b50849350608085013567ffffffffffffffff8111156111de57600080fd5b6111ea8782880161114f565b9598909750949560a00135949350505050565b6000806040838503121561121057600080fd5b50508035926020909101359150565b6000806000806060858703121561123557600080fd5b843567ffffffffffffffff8082111561124d57600080fd5b61125988838901610f68565b9550602087013591508082111561126f57600080fd5b5061127c8782880161114f565b9598909750949560400135949350505050565b67ffffffffffffffff81168114610dcc57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152600082356112df81610fce565b6001600160a01b03811660208401525060208301356112fd8161128f565b67ffffffffffffffff80821660408501526040850135915061131e82611071565b63ffffffff80831660608601526060860135925061133b83611071565b80831660808601525060808501359150601e1985360301821261135d57600080fd5b602091850191820191358181111561137457600080fd5b80360383131561138357600080fd5b60c060a086015261139860e0860182856112a5565b925050506113a860a08501611092565b60ff811660c0850152509392505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610f6257610f626113b9565b6000602082840312156113f457600080fd5b813561042181611071565b60008135610f6281611071565b6000808335601e1984360301811261142357600080fd5b83018035915067ffffffffffffffff82111561143e57600080fd5b60200191503681900382131561119457600080fd5b634e487b7160e01b600052604160045260246000fd5b600181811c9082168061147d57607f821691505b602082108103610f7a57634e487b7160e01b600052602260045260246000fd5b601f82111561089457600081815260208120601f850160051c810160208610156114c45750805b601f850160051c820191505b818110156107e1578281556001016114d0565b67ffffffffffffffff8311156114fb576114fb611453565b61150f836115098354611469565b8361149d565b6000601f841160018114611543576000851561152b5750838201355b600019600387901b1c1916600186901b178355610af5565b600083815260209020601f19861690835b828110156115745786850135825560209485019460019092019101611554565b50868210156115915760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60008135610f6281611083565b81356115bb81610fce565b6001600160a01b038116905081548173ffffffffffffffffffffffffffffffffffffffff19821617835560208401356115f38161128f565b7bffffffffffffffff00000000000000000000000000000000000000008160a01b1690507fffffffff000000000000000000000000000000000000000000000000000000008184828516171785556040860135925061165183611071565b921760e09190911b90911617815561168961166e606084016113ff565b6001830163ffffffff821663ffffffff198254161781555050565b611696608083018361140c565b6116a48183600286016114e3565b505061067f6116b560a084016115a3565b6003830160ff821660ff198254161781555050565b67ffffffffffffffff87168152600063ffffffff808816602084015280871660408401525060a0606083015261170460a0830185876112a5565b905060ff83166080830152979650505050505050565b60808101823561172981610fce565b6001600160a01b03908116835260208401359061174582610fce565b1660208301526040838101359083015260608301356117638161128f565b67ffffffffffffffff811660608401525092915050565b67ffffffffffffffff81811683821601908082111561179b5761179b6113b9565b5092915050565b634e487b7160e01b600052603260045260246000fd5b6000600182016117ca576117ca6113b9565b506001019056fea2646970667358221220a449a197632e1117b118ced8f7cf97a1ae44b160775ee146e59b50cbc1b8dcaa64736f6c63430008140033a2646970667358221220309da62fd58df02f8628b3ebd2b6e5d0deb6d76c30954e9cc12c8ee1656f994b64736f6c63430008140033", + Bin: "0x608060405234801561001057600080fd5b5061001a3361001f565b610090565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6143a180620000a06000396000f3fe60806040523480156200001157600080fd5b5060043610620001e85760003560e01c8063715018a6116200010d578063a1a227fa11620000a3578063db5d91b1116200007a578063db5d91b1146200049c578063e34fbfc814620004cb578063e874eb2014620004e0578063f2fde38b14620004f457600080fd5b8063a1a227fa1462000460578063a52f433c1462000474578063d4fab887146200048557600080fd5b80638236a7ba11620000e45780638236a7ba14620003cb57806387059edb14620003f25780638da5cb5b146200040957806398077e86146200043a57600080fd5b8063715018a614620003ad5780637281099614620003b75780638129fc1c14620003c157600080fd5b8063440c953b1162000183578063568699c8116200015a578063568699c8146200033f57806368e1038314620003665780636a30d26c146200037d5780636b9707d6146200039657600080fd5b8063440c953b14620003075780634766573814620003115780635371a216146200032857600080fd5b80632c77c81f11620001c45780632c77c81f146200023a5780632f0cb9e314620002515780633e60a22f146200028857806343348b2f14620002d857600080fd5b80620ddd2714620001ed57806303e72e48146200020a578063073b6ef31462000223575b600080fd5b620001f7600d5481565b6040519081526020015b60405180910390f35b620002216200021b36600462001e27565b6200050b565b005b620002216200023436600462001ec7565b6200061e565b620002216200024b36600462001ffb565b62000909565b62000277620002623660046200209e565b600c6020526000908152604090205460ff1681565b604051901515815260200162000201565b620002bf62000299366004620020b8565b80516020818301810180516003825292820191909301209152546001600160a01b031681565b6040516001600160a01b03909116815260200162000201565b62000277620002e9366004620020f9565b6001600160a01b031660009081526020819052604090205460ff1690565b620001f760055481565b6200022162000322366004620020f9565b62000a79565b62000221620003393660046200211e565b62000b49565b62000356620003503660046200209e565b62000d52565b6040516200020192919062002241565b62000221620003773660046200225c565b62000dab565b6200038762000e98565b604051620002019190620022e6565b62000221620003a7366004620020f9565b62000f7b565b6200022162001041565b6200022162001059565b62000221620010dd565b620003e2620003dc3660046200209e565b620012c1565b604051620002019291906200234c565b620003e2620004033660046200209e565b620013b1565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b0316620002bf565b620004516200044b3660046200209e565b6200142b565b60405162000201919062002369565b600a54620002bf906001600160a01b031681565b600454610100900460ff1662000277565b62000221620004963660046200237e565b620014e0565b62000277620004ad366004620020f9565b6001600160a01b031660009081526001602052604090205460ff1690565b62000221620004dc36600462002429565b5050565b600b54620002bf906001600160a01b031681565b6200022162000505366004620020f9565b62001673565b62000515620016d0565b60006001600160a01b03166003836040516200053291906200246f565b908152604051908190036020019020546001600160a01b0316036200059157600280546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace016200058f83826200251c565b505b80600383604051620005a491906200246f565b90815260405190819003602001812080546001600160a01b039390931673ffffffffffffffffffffffffffffffffffffffff19909316929092179091557f17b2f9f5748931099ffee882b5b64f4a560b5c55da9b4f4e396dae3bb9f98cb590620006129084908490620025e9565b60405180910390a15050565b6200062b8660ff6200262c565b431115620006805760405162461bcd60e51b815260206004820152601560248201527f426c6f636b2062696e64696e6720746f6f206f6c64000000000000000000000060448201526064015b60405180910390fd5b86864014620006e757620006944362001747565b6200069f8862001747565b620006ab884062001747565b604051602001620006bf9392919062002642565b60408051601f198184030181529082905262461bcd60e51b8252620006779160040162002369565b6000828152600860205260409020548114620007465760405162461bcd60e51b815260206004820152600e60248201527f496e76616c696420666f726b4944000000000000000000000000000000000000604482015260640162000677565b6000620007b889898989604051602001620007659493929190620026e7565b6040516020818303038152906040528051906020012086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620017ee92505050565b6001600160a01b03811660009081526020819052604090205490915060ff16620008255760405162461bcd60e51b815260206004820152601660248201527f656e636c6176654944206e6f7420617474657374656400000000000000000000604482015260640162000677565b600d89905560005b8651811015620008fd57600b5487516001600160a01b039091169063b6aed0cb9089908490811062000863576200086362002763565b6020026020010151620008769062002779565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526004810191909152426024820152604401600060405180830381600087803b158015620008ce57600080fd5b505af1158015620008e3573d6000803e3d6000fd5b505050508080620008f4906200279e565b9150506200082d565b50505050505050505050565b60006200095b8535620009206020880188620027ba565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250620017ee92505050565b6001600160a01b03811660009081526020819052604090205490915060ff16620009c85760405162461bcd60e51b815260206004820152601660248201527f656e636c6176654944206e6f7420617474657374656400000000000000000000604482015260640162000677565b6001600160a01b03811660009081526001602052604090205460ff1662000a325760405162461bcd60e51b815260206004820152601960248201527f656e636c6176654944206e6f7420612073657175656e63657200000000000000604482015260640162000677565b62000a3d856200181e565b604051853581527fd6555bff8670bd3008dc064c30bb56d6ac7cb14ae801e36146fe4e7c6a504a58906020015b60405180910390a15050505050565b62000a83620016d0565b6001600160a01b03811660009081526020819052604090205460ff1662000aed5760405162461bcd60e51b815260206004820152601660248201527f656e636c6176654944206e6f7420617474657374656400000000000000000000604482015260640162000677565b6001600160a01b038116600081815260016020818152604092839020805460ff191690921790915590519182527ffe64c7181f0fc60e300dc02cca368cdfa94d7ca45902de3b9a9d80070e76093691015b60405180910390a150565b600b546040517fb201246f0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063b201246f9062000b9a90879087908790879060040162002864565b60006040518083038186803b15801562000bb357600080fd5b505afa15801562000bc8573d6000803e3d6000fd5b5050505060008460405160200162000be19190620028cc565b60408051601f1981840301815291815281516020928301206000818152600c90935291205490915060ff161562000c5b5760405162461bcd60e51b815260206004820152601860248201527f7769746864726177616c20616c7265616479207370656e740000000000000000604482015260640162000677565b6001600c60008760405160200162000c749190620028cc565b60408051808303601f190181529181528151602092830120835282820193909352908201600020805460ff191693151593909317909255600a546001600160a01b0316916399a3ad219162000ccf91908901908901620020f9565b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b0390921660048301528801356024820152604401600060405180830381600087803b15801562000d3257600080fd5b505af115801562000d47573d6000803e3d6000fd5b505050505050505050565b60408051606080820183526000808352602083019190915291810182905260008062000d7e85620013b1565b915091508162000d945760009590945092505050565b600094855260086020526040909420549492505050565b60045460ff161562000e265760405162461bcd60e51b815260206004820152602260248201527f6e6574776f726b2073656372657420616c726561647920696e697469616c697a60448201527f6564000000000000000000000000000000000000000000000000000000000000606482015260840162000677565b60048054600160ff1991821681179092556001600160a01b038716600081815260208181526040808320805486168717905585825291829020805490941690941790925590519081527ffe64c7181f0fc60e300dc02cca368cdfa94d7ca45902de3b9a9d80070e760936910162000a6a565b60606002805480602002602001604051908101604052809291908181526020016000905b8282101562000f7257838290600052602060002001805462000ede906200248d565b80601f016020809104026020016040519081016040528092919081815260200182805462000f0c906200248d565b801562000f5d5780601f1062000f315761010080835404028352916020019162000f5d565b820191906000526020600020905b81548152906001019060200180831162000f3f57829003601f168201915b50505050508152602001906001019062000ebc565b50505050905090565b62000f85620016d0565b6001600160a01b03811660009081526001602052604090205460ff1662000fef5760405162461bcd60e51b815260206004820152601960248201527f656e636c6176654944206e6f7420612073657175656e63657200000000000000604482015260640162000677565b6001600160a01b038116600081815260016020908152604091829020805460ff1916905590519182527f0f279980343c7ca542fde9fa5396555068efb5cd560d9cf9c191aa2911079b47910162000b3e565b6200104b620016d0565b620010576000620018d3565b565b62001063620016d0565b600a546040517f36d2da900000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03909116906336d2da9090602401600060405180830381600087803b158015620010c257600080fd5b505af1158015620010d7573d6000803e3d6000fd5b50505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015620011295750825b905060008267ffffffffffffffff166001148015620011475750303b155b90508115801562001156575080155b156200118e576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff191660011785558315620011c357845468ff00000000000000001916680100000000000000001785555b620011ce3362001951565b60006005556001600955604051620011e69062001d3b565b604051809103906000f08015801562001203573d6000803e3d6000fd5b50600b805473ffffffffffffffffffffffffffffffffffffffff199081166001600160a01b0393909316928317909155600a8054909116821790556040519081527fbd726cf82ac9c3260b1495107182e336e0654b25c10915648c0cc15b2bb72cbf9060200160405180910390a18315620012ba57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200162000a6a565b5050505050565b60408051606080820183526000808352602080840183905283850182905285825260068152848220855193840190955284548352600185018054929586949390928401919062001311906200248d565b80601f01602080910402602001604051908101604052809291908181526020018280546200133f906200248d565b8015620013905780601f10620013645761010080835404028352916020019162001390565b820191906000526020600020905b8154815290600101906020018083116200137257829003601f168201915b50505091835250506002919091015460209091015280519094149492505050565b604080516060808201835260008083526020830191909152918101829052600083815260076020526040812054908190036200141657505060408051606081018252600080825282516020818101855282825283015291810182905290939092509050565b6200142181620012c1565b9250925050915091565b600281815481106200143c57600080fd5b90600052602060002001600091509050805462001459906200248d565b80601f016020809104026020016040519081016040528092919081815260200182805462001487906200248d565b8015620014d85780601f10620014ac57610100808354040283529160200191620014d8565b820191906000526020600020905b815481529060010190602001808311620014ba57829003601f168201915b505050505081565b6001600160a01b03851660009081526020819052604090205460ff1680620015715760405162461bcd60e51b815260206004820152602360248201527f726573706f6e64696e67206174746573746572206973206e6f7420617474657360448201527f7465640000000000000000000000000000000000000000000000000000000000606482015260840162000677565b811562001648576000620015aa8787866040516020016200159593929190620028dc565b60405160208183030381529060405262001966565b90506000620015ba8287620017ee565b9050876001600160a01b0316816001600160a01b031614620016455760405162461bcd60e51b815260206004820152602c60248201527f63616c63756c61746564206164647265737320616e642061747465737465724960448201527f4420646f6e74206d617463680000000000000000000000000000000000000000606482015260840162000677565b50505b5050506001600160a01b039091166000908152602081905260409020805460ff191660011790555050565b6200167d620016d0565b6001600160a01b038116620016c2576040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526000600482015260240162000677565b620016cd81620018d3565b50565b33620017037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b03161462001057576040517f118cdaa700000000000000000000000000000000000000000000000000000000815233600482015260240162000677565b606060006200175683620019a5565b600101905060008167ffffffffffffffff81111562001779576200177962001d49565b6040519080825280601f01601f191660200182016040528015620017a4576020820181803683370190505b5090508181016020015b600019017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8504945084620017ae57509392505050565b60008060008062001800868662001a8e565b92509250925062001812828262001adf565b50909150505b92915050565b8035600090815260066020526040902081906200183c828262002924565b505060095460009081526007602052604090208135908190556200186260014362002a34565b406040516020016200187e929190918252602082015260400190565b60408051601f198184030181529181528151602092830120600980546000908152600890945291832055805491620018b6836200279e565b919050555060055481604001351115620016cd5760400135600555565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6200195b62001bf5565b620016cd8162001c5d565b600062001974825162001747565b826040516020016200198892919062002a4a565b604051602081830303815290604052805190602001209050919050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310620019ef577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef8100000000831062001a1c576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831062001a3b57662386f26fc10000830492506010015b6305f5e100831062001a54576305f5e100830492506008015b612710831062001a6957612710830492506004015b6064831062001a7c576064830492506002015b600a8310620018185760010192915050565b6000806000835160410362001acc5760208401516040850151606086015160001a62001abd8882858562001c67565b95509550955050505062001ad8565b50508151600091506002905b9250925092565b600082600381111562001af65762001af662002aa9565b0362001b00575050565b600182600381111562001b175762001b1762002aa9565b0362001b4f576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600282600381111562001b665762001b6662002aa9565b0362001ba2576040517ffce698f70000000000000000000000000000000000000000000000000000000081526004810182905260240162000677565b600382600381111562001bb95762001bb962002aa9565b03620004dc576040517fd78bce0c0000000000000000000000000000000000000000000000000000000081526004810182905260240162000677565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1662001057576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200167d62001bf5565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111562001ca4575060009150600390508262001d31565b604080516000808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801562001cf9573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811662001d275750600092506001915082905062001d31565b9250600091508190505b9450945094915050565b6118ac8062002ac083390190565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171562001d8b5762001d8b62001d49565b604052919050565b600082601f83011262001da557600080fd5b813567ffffffffffffffff81111562001dc25762001dc262001d49565b62001dd7601f8201601f191660200162001d5f565b81815284602083860101111562001ded57600080fd5b816020850160208301376000918101602001919091529392505050565b80356001600160a01b038116811462001e2257600080fd5b919050565b6000806040838503121562001e3b57600080fd5b823567ffffffffffffffff81111562001e5357600080fd5b62001e618582860162001d93565b92505062001e726020840162001e0a565b90509250929050565b60008083601f84011262001e8e57600080fd5b50813567ffffffffffffffff81111562001ea757600080fd5b60208301915083602082850101111562001ec057600080fd5b9250929050565b60008060008060008060008060e0898b03121562001ee457600080fd5b88359750602089013596506040890135955067ffffffffffffffff8060608b0135111562001f1157600080fd5b60608a01358a018b601f82011262001f2857600080fd5b818135111562001f3c5762001f3c62001d49565b62001f4e6020823560051b0162001d5f565b81358082526020808301929160051b8401018e101562001f6d57600080fd5b602083015b6020843560051b85010181101562001fb457848135111562001f9357600080fd5b62001fa58f6020833587010162001d93565b83526020928301920162001f72565b509750505060808a013581101562001fcb57600080fd5b5062001fde8a60808b01358b0162001e7b565b989b979a5095989497959660a08601359560c00135945092505050565b600080600080606085870312156200201257600080fd5b843567ffffffffffffffff808211156200202b57600080fd5b90860190606082890312156200204057600080fd5b909450602086013590808211156200205757600080fd5b620020658883890162001e7b565b909550935060408701359150808211156200207f57600080fd5b508501602081880312156200209357600080fd5b939692955090935050565b600060208284031215620020b157600080fd5b5035919050565b600060208284031215620020cb57600080fd5b813567ffffffffffffffff811115620020e357600080fd5b620020f18482850162001d93565b949350505050565b6000602082840312156200210c57600080fd5b620021178262001e0a565b9392505050565b60008060008084860360c08112156200213657600080fd5b60808112156200214557600080fd5b50849350608085013567ffffffffffffffff808211156200216557600080fd5b818701915087601f8301126200217a57600080fd5b8135818111156200218a57600080fd5b8860208260051b8501011115620021a057600080fd5b95986020929092019750949560a00135945092505050565b60005b83811015620021d5578181015183820152602001620021bb565b50506000910152565b60008151808452620021f8816020860160208601620021b8565b601f01601f19169290920160200192915050565b8051825260006020820151606060208501526200222d6060850182620021de565b604093840151949093019390935250919050565b828152604060208201526000620020f160408301846200220c565b6000806000806000606086880312156200227557600080fd5b620022808662001e0a565b9450602086013567ffffffffffffffff808211156200229e57600080fd5b620022ac89838a0162001e7b565b90965094506040880135915080821115620022c657600080fd5b50620022d58882890162001e7b565b969995985093965092949392505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156200233f57603f198886030184526200232c858351620021de565b945092850192908501906001016200230d565b5092979650505050505050565b8215158152604060208201526000620020f160408301846200220c565b602081526000620021176020830184620021de565b600080600080600060a086880312156200239757600080fd5b620023a28662001e0a565b9450620023b26020870162001e0a565b9350604086013567ffffffffffffffff80821115620023d057600080fd5b620023de89838a0162001d93565b94506060880135915080821115620023f557600080fd5b50620024048882890162001d93565b925050608086013580151581146200241b57600080fd5b809150509295509295909350565b600080602083850312156200243d57600080fd5b823567ffffffffffffffff8111156200245557600080fd5b620024638582860162001e7b565b90969095509350505050565b6000825162002483818460208701620021b8565b9190910192915050565b600181811c90821680620024a257607f821691505b602082108103620024c357634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200251757600081815260208120601f850160051c81016020861015620024f25750805b601f850160051c820191505b818110156200251357828155600101620024fe565b5050505b505050565b815167ffffffffffffffff81111562002539576200253962001d49565b62002551816200254a84546200248d565b84620024c9565b602080601f831160018114620025895760008415620025705750858301515b600019600386901b1c1916600185901b17855562002513565b600085815260208120601f198616915b82811015620025ba5788860151825594840194600190910190840162002599565b5085821015620025d95787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b604081526000620025fe6040830185620021de565b90506001600160a01b03831660208301529392505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111562001818576200181862002616565b7f496e76616c696420626c6f636b2062696e64696e673a000000000000000000008152600084516200267c816016850160208901620021b8565b80830190507f3a000000000000000000000000000000000000000000000000000000000000008060168301528551620026bd816017850160208a01620021b8565b60179201918201528351620026da816018840160208801620021b8565b0160180195945050505050565b600060808201868352602086818501528560408501526080606085015281855180845260a08601915060a08160051b870101935082870160005b828110156200275357609f1988870301845262002740868351620021de565b9550928401929084019060010162002721565b50939a9950505050505050505050565b634e487b7160e01b600052603260045260246000fd5b80516020808301519190811015620024c35760001960209190910360031b1b16919050565b600060018201620027b357620027b362002616565b5060010190565b6000808335601e19843603018112620027d257600080fd5b83018035915067ffffffffffffffff821115620027ee57600080fd5b60200191503681900382131562001ec057600080fd5b6001600160a01b0380620028188362001e0a565b168352806200282a6020840162001e0a565b1660208401525060408101356040830152606081013567ffffffffffffffff81168082146200285857600080fd5b80606085015250505050565b62002870818662002804565b60c060808201528260c082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841115620028ad57600080fd5b8360051b808660e085013760a0830193909352500160e0019392505050565b6080810162001818828462002804565b60006bffffffffffffffffffffffff19808660601b168352808560601b16601484015250825162002915816028850160208701620021b8565b91909101602801949350505050565b813581556001808201602080850135601e198636030181126200294657600080fd5b8501803567ffffffffffffffff8111156200296057600080fd5b80360383830113156200297257600080fd5b6200298a816200298386546200248d565b86620024c9565b6000601f821160018114620029c35760008315620029aa57508382018501355b600019600385901b1c1916600184901b17865562002a1f565b600086815260209020601f19841690835b82811015620029f557868501880135825593870193908901908701620029d4565b508482101562002a155760001960f88660031b161c198785880101351681555b50508683881b0186555b50505050505050604082013560028201555050565b8181038181111562001818576200181862002616565b7f19457468657265756d205369676e6564204d6573736167653a0a00000000000081526000835162002a8481601a850160208801620021b8565b83519083019062002a9d81601a840160208801620021b8565b01601a01949350505050565b634e487b7160e01b600052602160045260246000fdfe608060405234801561001057600080fd5b50338061003757604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61004081610046565b50610096565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611807806100a56000396000f3fe6080604052600436106100e15760003560e01c80639730886d1161007f578063b201246f11610059578063b201246f1461030e578063b6aed0cb1461032e578063e138a8d21461034e578063f2fde38b1461036e57610155565b80639730886d1461029557806399a3ad21146102b5578063b1454caa146102d557610155565b8063346633fb116100bb578063346633fb1461022557806336d2da9014610238578063715018a6146102585780638da5cb5b1461026d57610155565b80630fcfbd11146101a25780630fe9188e146101d557806333a88c72146101f557610155565b36610155576040517f346633fb0000000000000000000000000000000000000000000000000000000081523360048201523460248201819052309163346633fb91906044016000604051808303818588803b15801561013f57600080fd5b505af1158015610153573d6000803e3d6000fd5b005b60405162461bcd60e51b815260206004820152600b60248201527f756e737570706f7274656400000000000000000000000000000000000000000060448201526064015b60405180910390fd5b3480156101ae57600080fd5b506101c26101bd366004610f80565b61038e565b6040519081526020015b60405180910390f35b3480156101e157600080fd5b506101536101f0366004610fb5565b610428565b34801561020157600080fd5b50610215610210366004610f80565b61049e565b60405190151581526020016101cc565b610153610233366004610fe3565b6104f1565b34801561024457600080fd5b5061015361025336600461100f565b6105d4565b34801561026457600080fd5b50610153610683565b34801561027957600080fd5b506000546040516001600160a01b0390911681526020016101cc565b3480156102a157600080fd5b506101536102b036600461102c565b610697565b3480156102c157600080fd5b506101536102d0366004610fe3565b6107e9565b3480156102e157600080fd5b506102f56102f03660046110a2565b610899565b60405167ffffffffffffffff90911681526020016101cc565b34801561031a57600080fd5b5061015361032936600461119b565b6108fa565b34801561033a57600080fd5b506101536103493660046111fd565b610afc565b34801561035a57600080fd5b5061015361036936600461121f565b610b98565b34801561037a57600080fd5b5061015361038936600461100f565b610d78565b600080826040516020016103a291906112ce565b60408051601f19818403018152918152815160209283012060008181526001909352912054909150806104215760405162461bcd60e51b815260206004820152602160248201527f54686973206d65737361676520776173206e65766572207375626d69747465646044820152601760f91b6064820152608401610199565b9392505050565b610430610dcf565b600081815260046020526040812054900361048d5760405162461bcd60e51b815260206004820152601a60248201527f537461746520726f6f7420646f6573206e6f742065786973742e0000000000006044820152606401610199565b600090815260046020526040812055565b600080826040516020016104b291906112ce565b60408051601f1981840301815291815281516020928301206000818152600190935291205490915080158015906104e95750428111155b949350505050565b60003411801561050057508034145b6105725760405162461bcd60e51b815260206004820152603060248201527f417474656d7074696e6720746f2073656e642076616c756520776974686f757460448201527f2070726f766964696e67204574686572000000000000000000000000000000006064820152608401610199565b600061057d33610e15565b6040805134815267ffffffffffffffff831660208201529192506001600160a01b0385169133917f50c536ac33a920f00755865b831d17bf4cff0b2e0345f65b16d52bfc004068b6910160405180910390a3505050565b6105dc610dcf565b6000816001600160a01b03164760405160006040518083038185875af1925050503d8060008114610629576040519150601f19603f3d011682016040523d82523d6000602084013e61062e565b606091505b505090508061067f5760405162461bcd60e51b815260206004820152601460248201527f6661696c65642073656e64696e672076616c75650000000000000000000000006044820152606401610199565b5050565b61068b610dcf565b6106956000610e73565b565b61069f610dcf565b60006106ab82426113cf565b90506000836040516020016106c091906112ce565b60408051601f198184030181529181528151602092830120600081815260019093529120549091501561075b5760405162461bcd60e51b815260206004820152602160248201527f4d657373616765207375626d6974746564206d6f7265207468616e206f6e636560448201527f21000000000000000000000000000000000000000000000000000000000000006064820152608401610199565b600081815260016020908152604082208490556002919061077e9087018761100f565b6001600160a01b0316815260208101919091526040016000908120906107aa60808701606088016113e2565b63ffffffff168152602080820192909252604001600090812080546001810182559082529190208591600402016107e182826115b0565b505050505050565b6107f1610dcf565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461083e576040519150601f19603f3d011682016040523d82523d6000602084013e610843565b606091505b50509050806108945760405162461bcd60e51b815260206004820152601460248201527f6661696c65642073656e64696e672076616c75650000000000000000000000006044820152606401610199565b505050565b60006108a433610e15565b9050336001600160a01b03167fb93c37389233beb85a3a726c3f15c2d15533ee74cb602f20f490dfffef7759378288888888886040516108e9969594939291906116ca565b60405180910390a295945050505050565b600081815260046020526040812054900361096a5760405162461bcd60e51b815260206004820152602a60248201527f526f6f74206973206e6f74207075626c6973686564206f6e2074686973206d6560448201526939b9b0b3b290313ab99760b11b6064820152608401610199565b6000818152600460205260409020544210156109d25760405162461bcd60e51b815260206004820152602160248201527f526f6f74206973206e6f7420636f6e736964657265642066696e616c207965746044820152601760f91b6064820152608401610199565b6000846040516020016109e5919061171a565b60408051601f198184030181528282528051602091820120908301829052600160608401527f760000000000000000000000000000000000000000000000000000000000000060808401529082015260a001604051602081830303815290604052805190602001209050610a8384848484604051602001610a6891815260200190565b60405160208183030381529060405280519060200120610ed0565b610af55760405162461bcd60e51b815260206004820152603360248201527f496e76616c696420696e636c7573696f6e2070726f6f6620666f722076616c7560448201527f65207472616e73666572206d6573736167652e000000000000000000000000006064820152608401610199565b5050505050565b610b04610dcf565b60008281526004602052604090205415610b865760405162461bcd60e51b815260206004820152602560248201527f526f6f7420616c726561647920616464656420746f20746865206d657373616760448201527f65206275730000000000000000000000000000000000000000000000000000006064820152608401610199565b60009182526004602052604090912055565b6000818152600460205260408120549003610c085760405162461bcd60e51b815260206004820152602a60248201527f526f6f74206973206e6f74207075626c6973686564206f6e2074686973206d6560448201526939b9b0b3b290313ab99760b11b6064820152608401610199565b600081815260046020526040902054421015610c705760405162461bcd60e51b815260206004820152602160248201527f526f6f74206973206e6f7420636f6e736964657265642066696e616c207965746044820152601760f91b6064820152608401610199565b600084604051602001610c8391906112ce565b60408051601f198184030181528282528051602091820120908301829052600160608401527f6d0000000000000000000000000000000000000000000000000000000000000060808401529082015260a001604051602081830303815290604052805190602001209050610d0684848484604051602001610a6891815260200190565b610af55760405162461bcd60e51b815260206004820152603060248201527f496e76616c696420696e636c7573696f6e2070726f6f6620666f722063726f7360448201527f7320636861696e206d6573736167652e000000000000000000000000000000006064820152608401610199565b610d80610dcf565b6001600160a01b038116610dc3576040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260006004820152602401610199565b610dcc81610e73565b50565b6000546001600160a01b03163314610695576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610199565b6001600160a01b0381166000908152600360205260408120805467ffffffffffffffff169160019190610e48838561177a565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550919050565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600082610ede868685610ee8565b1495945050505050565b600081815b84811015610f2b57610f1782878784818110610f0b57610f0b6117a2565b90506020020135610f34565b915080610f23816117b8565b915050610eed565b50949350505050565b6000818310610f50576000828152602084905260409020610f5f565b60008381526020839052604090205b90505b92915050565b600060c08284031215610f7a57600080fd5b50919050565b600060208284031215610f9257600080fd5b813567ffffffffffffffff811115610fa957600080fd5b6104e984828501610f68565b600060208284031215610fc757600080fd5b5035919050565b6001600160a01b0381168114610dcc57600080fd5b60008060408385031215610ff657600080fd5b823561100181610fce565b946020939093013593505050565b60006020828403121561102157600080fd5b813561042181610fce565b6000806040838503121561103f57600080fd5b823567ffffffffffffffff81111561105657600080fd5b61106285828601610f68565b95602094909401359450505050565b63ffffffff81168114610dcc57600080fd5b60ff81168114610dcc57600080fd5b803561109d81611083565b919050565b6000806000806000608086880312156110ba57600080fd5b85356110c581611071565b945060208601356110d581611071565b9350604086013567ffffffffffffffff808211156110f257600080fd5b818801915088601f83011261110657600080fd5b81358181111561111557600080fd5b89602082850101111561112757600080fd5b602083019550809450505050606086013561114181611083565b809150509295509295909350565b60008083601f84011261116157600080fd5b50813567ffffffffffffffff81111561117957600080fd5b6020830191508360208260051b850101111561119457600080fd5b9250929050565b60008060008084860360c08112156111b257600080fd5b60808112156111c057600080fd5b50849350608085013567ffffffffffffffff8111156111de57600080fd5b6111ea8782880161114f565b9598909750949560a00135949350505050565b6000806040838503121561121057600080fd5b50508035926020909101359150565b6000806000806060858703121561123557600080fd5b843567ffffffffffffffff8082111561124d57600080fd5b61125988838901610f68565b9550602087013591508082111561126f57600080fd5b5061127c8782880161114f565b9598909750949560400135949350505050565b67ffffffffffffffff81168114610dcc57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152600082356112df81610fce565b6001600160a01b03811660208401525060208301356112fd8161128f565b67ffffffffffffffff80821660408501526040850135915061131e82611071565b63ffffffff80831660608601526060860135925061133b83611071565b80831660808601525060808501359150601e1985360301821261135d57600080fd5b602091850191820191358181111561137457600080fd5b80360383131561138357600080fd5b60c060a086015261139860e0860182856112a5565b925050506113a860a08501611092565b60ff811660c0850152509392505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610f6257610f626113b9565b6000602082840312156113f457600080fd5b813561042181611071565b60008135610f6281611071565b6000808335601e1984360301811261142357600080fd5b83018035915067ffffffffffffffff82111561143e57600080fd5b60200191503681900382131561119457600080fd5b634e487b7160e01b600052604160045260246000fd5b600181811c9082168061147d57607f821691505b602082108103610f7a57634e487b7160e01b600052602260045260246000fd5b601f82111561089457600081815260208120601f850160051c810160208610156114c45750805b601f850160051c820191505b818110156107e1578281556001016114d0565b67ffffffffffffffff8311156114fb576114fb611453565b61150f836115098354611469565b8361149d565b6000601f841160018114611543576000851561152b5750838201355b600019600387901b1c1916600186901b178355610af5565b600083815260209020601f19861690835b828110156115745786850135825560209485019460019092019101611554565b50868210156115915760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60008135610f6281611083565b81356115bb81610fce565b6001600160a01b038116905081548173ffffffffffffffffffffffffffffffffffffffff19821617835560208401356115f38161128f565b7bffffffffffffffff00000000000000000000000000000000000000008160a01b1690507fffffffff000000000000000000000000000000000000000000000000000000008184828516171785556040860135925061165183611071565b921760e09190911b90911617815561168961166e606084016113ff565b6001830163ffffffff821663ffffffff198254161781555050565b611696608083018361140c565b6116a48183600286016114e3565b505061067f6116b560a084016115a3565b6003830160ff821660ff198254161781555050565b67ffffffffffffffff87168152600063ffffffff808816602084015280871660408401525060a0606083015261170460a0830185876112a5565b905060ff83166080830152979650505050505050565b60808101823561172981610fce565b6001600160a01b03908116835260208401359061174582610fce565b1660208301526040838101359083015260608301356117638161128f565b67ffffffffffffffff811660608401525092915050565b67ffffffffffffffff81811683821601908082111561179b5761179b6113b9565b5092915050565b634e487b7160e01b600052603260045260246000fd5b6000600182016117ca576117ca6113b9565b506001019056fea2646970667358221220a449a197632e1117b118ced8f7cf97a1ae44b160775ee146e59b50cbc1b8dcaa64736f6c63430008140033a2646970667358221220d500420acc4e9a0c6c9979499f0438445c2797b0a7aa4819ba213d9d82c267f764736f6c63430008140033", } // ManagementContractABI is the input ABI used to generate the binding from. diff --git a/contracts/src/management/ManagementContract.sol b/contracts/src/management/ManagementContract.sol index 1b538a7c59..04ffadf42a 100644 --- a/contracts/src/management/ManagementContract.sol +++ b/contracts/src/management/ManagementContract.sol @@ -61,7 +61,7 @@ contract ManagementContract is Initializable, OwnableUpgradeable { function initialize() public initializer { __Ownable_init(msg.sender); lastBatchSeqNo = 0; - rollups.nextFreeSequenceNumber = 0; //redundant as the default is 0, but for clarity + rollups.nextFreeSequenceNumber = 1; // rollup 0 == nil hash merkleMessageBus = new MerkleTreeMessageBus.MerkleTreeMessageBus(); messageBus = MessageBus.IMessageBus(address(merkleMessageBus)); diff --git a/go/host/l1/statemachine.go b/go/host/l1/statemachine.go index d941e91c9e..ef967518c5 100644 --- a/go/host/l1/statemachine.go +++ b/go/host/l1/statemachine.go @@ -103,7 +103,7 @@ func (c *crossChainStateMachine) PublishNextBundle() error { } // Get the bundle range from the management contract - nextForkUID, begin, end, err := c.publisher.GetBundleRangeFromManagementContract(big.NewInt(0).SetUint64(c.currentRollup), c.latestRollup.ForkUID) + nextForkUID, begin, end, err := c.publisher.GetBundleRangeFromManagementContract(big.NewInt(0).SetUint64(c.currentRollup), c.rollupHistory[c.currentRollup].ForkUID) if err != nil { return err } From ef0bf45ec3a75770589472f56feaf145fde0bce0 Mon Sep 17 00:00:00 2001 From: Stefan Iliev <46542846+StefanIliev545@users.noreply.github.com> Date: Mon, 1 Jul 2024 14:58:18 +0300 Subject: [PATCH 4/8] Fix. (#1973) Co-authored-by: StefanIliev545 --- go/enclave/rpc/EstimateGas.go | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/go/enclave/rpc/EstimateGas.go b/go/enclave/rpc/EstimateGas.go index f09a3d4b96..0873ec35ee 100644 --- a/go/enclave/rpc/EstimateGas.go +++ b/go/enclave/rpc/EstimateGas.go @@ -94,7 +94,7 @@ func EstimateGasExecute(builder *CallBuilder[CallParamsWithBlock, hexutil.Uint64 // TODO: Change to fixed time period quotes, rather than this. publishingGas = publishingGas.Mul(publishingGas, gethcommon.Big2) - executionGasEstimate, err := rpc.doEstimateGas(builder.ctx, txArgs, blockNumber, rpc.config.GasLocalExecutionCapFlag) + executionGasEstimate, gasPrice, err := rpc.doEstimateGas(builder.ctx, txArgs, blockNumber, rpc.config.GasLocalExecutionCapFlag) if err != nil { err = fmt.Errorf("unable to estimate transaction - %w", err) @@ -107,7 +107,16 @@ func EstimateGasExecute(builder *CallBuilder[CallParamsWithBlock, hexutil.Uint64 return nil } - totalGasEstimate := hexutil.Uint64(publishingGas.Uint64() + uint64(executionGasEstimate)) + totalGasEstimateUint64 := publishingGas.Uint64() + uint64(executionGasEstimate) + totalGasEstimate := hexutil.Uint64(totalGasEstimateUint64) + balance, err := rpc.chain.GetBalanceAtBlock(builder.ctx, *txArgs.From, blockNumber) + if err != nil { + return err + } + + if balance.ToInt().Cmp(big.NewInt(0).Mul(gasPrice, big.NewInt(0).SetUint64(totalGasEstimateUint64))) < 0 { + return fmt.Errorf("insufficient funds for gas estimate") + } builder.ReturnValue = &totalGasEstimate return nil } @@ -116,7 +125,7 @@ func EstimateGasExecute(builder *CallBuilder[CallParamsWithBlock, hexutil.Uint64 // This is a copy of https://github.com/ethereum/go-ethereum/blob/master/internal/ethapi/api.go#L1055 // there's a high complexity to the method due to geth business rules (which is mimic'd here) // once the work of obscuro gas mechanics is established this method should be simplified -func (rpc *EncryptionManager) doEstimateGas(ctx context.Context, args *gethapi.TransactionArgs, blkNumber *gethrpc.BlockNumber, gasCap uint64) (hexutil.Uint64, common.SystemError) { //nolint: gocognit +func (rpc *EncryptionManager) doEstimateGas(ctx context.Context, args *gethapi.TransactionArgs, blkNumber *gethrpc.BlockNumber, gasCap uint64) (hexutil.Uint64, *big.Int, common.SystemError) { //nolint: gocognit // Binary search the gas requirement, as it may be higher than the amount used var ( //nolint: revive lo = params.TxGas - 1 @@ -148,7 +157,7 @@ func (rpc *EncryptionManager) doEstimateGas(ctx context.Context, args *gethapi.T // Normalize the max fee per gas the call is willing to spend. var feeCap *big.Int if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) { - return 0, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") + return 0, gethcommon.Big0, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") } else if args.GasPrice != nil { feeCap = args.GasPrice.ToInt() } else if args.MaxFeePerGas != nil { @@ -160,13 +169,13 @@ func (rpc *EncryptionManager) doEstimateGas(ctx context.Context, args *gethapi.T if feeCap.BitLen() != 0 { //nolint:nestif balance, err := rpc.chain.GetBalanceAtBlock(ctx, *args.From, blkNumber) if err != nil { - return 0, fmt.Errorf("unable to fetch account balance - %w", err) + return 0, gethcommon.Big0, fmt.Errorf("unable to fetch account balance - %w", err) } available := new(big.Int).Set(balance.ToInt()) if args.Value != nil { if args.Value.ToInt().Cmp(available) >= 0 { - return 0, errors.New("insufficient funds for transfer") + return 0, gethcommon.Big0, errors.New("insufficient funds for transfer") } available.Sub(available, args.Value.ToInt()) } @@ -204,7 +213,7 @@ func (rpc *EncryptionManager) doEstimateGas(ctx context.Context, args *gethapi.T // call or transaction will never be accepted no matter how much gas it is // assigned. Return the error directly, don't struggle any more. if err != nil { - return 0, err + return 0, gethcommon.Big0, err } if failed { lo = mid @@ -216,20 +225,20 @@ func (rpc *EncryptionManager) doEstimateGas(ctx context.Context, args *gethapi.T if hi == cap { //nolint:nestif failed, result, err := rpc.isGasEnough(ctx, args, hi, blkNumber) if err != nil { - return 0, err + return 0, gethcommon.Big0, err } if failed { if result != nil && result.Err != vm.ErrOutOfGas { //nolint: errorlint if len(result.Revert()) > 0 { - return 0, newRevertError(result) + return 0, gethcommon.Big0, newRevertError(result) } - return 0, result.Err + return 0, gethcommon.Big0, result.Err } // Otherwise, the specified gas cap is too low - return 0, fmt.Errorf("gas required exceeds allowance (%d)", cap) + return 0, gethcommon.Big0, fmt.Errorf("gas required exceeds allowance (%d)", cap) } } - return hexutil.Uint64(hi), nil + return hexutil.Uint64(hi), feeCap, nil } // Create a helper to check if a gas allowance results in an executable transaction From 810ad3a6b764d9403a06ee8baeadd49ea0a5ca69 Mon Sep 17 00:00:00 2001 From: Anthony Nixon Date: Tue, 2 Jul 2024 10:44:04 +0100 Subject: [PATCH 5/8] Set Restart policy on docker containers --- go/common/docker/docker.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/go/common/docker/docker.go b/go/common/docker/docker.go index eb115c7d9c..e299330b48 100644 --- a/go/common/docker/docker.go +++ b/go/common/docker/docker.go @@ -104,10 +104,11 @@ func StartNewContainer(containerName, image string, cmds []string, ports []int, Env: envVars, }, &container.HostConfig{ - PortBindings: portBindings, - Mounts: mountVolumes, - Resources: container.Resources{Devices: deviceMapping}, - LogConfig: container.LogConfig{Type: "json-file", Config: logOptions}, + PortBindings: portBindings, + Mounts: mountVolumes, + RestartPolicy: container.RestartPolicy{Name: "unless-stopped"}, + Resources: container.Resources{Devices: deviceMapping}, + LogConfig: container.LogConfig{Type: "json-file", Config: logOptions}, }, &network.NetworkingConfig{ EndpointsConfig: map[string]*network.EndpointSettings{ From 82136ac6741caafa3ff346a739c73ce56acfb1ca Mon Sep 17 00:00:00 2001 From: Tudor Malene Date: Tue, 2 Jul 2024 16:56:51 +0100 Subject: [PATCH 6/8] db tweaks + getLogs Fix (#1974) * remove database order by because it slows down the query * db index tweaking * fix getLogs * fix getLogs * fix * fix * comments, and better name --- go/common/log_events.go | 4 +- go/enclave/storage/enclavedb/events.go | 8 +- .../storage/init/edgelessdb/001_init.sql | 13 +-- go/enclave/storage/storage.go | 15 ++- go/host/l1/statemachine.go | 10 +- tools/walletextension/rpcapi/filter_api.go | 97 ++++++++++++++----- tools/walletextension/rpcapi/utils.go | 10 +- 7 files changed, 112 insertions(+), 45 deletions(-) diff --git a/go/common/log_events.go b/go/common/log_events.go index 5f5df48b44..0db83be12f 100644 --- a/go/common/log_events.go +++ b/go/common/log_events.go @@ -43,7 +43,7 @@ func CreateAuthenticatedLogSubscriptionPayload(args []interface{}, vk *viewingke if !ok { return nil, fmt.Errorf("invalid subscription") } - fc := FromCriteria(filterCriteria) + fc := SerializableFilterCriteria(filterCriteria) logSubscription.Filter = &fc return logSubscription, nil } @@ -59,7 +59,7 @@ type FilterCriteriaJSON struct { Topics [][]common.Hash `json:"topics"` } -func FromCriteria(crit FilterCriteria) FilterCriteriaJSON { +func SerializableFilterCriteria(crit FilterCriteria) FilterCriteriaJSON { var from *rpc.BlockNumber if crit.FromBlock != nil { f := (rpc.BlockNumber)(crit.FromBlock.Int64()) diff --git a/go/enclave/storage/enclavedb/events.go b/go/enclave/storage/enclavedb/events.go index dc53b3994d..ba00c39ee2 100644 --- a/go/enclave/storage/enclavedb/events.go +++ b/go/enclave/storage/enclavedb/events.go @@ -18,9 +18,9 @@ import ( const ( baseEventsJoin = "from event_log e " + - "join receipt extx on e.receipt=extx.id" + - " join tx on extx.tx=tx.id " + - " join batch b on extx.batch=b.sequence " + + "join receipt rec on e.receipt=rec.id" + + " join tx on rec.tx=tx.id " + + " join batch b on rec.batch=b.sequence " + "join event_type et on e.event_type=et.id " + " join contract c on et.contract=c.id " + "left join event_topic t1 on e.topic1=t1.id " + @@ -237,8 +237,6 @@ func loadLogs(ctx context.Context, db *sql.DB, requestingAccount *gethcommon.Add query += whereCondition queryParams = append(queryParams, whereParams...) - query += " order by b.height, tx.idx asc" - rows, err := db.QueryContext(ctx, query, queryParams...) if err != nil { return nil, err diff --git a/go/enclave/storage/init/edgelessdb/001_init.sql b/go/enclave/storage/init/edgelessdb/001_init.sql index 48046641b0..387417c697 100644 --- a/go/enclave/storage/init/edgelessdb/001_init.sql +++ b/go/enclave/storage/init/edgelessdb/001_init.sql @@ -104,12 +104,12 @@ GRANT ALL ON obsdb.tx TO obscuro; create table if not exists obsdb.receipt ( - id INTEGER AUTO_INCREMENT, - content mediumblob, - tx int, - batch int NOT NULL, + id INTEGER AUTO_INCREMENT, + content mediumblob, + tx int, + batch int NOT NULL, INDEX (batch), - INDEX (tx), + INDEX (tx, batch), primary key (id) ); GRANT ALL ON obsdb.receipt TO obscuro; @@ -166,6 +166,7 @@ create table if not exists obsdb.event_log log_idx INTEGER NOT NULL, receipt INTEGER NOT NULL, primary key (id), - INDEX (receipt, event_type, topic1, topic2, topic3) + INDEX (receipt, event_type, topic1, topic2, topic3), + INDEX (event_type, topic1, topic2, topic3) ); GRANT ALL ON obsdb.event_log TO obscuro; \ No newline at end of file diff --git a/go/enclave/storage/storage.go b/go/enclave/storage/storage.go index 662eeb08ea..e6aac396e1 100644 --- a/go/enclave/storage/storage.go +++ b/go/enclave/storage/storage.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "math/big" + "sort" "time" "github.com/ten-protocol/go-ten/go/common/errutil" @@ -979,7 +980,19 @@ func (s *storageImpl) FilterLogs( topics [][]gethcommon.Hash, ) ([]*types.Log, error) { defer s.logDuration("FilterLogs", measure.NewStopwatch()) - return enclavedb.FilterLogs(ctx, s.db.GetSQLDB(), requestingAccount, fromBlock, toBlock, blockHash, addresses, topics) + logs, err := enclavedb.FilterLogs(ctx, s.db.GetSQLDB(), requestingAccount, fromBlock, toBlock, blockHash, addresses, topics) + if err != nil { + return nil, err + } + // the database returns an unsorted list of event logs. + // we have to perform the sorting programatically + sort.Slice(logs, func(i, j int) bool { + if logs[i].BlockNumber == logs[j].BlockNumber { + return logs[i].Index < logs[j].Index + } + return logs[i].BlockNumber < logs[j].BlockNumber + }) + return logs, nil } func (s *storageImpl) GetContractCount(ctx context.Context) (*big.Int, error) { diff --git a/go/host/l1/statemachine.go b/go/host/l1/statemachine.go index ef967518c5..84b9f5cc2a 100644 --- a/go/host/l1/statemachine.go +++ b/go/host/l1/statemachine.go @@ -17,8 +17,10 @@ import ( "github.com/ten-protocol/go-ten/go/ethadapter/mgmtcontractlib" ) -type ForkUniqueID = gethcommon.Hash -type RollupNumber = uint64 +type ( + ForkUniqueID = gethcommon.Hash + RollupNumber = uint64 +) type CrossChainStateMachine interface { GetRollupData(number RollupNumber) (RollupInfo, error) @@ -75,9 +77,11 @@ func NewCrossChainStateMachine( func (c *crossChainStateMachine) Start() error { return nil } + func (c *crossChainStateMachine) Stop() error { return nil } + func (c *crossChainStateMachine) HealthStatus(context.Context) host.HealthStatus { errMsg := "" if c.hostStopper.IsStopping() { @@ -174,7 +178,7 @@ func (c *crossChainStateMachine) revertToLatestKnownCommonAncestorRollup() error for forkHash != c.latestRollup.ForkUID { // Revert to previous rollup; No need to wipe the map as the synchronization reinserts the latest rollup - c.latestRollup = c.rollupHistory[c.latestRollup.Number-1] //go to previous rollup + c.latestRollup = c.rollupHistory[c.latestRollup.Number-1] // go to previous rollup hashBytes, _, err = managementContract.GetUniqueForkID(&bind.CallOpts{}, big.NewInt(0).SetUint64(c.latestRollup.Number)) if err != nil { diff --git a/tools/walletextension/rpcapi/filter_api.go b/tools/walletextension/rpcapi/filter_api.go index b7f049833c..b144160ae8 100644 --- a/tools/walletextension/rpcapi/filter_api.go +++ b/tools/walletextension/rpcapi/filter_api.go @@ -3,9 +3,12 @@ package rpcapi import ( "context" "fmt" + "sort" "sync/atomic" "time" + "github.com/status-im/keycard-go/hexutils" + "github.com/ethereum/go-ethereum/log" subscriptioncommon "github.com/ten-protocol/go-ten/go/common/subscription" @@ -186,32 +189,80 @@ func (api *FilterAPI) NewFilter(crit common.FilterCriteria) (rpc.ID, error) { } func (api *FilterAPI) GetLogs(ctx context.Context, crit common.FilterCriteria) ([]*types.Log, error) { - logs, err := ExecAuthRPC[[]*types.Log]( - ctx, - api.we, - &ExecCfg{ - cacheCfg: &CacheCfg{ - CacheTypeDynamic: func() CacheStrategy { - // when the toBlock is not specified, the request is open-ended - if crit.ToBlock != nil && crit.ToBlock.Int64() > 0 { - return LongLiving - } - return LatestBatch - }, - }, - tryUntilAuthorised: true, - adjustArgs: func(acct *GWAccount) []any { - // convert to something serializable - return []any{common.FromCriteria(crit)} + method := "eth_getLogs" + audit(api.we, "RPC start method=%s args=%v", method, ctx) + requestStartTime := time.Now() + userID, err := extractUserID(ctx, api.we) + if err != nil { + return nil, err + } + + res, err := withCache( + api.we.Cache, + &CacheCfg{ + CacheTypeDynamic: func() CacheStrategy { + if crit.ToBlock != nil && crit.ToBlock.Int64() > 0 { + return LongLiving + } + if crit.BlockHash != nil { + return LongLiving + } + // when the toBlock or the block Hash are not specified, the request is open-ended + return LatestBatch }, }, - "eth_getLogs", - crit, - ) - if logs != nil { - return *logs, err + generateCacheKey([]any{userID, method, common.SerializableFilterCriteria(crit)}), + func() (*[]*types.Log, error) { // called when there is no entry in the cache + user, err := getUser(userID, api.we) + if err != nil { + return nil, err + } + + allEventLogsMap := make(map[LogKey]*types.Log) + // for each account registered for the current user + // execute the get_Logs function + // dedupe and concatenate the results + for _, acct := range user.accounts { + eventLogs, err := withEncRPCConnection(ctx, api.we, acct, func(rpcClient *tenrpc.EncRPCClient) (*[]*types.Log, error) { + var result []*types.Log + + // wrap the context with a timeout to prevent long executions + timeoutContext, cancelCtx := context.WithTimeout(ctx, maximumRPCCallDuration) + defer cancelCtx() + + err := rpcClient.CallContext(timeoutContext, &result, method, common.SerializableFilterCriteria(crit)) + return &result, err + }) + if err != nil { + return nil, fmt.Errorf("could not read logs. cause: %w", err) + } + // dedupe event logs + for _, eventLog := range *eventLogs { + allEventLogsMap[LogKey{ + BlockHash: eventLog.BlockHash, + TxHash: eventLog.TxHash, + Index: eventLog.Index, + }] = eventLog + } + } + + result := make([]*types.Log, 0) + for _, eventLog := range allEventLogsMap { + result = append(result, eventLog) + } + sort.Slice(result, func(i, j int) bool { + if result[i].BlockNumber == result[j].BlockNumber { + return result[i].Index < result[j].Index + } + return result[i].BlockNumber < result[j].BlockNumber + }) + return &result, nil + }) + if err != nil { + return nil, err } - return nil, err + audit(api.we, "RPC call. uid=%s, method=%s args=%v result=%v error=%v time=%d", hexutils.BytesToHex(userID), method, crit, res, err, time.Since(requestStartTime).Milliseconds()) + return *res, err } func (api *FilterAPI) UninstallFilter(id rpc.ID) bool { diff --git a/tools/walletextension/rpcapi/utils.go b/tools/walletextension/rpcapi/utils.go index 9dbca7148a..2bab927659 100644 --- a/tools/walletextension/rpcapi/utils.go +++ b/tools/walletextension/rpcapi/utils.go @@ -101,15 +101,15 @@ func ExecAuthRPC[R any](ctx context.Context, w *Services, cfg *ExecCfg, method s return nil, err } - user, err := getUser(userID, w) - if err != nil { - return nil, err - } - cacheArgs := []any{userID, method} cacheArgs = append(cacheArgs, args...) res, err := withCache(w.Cache, cfg.cacheCfg, generateCacheKey(cacheArgs), func() (*R, error) { + user, err := getUser(userID, w) + if err != nil { + return nil, err + } + // determine candidate "from" candidateAccts, err := getCandidateAccounts(user, w, cfg) if err != nil { From a65abce21859b8021d1f307b958007a620cadd40 Mon Sep 17 00:00:00 2001 From: Moray Grieve Date: Wed, 3 Jul 2024 12:15:17 +0100 Subject: [PATCH 7/8] Change log for v0.25 (#1976) --- changelog.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/changelog.md b/changelog.md index b9991f0bdf..74d014ee4b 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,43 @@ --- # Ten Testnet Change Log +# July 2024-07-03 (v0.25.0) +* This is an L2 deployment release meaning state will be lost in order to upgrade the network. Any dApps on the + network will need to be redeployed. The release predominantly addresses performance improvements for large numbers + of transactions in the network, and for event log queries. +* A full list of the PRs merged in this release is as below; + * `ef0bf45e` Fix for xchain messages (#1973) + * `0dc7d5c5` Fix for integration test (#1971) + * `186bc2c3` Host db performance fixes (#1969) + * `c0ea9b43` Bundle submission rework (#1966) + * `0b01bfd1` Assets fix and clear console warnings (#1959) + * `ddff74a5` Update db schema (#1967) + * `e1c91243` Rework event logs and transaction database schema (#1961) + * `291a698d` Add db query tool (#1963) + * `b1af061b` Initiate bridge deployment (#1965) + * `95f35150` Initiate bridge deployment (#1960) + * `447ff489` Placeholder commit for new gh action workflow (#1964) + * `9d6e7747` Fix for startup (#1962) + * `b537d2e6` Add indexed events (#1954) + * `c6e5a48f` Adds log constraints to docker containers not instantiated by the go client (#1956) + * `85e6cd0d` Ignore empty l1 head status from enclave (#1955) + * `a9485fef` Fixes for ethereum bridge and json representation of batch header (#1953) + * `e6453082` Deploy separate ten gateway for dexynth (#1949) + * `b8935c31` Network tests: util func for l1 transfers (#1948) + * `0f3d42bf` Network tests: start gateway synchronously to fix race (#1947) + * `9cee2fd4` Increase max message size grpc config (#1946) + * `c0bf4086` Small mem pool fixes (#1943) + * `b335bd1e` Avoid spamming stuck l1 transactions (#1941) + * `99a8aeee` Fix panic on uninitialised mem pool (#1940) + * `1daffac0` Replace health-check db query (#1938) + * `a880b169` Hardcode response to client version request (#1937) + * `5780140e` Check conversions (#1936) + * `b97d0b93` Fix flakyness errors (#1927) + * `6e432a1a` Add net_version support and test (#1934) + * `4f39832e` Fixing log spam (#1931) + * `f8b86b52` Fix log spam (#1929) + * `762dfef9` Fix for interval (#1926) + # May 2024-05-20 (v0.24.0) * This is an L2 deployment release meaning state will be lost in order to upgrade the network. Any dApps on the network will need to be redeployed. High level changes made in the release include; From f396ac690e1d8537bb2ff42418405b19fde77bc1 Mon Sep 17 00:00:00 2001 From: Tudor Malene Date: Wed, 3 Jul 2024 14:45:15 +0100 Subject: [PATCH 8/8] split up storage and improve caching (#1977) * split up storage and improve caching * test fix --- go/common/cache_util.go | 39 --- go/common/gethencoding/geth_encoding.go | 33 +-- go/enclave/enclave.go | 5 +- go/enclave/genesis/genesis_test.go | 4 +- go/enclave/storage/cache_service.go | 167 +++++++++++++ go/enclave/storage/events_storage.go | 230 +++++++++++++++++ go/enclave/storage/interfaces.go | 3 - go/enclave/storage/storage.go | 317 ++---------------------- 8 files changed, 433 insertions(+), 365 deletions(-) delete mode 100644 go/common/cache_util.go create mode 100644 go/enclave/storage/cache_service.go create mode 100644 go/enclave/storage/events_storage.go diff --git a/go/common/cache_util.go b/go/common/cache_util.go deleted file mode 100644 index b35cc9068b..0000000000 --- a/go/common/cache_util.go +++ /dev/null @@ -1,39 +0,0 @@ -package common - -import ( - "context" - - "github.com/eko/gocache/lib/v4/cache" - gethlog "github.com/ethereum/go-ethereum/log" - "github.com/ten-protocol/go-ten/go/common/log" -) - -// GetCachedValue - returns the cached value for the provided key. If the key is not found, then invoke the 'onFailed' function -// which returns the value, and cache it -func GetCachedValue[V any](ctx context.Context, cache *cache.Cache[*V], logger gethlog.Logger, key any, onCacheMiss func(any) (*V, error)) (*V, error) { - value, err := cache.Get(ctx, key) - if err != nil || value == nil { - // todo metrics for cache misses - v, err := onCacheMiss(key) - if err != nil { - return v, err - } - if v == nil { - logger.Crit("Returned a nil value from the onCacheMiss function. Should not happen.") - } - CacheValue(ctx, cache, logger, key, v) - return v, nil - } - - return value, err -} - -func CacheValue[V any](ctx context.Context, cache *cache.Cache[*V], logger gethlog.Logger, key any, v *V) { - if v == nil { - return - } - err := cache.Set(ctx, key, v) - if err != nil { - logger.Error("Could not store value in cache", log.ErrKey, err) - } -} diff --git a/go/common/gethencoding/geth_encoding.go b/go/common/gethencoding/geth_encoding.go index bac9685bfb..a82bdb1fbf 100644 --- a/go/common/gethencoding/geth_encoding.go +++ b/go/common/gethencoding/geth_encoding.go @@ -10,10 +10,6 @@ import ( "time" "unsafe" - "github.com/dgraph-io/ristretto" - "github.com/eko/gocache/lib/v4/cache" - ristretto_store "github.com/eko/gocache/store/ristretto/v4" - gethlog "github.com/ethereum/go-ethereum/log" "github.com/ten-protocol/go-ten/go/common/log" "github.com/ten-protocol/go-ten/go/enclave/storage" @@ -51,29 +47,16 @@ type EncodingService interface { } type gethEncodingServiceImpl struct { - // conversion is expensive. Cache the converted headers. The key is the hash of the batch. - gethHeaderCache *cache.Cache[*types.Header] - - storage storage.Storage - logger gethlog.Logger + storage storage.Storage + logger gethlog.Logger + cachingService *storage.CacheService } -func NewGethEncodingService(storage storage.Storage, logger gethlog.Logger) EncodingService { - // todo (tudor) figure out the best values - ristrettoCache, err := ristretto.NewCache(&ristretto.Config{ - NumCounters: 5000, // number of keys to track frequency of. - MaxCost: 500, // todo - this represents how many items. - BufferItems: 64, // number of keys per Get buffer. Todo - what is this - }) - if err != nil { - panic(err) - } - ristrettoStore := ristretto_store.NewRistretto(ristrettoCache) - +func NewGethEncodingService(storage storage.Storage, cachingService *storage.CacheService, logger gethlog.Logger) EncodingService { return &gethEncodingServiceImpl{ - gethHeaderCache: cache.New[*types.Header](ristrettoStore), - storage: storage, - logger: logger, + storage: storage, + logger: logger, + cachingService: cachingService, } } @@ -276,7 +259,7 @@ func ExtractEthCall(param interface{}) (*gethapi.TransactionArgs, error) { // Special care must be taken to maintain a valid chain of these converted headers. func (enc *gethEncodingServiceImpl) CreateEthHeaderForBatch(ctx context.Context, h *common.BatchHeader) (*types.Header, error) { // wrap in a caching layer - return common.GetCachedValue(ctx, enc.gethHeaderCache, enc.logger, h.Hash(), func(a any) (*types.Header, error) { + return enc.cachingService.ReadConvertedHeader(ctx, h.Hash(), func(a any) (*types.Header, error) { // deterministically calculate the private randomness that will be exposed to the EVM secret, err := enc.storage.FetchSecret(ctx) if err != nil { diff --git a/go/enclave/enclave.go b/go/enclave/enclave.go index a12e7a7028..ada7f2c0fb 100644 --- a/go/enclave/enclave.go +++ b/go/enclave/enclave.go @@ -114,8 +114,9 @@ func NewEnclave( } // Initialise the database + cachingService := storage.NewCacheService(logger) chainConfig := ethchainadapter.ChainParams(big.NewInt(config.ObscuroChainID)) - storage := storage.NewStorageFromConfig(config, chainConfig, logger) + storage := storage.NewStorageFromConfig(config, cachingService, chainConfig, logger) // Initialise the Ethereum "Blockchain" structure that will allow us to validate incoming blocks // todo (#1056) - valid block @@ -160,7 +161,7 @@ func NewEnclave( obscuroKey := crypto.GetObscuroKey(logger) - gethEncodingService := gethencoding.NewGethEncodingService(storage, logger) + gethEncodingService := gethencoding.NewGethEncodingService(storage, cachingService, logger) dataEncryptionService := crypto.NewDataEncryptionService(logger) dataCompressionService := compression.NewBrotliDataCompressionService() diff --git a/go/enclave/genesis/genesis_test.go b/go/enclave/genesis/genesis_test.go index 66ef8f86b8..165caf653c 100644 --- a/go/enclave/genesis/genesis_test.go +++ b/go/enclave/genesis/genesis_test.go @@ -43,7 +43,7 @@ func TestDefaultGenesis(t *testing.T) { if err != nil { t.Fatalf("unable to create temp db: %s", err) } - storageDB := storage.NewStorage(backingDB, nil, gethlog.New()) + storageDB := storage.NewStorage(backingDB, storage.NewCacheService(gethlog.New()), nil, gethlog.New()) stateDB, err := gen.applyAllocations(storageDB) if err != nil { t.Fatalf("unable to apply genesis allocations") @@ -86,7 +86,7 @@ func TestCustomGenesis(t *testing.T) { if err != nil { t.Fatalf("unable to create temp db: %s", err) } - storageDB := storage.NewStorage(backingDB, nil, gethlog.New()) + storageDB := storage.NewStorage(backingDB, storage.NewCacheService(gethlog.New()), nil, gethlog.New()) stateDB, err := gen.applyAllocations(storageDB) if err != nil { t.Fatalf("unable to apply genesis allocations") diff --git a/go/enclave/storage/cache_service.go b/go/enclave/storage/cache_service.go new file mode 100644 index 0000000000..8982434aa6 --- /dev/null +++ b/go/enclave/storage/cache_service.go @@ -0,0 +1,167 @@ +package storage + +import ( + "context" + "math/big" + + "github.com/eko/gocache/lib/v4/store" + + "github.com/ten-protocol/go-ten/go/enclave/core" + + "github.com/dgraph-io/ristretto" + "github.com/eko/gocache/lib/v4/cache" + ristretto_store "github.com/eko/gocache/store/ristretto/v4" + + gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + gethlog "github.com/ethereum/go-ethereum/log" + "github.com/ten-protocol/go-ten/go/common" + "github.com/ten-protocol/go-ten/go/common/log" +) + +// approximate cost in bytes of the cached values +const ( + blockCost = 1024 + batchCost = 1024 + hashCost = 32 + idCost = 8 +) + +type CacheService struct { + // cache for the immutable blocks and batches. + // this avoids a trip to the database. + blockCache *cache.Cache[*types.Block] + + // stores batches using the sequence number as key + batchCacheBySeqNo *cache.Cache[*common.BatchHeader] + + // mapping between the hash and the sequence number + // note: to fetch a batch by hash will require 2 cache hits + seqCacheByHash *cache.Cache[*big.Int] + + // mapping between the height and the sequence number + // note: to fetch a batch by height will require 2 cache hits + seqCacheByHeight *cache.Cache[*big.Int] + + // batch hash - geth converted hash + convertedHashCache *cache.Cache[*gethcommon.Hash] + + // from address ( either eoa or contract) to the id of the db entry + eoaCache *cache.Cache[*uint64] + contractAddressCache *cache.Cache[*uint64] + + // from contract_address||event_sig to the event_type (id, isLifecycle) object + eventTypeCache *cache.Cache[*EventType] + + // store the converted ethereum header which is passed to the evm + convertedGethHeaderCache *cache.Cache[*types.Header] + + logger gethlog.Logger +} + +func NewCacheService(logger gethlog.Logger) *CacheService { + // todo (tudor) figure out the config + ristrettoCache, err := ristretto.NewCache(&ristretto.Config{ + NumCounters: 100_000_000, // 10 times the expected elements + MaxCost: 1024 * 1024 * 1024, // allocate 1GB + BufferItems: 64, // number of keys per Get buffer. + }) + if err != nil { + logger.Crit("Could not initialise ristretto cache", log.ErrKey, err) + } + ristrettoStore := ristretto_store.NewRistretto(ristrettoCache) + return &CacheService{ + blockCache: cache.New[*types.Block](ristrettoStore), + batchCacheBySeqNo: cache.New[*common.BatchHeader](ristrettoStore), + seqCacheByHash: cache.New[*big.Int](ristrettoStore), + seqCacheByHeight: cache.New[*big.Int](ristrettoStore), + convertedHashCache: cache.New[*gethcommon.Hash](ristrettoStore), + eoaCache: cache.New[*uint64](ristrettoStore), + contractAddressCache: cache.New[*uint64](ristrettoStore), + eventTypeCache: cache.New[*EventType](ristrettoStore), + convertedGethHeaderCache: cache.New[*types.Header](ristrettoStore), + logger: logger, + } +} + +func (cs *CacheService) CacheBlock(ctx context.Context, b *types.Block) { + cacheValue(ctx, cs.blockCache, cs.logger, b.Hash(), b, blockCost) +} + +func (cs *CacheService) CacheBatch(ctx context.Context, batch *core.Batch) { + cacheValue(ctx, cs.batchCacheBySeqNo, cs.logger, batch.SeqNo().Uint64(), batch.Header, batchCost) + cacheValue(ctx, cs.seqCacheByHash, cs.logger, batch.Hash(), batch.SeqNo(), idCost) + // note: the key is (height+1), because for some reason it doesn't like a key of 0 + // should always contain the canonical batch because the cache is overwritten by each new batch after a reorg + cacheValue(ctx, cs.seqCacheByHeight, cs.logger, batch.NumberU64()+1, batch.SeqNo(), idCost) +} + +func (cs *CacheService) ReadBlock(ctx context.Context, key gethcommon.Hash, onCacheMiss func(any) (*types.Block, error)) (*types.Block, error) { + return getCachedValue(ctx, cs.blockCache, cs.logger, key, blockCost, onCacheMiss) +} + +func (cs *CacheService) ReadBatchSeqByHash(ctx context.Context, hash common.L2BatchHash, onCacheMiss func(any) (*big.Int, error)) (*big.Int, error) { + return getCachedValue(ctx, cs.seqCacheByHash, cs.logger, hash, idCost, onCacheMiss) +} + +func (cs *CacheService) ReadBatchSeqByHeight(ctx context.Context, height uint64, onCacheMiss func(any) (*big.Int, error)) (*big.Int, error) { + // the key is (height+1), because for some reason it doesn't like a key of 0 + return getCachedValue(ctx, cs.seqCacheByHeight, cs.logger, height+1, idCost, onCacheMiss) +} + +func (cs *CacheService) ReadConvertedHash(ctx context.Context, hash common.L2BatchHash, onCacheMiss func(any) (*gethcommon.Hash, error)) (*gethcommon.Hash, error) { + return getCachedValue(ctx, cs.convertedHashCache, cs.logger, hash, hashCost, onCacheMiss) +} + +func (cs *CacheService) ReadBatch(ctx context.Context, seqNum uint64, onCacheMiss func(any) (*common.BatchHeader, error)) (*common.BatchHeader, error) { + return getCachedValue(ctx, cs.batchCacheBySeqNo, cs.logger, seqNum, batchCost, onCacheMiss) +} + +func (cs *CacheService) ReadEOA(ctx context.Context, addr gethcommon.Address, onCacheMiss func(any) (*uint64, error)) (*uint64, error) { + return getCachedValue(ctx, cs.eoaCache, cs.logger, addr, idCost, onCacheMiss) +} + +func (cs *CacheService) ReadContractAddr(ctx context.Context, addr gethcommon.Address, onCacheMiss func(any) (*uint64, error)) (*uint64, error) { + return getCachedValue(ctx, cs.contractAddressCache, cs.logger, addr, idCost, onCacheMiss) +} + +func (cs *CacheService) ReadEventType(ctx context.Context, contractAddress gethcommon.Address, eventSignature gethcommon.Hash, onCacheMiss func(any) (*EventType, error)) (*EventType, error) { + key := make([]byte, 0) + key = append(key, contractAddress.Bytes()...) + key = append(key, eventSignature.Bytes()...) + return getCachedValue(ctx, cs.eventTypeCache, cs.logger, key, idCost, onCacheMiss) +} + +func (cs *CacheService) ReadConvertedHeader(ctx context.Context, batchHash common.L2BatchHash, onCacheMiss func(any) (*types.Header, error)) (*types.Header, error) { + return getCachedValue(ctx, cs.convertedGethHeaderCache, cs.logger, batchHash, blockCost, onCacheMiss) +} + +// getCachedValue - returns the cached value for the provided key. If the key is not found, then invoke the 'onCacheMiss' function +// which returns the value, and cache it +func getCachedValue[V any](ctx context.Context, cache *cache.Cache[*V], logger gethlog.Logger, key any, cost int64, onCacheMiss func(any) (*V, error)) (*V, error) { + value, err := cache.Get(ctx, key) + if err != nil || value == nil { + // todo metrics for cache misses + v, err := onCacheMiss(key) + if err != nil { + return v, err + } + if v == nil { + logger.Crit("Returned a nil value from the onCacheMiss function. Should not happen.") + } + cacheValue(ctx, cache, logger, key, v, cost) + return v, nil + } + + return value, err +} + +func cacheValue[V any](ctx context.Context, cache *cache.Cache[*V], logger gethlog.Logger, key any, v *V, cost int64) { + if v == nil { + return + } + err := cache.Set(ctx, key, v, store.WithCost(cost)) + if err != nil { + logger.Error("Could not store value in cache", log.ErrKey, err) + } +} diff --git a/go/enclave/storage/events_storage.go b/go/enclave/storage/events_storage.go new file mode 100644 index 0000000000..20370589ff --- /dev/null +++ b/go/enclave/storage/events_storage.go @@ -0,0 +1,230 @@ +package storage + +import ( + "context" + "database/sql" + "errors" + "fmt" + + gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + gethlog "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ten-protocol/go-ten/go/common" + "github.com/ten-protocol/go-ten/go/common/errutil" + "github.com/ten-protocol/go-ten/go/common/measure" + "github.com/ten-protocol/go-ten/go/enclave/core" + "github.com/ten-protocol/go-ten/go/enclave/storage/enclavedb" +) + +// responsible for saving event logs +type eventsStorage struct { + cachingService *CacheService + logger gethlog.Logger +} + +func newEventsStorage(cachingService *CacheService, logger gethlog.Logger) *eventsStorage { + return &eventsStorage{cachingService: cachingService, logger: logger} +} + +func (es *eventsStorage) storeReceiptAndEventLogs(ctx context.Context, dbTX *sql.Tx, batch *common.BatchHeader, receipt *types.Receipt, createdContracts []*gethcommon.Address) error { + txId, senderId, err := enclavedb.ReadTransactionIdAndSender(ctx, dbTX, receipt.TxHash) + if err != nil && !errors.Is(err, errutil.ErrNotFound) { + return fmt.Errorf("could not get transaction id. Cause: %w", err) + } + + for _, createdContract := range createdContracts { + _, err = enclavedb.WriteContractAddress(ctx, dbTX, createdContract, *senderId) + if err != nil { + return fmt.Errorf("could not write contract address. cause %w", err) + } + } + + // Convert the receipt into its storage form and serialize + // this removes information that can be recreated + // todo - in a future iteration, this can be slimmed down further because we already store the logs separately + storageReceipt := (*types.ReceiptForStorage)(receipt) + receiptBytes, err := rlp.EncodeToBytes(storageReceipt) + if err != nil { + return fmt.Errorf("failed to encode block receipts. Cause: %w", err) + } + + execTxId, err := enclavedb.WriteReceipt(ctx, dbTX, batch.SequencerOrderNo.Uint64(), txId, receiptBytes) + if err != nil { + return fmt.Errorf("could not write receipt. Cause: %w", err) + } + + for _, l := range receipt.Logs { + err := es.storeEventLog(ctx, dbTX, execTxId, l) + if err != nil { + return fmt.Errorf("could not store log entry %v. Cause: %w", l, err) + } + } + return nil +} + +func (es *eventsStorage) storeEventLog(ctx context.Context, dbTX *sql.Tx, execTxId uint64, l *types.Log) error { + topicIds, isLifecycle, err := es.handleUserTopics(ctx, dbTX, l) + if err != nil { + return err + } + + eventTypeId, err := es.handleEventType(ctx, dbTX, l, isLifecycle) + if err != nil { + return err + } + + // normalize data + data := l.Data + if len(data) == 0 { + data = nil + } + err = enclavedb.WriteEventLog(ctx, dbTX, eventTypeId, topicIds, data, l.Index, execTxId) + if err != nil { + return fmt.Errorf("could not write event log. Cause: %w", err) + } + + return nil +} + +func (es *eventsStorage) handleEventType(ctx context.Context, dbTX *sql.Tx, l *types.Log, isLifecycle bool) (uint64, error) { + et, err := es.readEventType(ctx, dbTX, l.Address, l.Topics[0]) + if err != nil && !errors.Is(err, errutil.ErrNotFound) { + return 0, fmt.Errorf("could not read event type. Cause: %w", err) + } + if err == nil { + // in case we determined the current emitted event is not lifecycle, we must update the EventType + if !isLifecycle && et.isLifecycle { + err := enclavedb.UpdateEventTopicLifecycle(ctx, dbTX, et.id, isLifecycle) + if err != nil { + return 0, fmt.Errorf("could not update the event type. cause: %w", err) + } + } + return et.id, nil + } + + // the first time an event of this type is emitted we must store it + contractAddId, err := es.readContractAddress(ctx, dbTX, l.Address) + if err != nil { + // the contract was already stored when it was created + return 0, fmt.Errorf("could not read contract address. %s. Cause: %w", l.Address, err) + } + return enclavedb.WriteEventType(ctx, dbTX, contractAddId, l.Topics[0], isLifecycle) +} + +func (es *eventsStorage) handleUserTopics(ctx context.Context, dbTX *sql.Tx, l *types.Log) ([]*uint64, bool, error) { + topicIds := make([]*uint64, 3) + // iterate the topics containing user values + // reuse them if already inserted + // if not, discover if there is a relevant externally owned address + isLifecycle := true + for i := 1; i < len(l.Topics); i++ { + topic := l.Topics[i] + // first check if there is an entry already for this topic + eventTopicId, relAddressId, err := es.findEventTopic(ctx, dbTX, topic.Bytes()) + if err != nil && !errors.Is(err, errutil.ErrNotFound) { + return nil, false, fmt.Errorf("could not read the event topic. Cause: %w", err) + } + if errors.Is(err, errutil.ErrNotFound) { + // check whether the topic is an EOA + relAddressId, err = es.findRelevantAddress(ctx, dbTX, topic) + if err != nil && !errors.Is(err, errutil.ErrNotFound) { + return nil, false, fmt.Errorf("could not read relevant address. Cause %w", err) + } + eventTopicId, err = enclavedb.WriteEventTopic(ctx, dbTX, &topic, relAddressId) + if err != nil { + return nil, false, fmt.Errorf("could not write event topic. Cause: %w", err) + } + } + + if relAddressId != nil { + isLifecycle = false + } + topicIds[i-1] = &eventTopicId + } + return topicIds, isLifecycle, nil +} + +// Of the log's topics, returns those that are (potentially) user addresses. A topic is considered a user address if: +// - It has at least 12 leading zero bytes (since addresses are 20 bytes long, while hashes are 32) and at most 22 leading zero bytes +// - It is not a smart contract address +func (es *eventsStorage) findRelevantAddress(ctx context.Context, dbTX *sql.Tx, topic gethcommon.Hash) (*uint64, error) { + potentialAddr := common.ExtractPotentialAddress(topic) + if potentialAddr == nil { + return nil, errutil.ErrNotFound + } + + // first check whether there is already an entry in the EOA table + eoaID, err := es.readEOA(ctx, dbTX, *potentialAddr) + if err != nil && !errors.Is(err, errutil.ErrNotFound) { + return nil, err + } + if err == nil { + return eoaID, nil + } + + // if the address is a contract then it's clearly not an EOA + _, err = es.readContractAddress(ctx, dbTX, *potentialAddr) + if err != nil && !errors.Is(err, errutil.ErrNotFound) { + return nil, err + } + if err == nil { + return nil, errutil.ErrNotFound + } + + // when we reach this point, the value looks like an address, but we haven't yet seen it + // for the first iteration, we'll just assume it's an EOA + // we can make this smarter by passing in more information about the event + id, err := enclavedb.WriteEoa(ctx, dbTX, *potentialAddr) + if err != nil { + return nil, err + } + + return &id, nil +} + +func (es *eventsStorage) readEventType(ctx context.Context, dbTX *sql.Tx, contractAddress gethcommon.Address, eventSignature gethcommon.Hash) (*EventType, error) { + defer es.logDuration("ReadEventType", measure.NewStopwatch()) + + return es.cachingService.ReadEventType(ctx, contractAddress, eventSignature, func(v any) (*EventType, error) { + contractAddrId, err := enclavedb.ReadContractAddress(ctx, dbTX, contractAddress) + if err != nil { + return nil, err + } + id, isLifecycle, err := enclavedb.ReadEventType(ctx, dbTX, *contractAddrId, eventSignature) + if err != nil { + return nil, err + } + return &EventType{ + id: id, + isLifecycle: isLifecycle, + }, nil + }) +} + +func (es *eventsStorage) readContractAddress(ctx context.Context, dbTX *sql.Tx, addr gethcommon.Address) (*uint64, error) { + defer es.logDuration("readContractAddress", measure.NewStopwatch()) + return es.cachingService.ReadContractAddr(ctx, addr, func(v any) (*uint64, error) { + return enclavedb.ReadContractAddress(ctx, dbTX, addr) + }) +} + +func (es *eventsStorage) findEventTopic(ctx context.Context, dbTX *sql.Tx, topic []byte) (uint64, *uint64, error) { + defer es.logDuration("findEventTopic", measure.NewStopwatch()) + return enclavedb.ReadEventTopic(ctx, dbTX, topic) +} + +func (es *eventsStorage) readEOA(ctx context.Context, dbTX *sql.Tx, addr gethcommon.Address) (*uint64, error) { + defer es.logDuration("ReadEOA", measure.NewStopwatch()) + return es.cachingService.ReadEOA(ctx, addr, func(v any) (*uint64, error) { + id, err := enclavedb.ReadEoa(ctx, dbTX, addr) + if err != nil { + return nil, err + } + return &id, nil + }) +} + +func (es *eventsStorage) logDuration(method string, stopWatch *measure.Stopwatch) { + core.LogMethodDuration(es.logger, stopWatch, fmt.Sprintf("Storage::%s completed", method)) +} diff --git a/go/enclave/storage/interfaces.go b/go/enclave/storage/interfaces.go index 01b7f81586..fb7ac7b73a 100644 --- a/go/enclave/storage/interfaces.go +++ b/go/enclave/storage/interfaces.go @@ -150,9 +150,6 @@ type Storage interface { // StateDB - return the underlying state database StateDB() state.Database - ReadEOA(ctx context.Context, addr gethcommon.Address) (*uint64, error) - - ReadContractAddress(ctx context.Context, addr gethcommon.Address) (*uint64, error) ReadContractOwner(ctx context.Context, address gethcommon.Address) (*gethcommon.Address, error) } diff --git a/go/enclave/storage/storage.go b/go/enclave/storage/storage.go index e6aac396e1..244ffd7c5d 100644 --- a/go/enclave/storage/storage.go +++ b/go/enclave/storage/storage.go @@ -18,12 +18,8 @@ import ( "github.com/ethereum/go-ethereum/triedb" - "github.com/dgraph-io/ristretto" - "github.com/eko/gocache/lib/v4/cache" "github.com/ten-protocol/go-ten/go/common/measure" - ristretto_store "github.com/eko/gocache/store/ristretto/v4" - "github.com/ten-protocol/go-ten/go/config" "github.com/ten-protocol/go-ten/go/enclave/storage/enclavedb" @@ -50,40 +46,16 @@ const ( masterSeedCfg = "MASTER_SEED" ) -type eventType struct { +type EventType struct { id uint64 isLifecycle bool } // todo - this file needs splitting up based on concerns type storageImpl struct { - db enclavedb.EnclaveDB - - // cache for the immutable blocks and batches. - // this avoids a trip to the database. - blockCache *cache.Cache[*types.Block] - - // stores batches using the sequence number as key - batchCacheBySeqNo *cache.Cache[*common.BatchHeader] - - // mapping between the hash and the sequence number - // note: to fetch a batch by hash will require 2 cache hits - seqCacheByHash *cache.Cache[*big.Int] - - // mapping between the height and the sequence number - // note: to fetch a batch by height will require 2 cache hits - seqCacheByHeight *cache.Cache[*big.Int] - - // batch hash - geth converted hash - convertedHashCache *cache.Cache[*gethcommon.Hash] - - // from address ( either eoa or contract) to the id of the db entry - eoaCache *cache.Cache[*uint64] - contractAddressCache *cache.Cache[*uint64] - - // from contract_address||event_sig to the event_type (id, isLifecycle) object - eventTypeCache *cache.Cache[*eventType] - + db enclavedb.EnclaveDB + cachingService *CacheService + eventsStorage *eventsStorage cachedSharedSecret *crypto.SharedEnclaveSecret stateCache state.Database @@ -91,12 +63,12 @@ type storageImpl struct { logger gethlog.Logger } -func NewStorageFromConfig(config *config.EnclaveConfig, chainConfig *params.ChainConfig, logger gethlog.Logger) Storage { +func NewStorageFromConfig(config *config.EnclaveConfig, cachingService *CacheService, chainConfig *params.ChainConfig, logger gethlog.Logger) Storage { backingDB, err := CreateDBFromConfig(config, logger) if err != nil { logger.Crit("Failed to connect to backing database", log.ErrKey, err) } - return NewStorage(backingDB, chainConfig, logger) + return NewStorage(backingDB, cachingService, chainConfig, logger) } var defaultCacheConfig = &gethcore.CacheConfig{ @@ -116,35 +88,19 @@ var trieDBConfig = &triedb.Config{ }, } -func NewStorage(backingDB enclavedb.EnclaveDB, chainConfig *params.ChainConfig, logger gethlog.Logger) Storage { +func NewStorage(backingDB enclavedb.EnclaveDB, cachingService *CacheService, chainConfig *params.ChainConfig, logger gethlog.Logger) Storage { // Open trie database with provided config triedb := triedb.NewDatabase(backingDB, trieDBConfig) stateDB := state.NewDatabaseWithNodeDB(backingDB, triedb) - // todo (tudor) figure out the config - ristrettoCache, err := ristretto.NewCache(&ristretto.Config{ - NumCounters: 20_000, // 10*MaxCost - MaxCost: 2000, // - how many items to cache - BufferItems: 64, // number of keys per Get buffer. - }) - if err != nil { - logger.Crit("Could not initialise ristretto cache", log.ErrKey, err) - } - ristrettoStore := ristretto_store.NewRistretto(ristrettoCache) return &storageImpl{ - db: backingDB, - stateCache: stateDB, - chainConfig: chainConfig, - blockCache: cache.New[*types.Block](ristrettoStore), - batchCacheBySeqNo: cache.New[*common.BatchHeader](ristrettoStore), - seqCacheByHash: cache.New[*big.Int](ristrettoStore), - seqCacheByHeight: cache.New[*big.Int](ristrettoStore), - convertedHashCache: cache.New[*gethcommon.Hash](ristrettoStore), - eoaCache: cache.New[*uint64](ristrettoStore), - contractAddressCache: cache.New[*uint64](ristrettoStore), - eventTypeCache: cache.New[*eventType](ristrettoStore), - logger: logger, + db: backingDB, + stateCache: stateDB, + chainConfig: chainConfig, + cachingService: cachingService, + eventsStorage: newEventsStorage(cachingService, logger), + logger: logger, } } @@ -184,7 +140,7 @@ func (s *storageImpl) FetchBatch(ctx context.Context, hash common.L2BatchHash) ( } func (s *storageImpl) fetchSeqNoByHash(ctx context.Context, hash common.L2BatchHash) (*big.Int, error) { - seqNo, err := common.GetCachedValue(ctx, s.seqCacheByHash, s.logger, hash, func(v any) (*big.Int, error) { + seqNo, err := s.cachingService.ReadBatchSeqByHash(ctx, hash, func(v any) (*big.Int, error) { batch, err := enclavedb.ReadBatchHeaderByHash(ctx, s.db.GetSQLDB(), v.(common.L2BatchHash)) if err != nil { return nil, err @@ -201,7 +157,7 @@ func (s *storageImpl) FetchConvertedHash(ctx context.Context, hash common.L2Batc return gethcommon.Hash{}, err } - convertedHash, err := common.GetCachedValue(ctx, s.convertedHashCache, s.logger, hash, func(v any) (*gethcommon.Hash, error) { + convertedHash, err := s.cachingService.ReadConvertedHash(ctx, hash, func(v any) (*gethcommon.Hash, error) { ch, err := enclavedb.FetchConvertedBatchHash(ctx, s.db.GetSQLDB(), batch.SequencerOrderNo.Uint64()) if err != nil { return nil, err @@ -235,8 +191,7 @@ func (s *storageImpl) FetchBatchTransactionsBySeq(ctx context.Context, seqNo uin func (s *storageImpl) FetchBatchByHeight(ctx context.Context, height uint64) (*core.Batch, error) { defer s.logDuration("FetchBatchByHeight", measure.NewStopwatch()) - // the key is (height+1), because for some reason it doesn't like a key of 0 - seqNo, err := common.GetCachedValue(ctx, s.seqCacheByHeight, s.logger, height+1, func(h any) (*big.Int, error) { + seqNo, err := s.cachingService.ReadBatchSeqByHeight(ctx, height, func(h any) (*big.Int, error) { batch, err := enclavedb.ReadCanonicalBatchHeaderByHeight(ctx, s.db.GetSQLDB(), height) if err != nil { return nil, err @@ -322,14 +277,14 @@ func (s *storageImpl) StoreBlock(ctx context.Context, block *types.Block, chainF return fmt.Errorf("4. could not store block %s. Cause: %w", block.Hash(), err) } - common.CacheValue(ctx, s.blockCache, s.logger, block.Hash(), block) + s.cachingService.CacheBlock(ctx, block) return nil } func (s *storageImpl) FetchBlock(ctx context.Context, blockHash common.L1BlockHash) (*types.Block, error) { defer s.logDuration("FetchBlock", measure.NewStopwatch()) - return common.GetCachedValue(ctx, s.blockCache, s.logger, blockHash, func(hash any) (*types.Block, error) { + return s.cachingService.ReadBlock(ctx, blockHash, func(hash any) (*types.Block, error) { return enclavedb.FetchBlock(ctx, s.db.GetSQLDB(), hash.(common.L1BlockHash)) }) } @@ -511,9 +466,7 @@ func (s *storageImpl) StoreAttestedKey(ctx context.Context, aggregator gethcommo func (s *storageImpl) FetchBatchBySeqNo(ctx context.Context, seqNum uint64) (*core.Batch, error) { defer s.logDuration("FetchBatchBySeqNo", measure.NewStopwatch()) - h, err := common.GetCachedValue(ctx, s.batchCacheBySeqNo, s.logger, seqNum, func(seq any) (*common.BatchHeader, error) { - return enclavedb.ReadBatchHeaderBySeqNo(ctx, s.db.GetSQLDB(), seqNum) - }) + h, err := s.FetchBatchHeaderBySeqNo(ctx, seqNum) if err != nil { return nil, err } @@ -529,7 +482,7 @@ func (s *storageImpl) FetchBatchBySeqNo(ctx context.Context, seqNum uint64) (*co func (s *storageImpl) FetchBatchHeaderBySeqNo(ctx context.Context, seqNum uint64) (*common.BatchHeader, error) { defer s.logDuration("FetchBatchHeaderBySeqNo", measure.NewStopwatch()) - return common.GetCachedValue(ctx, s.batchCacheBySeqNo, s.logger, seqNum, func(seq any) (*common.BatchHeader, error) { + return s.cachingService.ReadBatch(ctx, seqNum, func(seq any) (*common.BatchHeader, error) { return enclavedb.ReadBatchHeaderBySeqNo(ctx, s.db.GetSQLDB(), seqNum) }) } @@ -608,11 +561,7 @@ func (s *storageImpl) StoreBatch(ctx context.Context, batch *core.Batch, convert return fmt.Errorf("could not commit batch %w", err) } - common.CacheValue(ctx, s.batchCacheBySeqNo, s.logger, batch.SeqNo().Uint64(), batch.Header) - common.CacheValue(ctx, s.seqCacheByHash, s.logger, batch.Hash(), batch.SeqNo()) - // note: the key is (height+1), because for some reason it doesn't like a key of 0 - // should always contain the canonical batch because the cache is overwritten by each new batch after a reorg - common.CacheValue(ctx, s.seqCacheByHeight, s.logger, batch.NumberU64()+1, batch.SeqNo()) + s.cachingService.CacheBatch(ctx, batch) return nil } @@ -657,7 +606,7 @@ func (s *storageImpl) StoreExecutedBatch(ctx context.Context, batch *common.Batc } for _, receipt := range receipts { - err = s.storeReceiptAndEventLogs(ctx, dbTx, batch, receipt, newContracts[receipt.TxHash]) + err = s.eventsStorage.storeReceiptAndEventLogs(ctx, dbTx, batch, receipt, newContracts[receipt.TxHash]) if err != nil { return fmt.Errorf("could not store receipt. Cause: %w", err) } @@ -669,185 +618,6 @@ func (s *storageImpl) StoreExecutedBatch(ctx context.Context, batch *common.Batc return nil } -// todo - move this to a separate service -func (s *storageImpl) storeReceiptAndEventLogs(ctx context.Context, dbTX *sql.Tx, batch *common.BatchHeader, receipt *types.Receipt, createdContracts []*gethcommon.Address) error { - txId, senderId, err := enclavedb.ReadTransactionIdAndSender(ctx, dbTX, receipt.TxHash) - if err != nil && !errors.Is(err, errutil.ErrNotFound) { - return fmt.Errorf("could not get transaction id. Cause: %w", err) - } - - for _, createdContract := range createdContracts { - _, err = enclavedb.WriteContractAddress(ctx, dbTX, createdContract, *senderId) - if err != nil { - return fmt.Errorf("could not write contract address. cause %w", err) - } - } - - // Convert the receipt into its storage form and serialize - // this removes information that can be recreated - // todo - in a future iteration, this can be slimmed down further because we already store the logs separately - storageReceipt := (*types.ReceiptForStorage)(receipt) - receiptBytes, err := rlp.EncodeToBytes(storageReceipt) - if err != nil { - return fmt.Errorf("failed to encode block receipts. Cause: %w", err) - } - - execTxId, err := enclavedb.WriteReceipt(ctx, dbTX, batch.SequencerOrderNo.Uint64(), txId, receiptBytes) - if err != nil { - return fmt.Errorf("could not write receipt. Cause: %w", err) - } - - for _, l := range receipt.Logs { - err := s.storeEventLog(ctx, dbTX, execTxId, l) - if err != nil { - return fmt.Errorf("could not store log entry %v. Cause: %w", l, err) - } - } - return nil -} - -func (s *storageImpl) storeEventLog(ctx context.Context, dbTX *sql.Tx, execTxId uint64, l *types.Log) error { - topicIds, isLifecycle, err := s.handleUserTopics(ctx, dbTX, l) - if err != nil { - return err - } - - eventTypeId, err := s.handleEventType(ctx, dbTX, l, isLifecycle) - if err != nil { - return err - } - - // normalize data - data := l.Data - if len(data) == 0 { - data = nil - } - err = enclavedb.WriteEventLog(ctx, dbTX, eventTypeId, topicIds, data, l.Index, execTxId) - if err != nil { - return fmt.Errorf("could not write event log. Cause: %w", err) - } - - return nil -} - -func (s *storageImpl) handleEventType(ctx context.Context, dbTX *sql.Tx, l *types.Log, isLifecycle bool) (uint64, error) { - et, err := s.readEventType(ctx, dbTX, l.Address, l.Topics[0]) - if err != nil && !errors.Is(err, errutil.ErrNotFound) { - return 0, fmt.Errorf("could not read event type. Cause: %w", err) - } - if err == nil { - // in case we determined the current emitted event is not lifecycle, we must update the eventType - if !isLifecycle && et.isLifecycle { - err := enclavedb.UpdateEventTopicLifecycle(ctx, dbTX, et.id, isLifecycle) - if err != nil { - return 0, fmt.Errorf("could not update the event type. cause: %w", err) - } - } - return et.id, nil - } - - // the first time an event of this type is emitted we must store it - contractAddId, err := s.readContractAddress(ctx, dbTX, l.Address) - if err != nil { - // the contract was already stored when it was created - return 0, fmt.Errorf("could not read contract address. %s. Cause: %w", l.Address, err) - } - return enclavedb.WriteEventType(ctx, dbTX, contractAddId, l.Topics[0], isLifecycle) -} - -func (s *storageImpl) handleUserTopics(ctx context.Context, dbTX *sql.Tx, l *types.Log) ([]*uint64, bool, error) { - topicIds := make([]*uint64, 3) - // iterate the topics containing user values - // reuse them if already inserted - // if not, discover if there is a relevant externally owned address - isLifecycle := true - for i := 1; i < len(l.Topics); i++ { - topic := l.Topics[i] - // first check if there is an entry already for this topic - eventTopicId, relAddressId, err := s.findEventTopic(ctx, dbTX, topic.Bytes()) - if err != nil && !errors.Is(err, errutil.ErrNotFound) { - return nil, false, fmt.Errorf("could not read the event topic. Cause: %w", err) - } - if errors.Is(err, errutil.ErrNotFound) { - // check whether the topic is an EOA - relAddressId, err = s.findRelevantAddress(ctx, dbTX, topic) - if err != nil && !errors.Is(err, errutil.ErrNotFound) { - return nil, false, fmt.Errorf("could not read relevant address. Cause %w", err) - } - eventTopicId, err = enclavedb.WriteEventTopic(ctx, dbTX, &topic, relAddressId) - if err != nil { - return nil, false, fmt.Errorf("could not write event topic. Cause: %w", err) - } - } - - if relAddressId != nil { - isLifecycle = false - } - topicIds[i-1] = &eventTopicId - } - return topicIds, isLifecycle, nil -} - -// Of the log's topics, returns those that are (potentially) user addresses. A topic is considered a user address if: -// - It has at least 12 leading zero bytes (since addresses are 20 bytes long, while hashes are 32) and at most 22 leading zero bytes -// - It is not a smart contract address -func (s *storageImpl) findRelevantAddress(ctx context.Context, dbTX *sql.Tx, topic gethcommon.Hash) (*uint64, error) { - potentialAddr := common.ExtractPotentialAddress(topic) - if potentialAddr == nil { - return nil, errutil.ErrNotFound - } - - // first check whether there is already an entry in the EOA table - eoaID, err := s.readEOA(ctx, dbTX, *potentialAddr) - if err != nil && !errors.Is(err, errutil.ErrNotFound) { - return nil, err - } - if err == nil { - return eoaID, nil - } - - // if the address is a contract then it's clearly not an EOA - _, err = s.readContractAddress(ctx, dbTX, *potentialAddr) - if err != nil && !errors.Is(err, errutil.ErrNotFound) { - return nil, err - } - if err == nil { - return nil, errutil.ErrNotFound - } - - // when we reach this point, the value looks like an address, but we haven't yet seen it - // for the first iteration, we'll just assume it's an EOA - // we can make this smarter by passing in more information about the event - id, err := enclavedb.WriteEoa(ctx, dbTX, *potentialAddr) - if err != nil { - return nil, err - } - - return &id, nil -} - -func (s *storageImpl) readEventType(ctx context.Context, dbTX *sql.Tx, contractAddress gethcommon.Address, eventSignature gethcommon.Hash) (*eventType, error) { - defer s.logDuration("readEventType", measure.NewStopwatch()) - - key := make([]byte, 0) - key = append(key, contractAddress.Bytes()...) - key = append(key, eventSignature.Bytes()...) - return common.GetCachedValue(ctx, s.eventTypeCache, s.logger, key, func(v any) (*eventType, error) { - contractAddrId, err := enclavedb.ReadContractAddress(ctx, dbTX, contractAddress) - if err != nil { - return nil, err - } - id, isLifecycle, err := enclavedb.ReadEventType(ctx, dbTX, *contractAddrId, eventSignature) - if err != nil { - return nil, err - } - return &eventType{ - id: id, - isLifecycle: isLifecycle, - }, nil - }) -} - func (s *storageImpl) StoreValueTransfers(ctx context.Context, blockHash common.L1BlockHash, transfers common.ValueTransferEvents) error { defer s.logDuration("StoreValueTransfers", measure.NewStopwatch()) dbtx, err := s.db.NewDBTransaction(ctx) @@ -1020,29 +790,9 @@ func (s *storageImpl) CountTransactionsPerAddress(ctx context.Context, address * return enclavedb.CountTransactionsPerAddress(ctx, s.db.GetSQLDB(), address) } -func (s *storageImpl) ReadEOA(ctx context.Context, addr gethcommon.Address) (*uint64, error) { - dbtx, err := s.db.NewDBTransaction(ctx) - if err != nil { - return nil, err - } - defer dbtx.Rollback() - return s.readEOA(ctx, dbtx, addr) -} - -func (s *storageImpl) readEOA(ctx context.Context, dbTX *sql.Tx, addr gethcommon.Address) (*uint64, error) { - defer s.logDuration("readEOA", measure.NewStopwatch()) - return common.GetCachedValue(ctx, s.eoaCache, s.logger, addr, func(v any) (*uint64, error) { - id, err := enclavedb.ReadEoa(ctx, dbTX, addr) - if err != nil { - return nil, err - } - return &id, nil - }) -} - func (s *storageImpl) readOrWriteEOA(ctx context.Context, dbTX *sql.Tx, addr gethcommon.Address) (*uint64, error) { defer s.logDuration("readOrWriteEOA", measure.NewStopwatch()) - return common.GetCachedValue(ctx, s.eoaCache, s.logger, addr, func(v any) (*uint64, error) { + return s.cachingService.ReadEOA(ctx, addr, func(v any) (*uint64, error) { id, err := enclavedb.ReadEoa(ctx, dbTX, addr) if err != nil { if errors.Is(err, errutil.ErrNotFound) { @@ -1058,31 +808,10 @@ func (s *storageImpl) readOrWriteEOA(ctx context.Context, dbTX *sql.Tx, addr get }) } -func (s *storageImpl) ReadContractAddress(ctx context.Context, addr gethcommon.Address) (*uint64, error) { - dbtx, err := s.db.NewDBTransaction(ctx) - if err != nil { - return nil, err - } - defer dbtx.Commit() - return s.readContractAddress(ctx, dbtx, addr) -} - func (s *storageImpl) ReadContractOwner(ctx context.Context, address gethcommon.Address) (*gethcommon.Address, error) { return enclavedb.ReadContractOwner(ctx, s.db.GetSQLDB(), address) } -func (s *storageImpl) readContractAddress(ctx context.Context, dbTX *sql.Tx, addr gethcommon.Address) (*uint64, error) { - defer s.logDuration("readContractAddress", measure.NewStopwatch()) - return common.GetCachedValue(ctx, s.contractAddressCache, s.logger, addr, func(v any) (*uint64, error) { - return enclavedb.ReadContractAddress(ctx, dbTX, addr) - }) -} - -func (s *storageImpl) findEventTopic(ctx context.Context, dbTX *sql.Tx, topic []byte) (uint64, *uint64, error) { - defer s.logDuration("findEventTopic", measure.NewStopwatch()) - return enclavedb.ReadEventTopic(ctx, dbTX, topic) -} - func (s *storageImpl) logDuration(method string, stopWatch *measure.Stopwatch) { core.LogMethodDuration(s.logger, stopWatch, fmt.Sprintf("Storage::%s completed", method)) }