From 514417ef784659e39ccc9e9e290bd34b64ae478f Mon Sep 17 00:00:00 2001 From: badgersrus <43809877+badgersrus@users.noreply.github.com> Date: Fri, 20 Dec 2024 12:57:18 +0100 Subject: [PATCH] L1 events and block processing (#2209) * homogenise l1 events into singular block processing --- .../ManagementContract/ManagementContract.go | 302 ++++++- .../src/management/ManagementContract.sol | 22 +- design/host/l1_block_processing.md | 75 ++ go/common/enclave.go | 4 +- go/common/host/host.go | 2 +- go/common/host/services.go | 15 +- go/common/l1_transaction.go | 139 +++ go/common/rpc/generated/enclave.pb.go | 843 +++++++++--------- go/common/rpc/generated/enclave.proto | 2 +- go/common/rpc/generated/enclave_grpc.pb.go | 149 ++-- go/enclave/components/block_processor.go | 18 +- go/enclave/components/interfaces.go | 4 +- go/enclave/components/rollup_consumer.go | 42 +- .../components/shared_secret_process.go | 70 +- .../crosschain/block_message_extractor.go | 98 +- go/enclave/crosschain/common.go | 34 +- go/enclave/crosschain/interfaces.go | 4 +- go/enclave/crosschain/message_bus_manager.go | 4 +- go/enclave/enclave.go | 4 +- go/enclave/enclave_admin_service.go | 44 +- go/enclave/rpc_server.go | 31 +- go/ethadapter/blob.go | 1 + .../erc20contractlib/erc20_contract_lib.go | 16 +- go/ethadapter/geth_rpc_client.go | 7 + go/ethadapter/interface.go | 1 + go/ethadapter/l1_transaction.go | 78 -- .../mgmtcontractlib/mgmt_contract_lib.go | 38 +- go/host/container/host_container.go | 11 +- go/host/enclave/guardian.go | 64 +- go/host/host.go | 2 +- go/host/l1/blockrepository.go | 239 ----- go/host/l1/dataservice.go | 346 +++++++ go/host/l1/publisher.go | 88 +- go/host/rpc/enclaverpc/enclave_client.go | 8 +- go/host/servicelocator.go | 4 +- .../ethereummock/erc20_contract_lib.go | 14 +- integration/ethereummock/mgmt_contract_lib.go | 52 +- integration/ethereummock/mock_l1_network.go | 6 +- integration/ethereummock/node.go | 85 +- integration/simulation/devnetwork/node.go | 8 +- .../simulation/network/network_utils.go | 4 +- integration/simulation/output_stats.go | 4 +- integration/simulation/simulation.go | 21 +- .../simulation_full_network_test.go | 2 +- .../transaction_injector_tracker.go | 9 +- integration/simulation/validate_chain.go | 6 +- .../smartcontract/debug_mgmt_contract_lib.go | 2 +- .../smartcontract/smartcontracts_test.go | 65 +- 48 files changed, 1832 insertions(+), 1255 deletions(-) create mode 100644 design/host/l1_block_processing.md create mode 100644 go/common/l1_transaction.go delete mode 100644 go/ethadapter/l1_transaction.go delete mode 100644 go/host/l1/blockrepository.go create mode 100644 go/host/l1/dataservice.go diff --git a/contracts/generated/ManagementContract/ManagementContract.go b/contracts/generated/ManagementContract/ManagementContract.go index 22d5738a79..ba341eee79 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\"},{\"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\":\"bytes[]\",\"name\":\"crossChainHashes\",\"type\":\"bytes[]\"}],\"name\":\"isBundleAvailable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"isBundleSaved\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"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: "0x6080604052348015600f57600080fd5b50601733601b565b608c565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6152738061009b6000396000f3fe608060405234801561001057600080fd5b50600436106101d95760003560e01c80638129fc1c11610104578063a25eb31c116100a2578063db5d91b111610071578063db5d91b114610475578063e34fbfc8146104a1578063e874eb20146104b3578063f2fde38b146104c657600080fd5b8063a25eb31c1461042c578063a4ab2faa1461043f578063a52f433c14610452578063d4fab8871461046257600080fd5b806387059edb116100de57806387059edb146103a95780638da5cb5b146103bc57806398077e86146103ec578063a1a227fa1461040c57600080fd5b80638129fc1c1461035d5780638236a7ba14610365578063841548261461038657600080fd5b8063476657381161017c5780636a30d26c1161014b5780636a30d26c146103255780636b9707d61461033a578063715018a61461034d578063728109961461035557600080fd5b806347665738146102cb5780635371a216146102de578063568699c8146102f157806368e103831461031257600080fd5b80632f0cb9e3116101b85780632f0cb9e3146102255780633e60a22f1461025557806343348b2f14610296578063440c953b146102c257600080fd5b80620ddd27146101de57806303e72e48146101fd578063073b6ef314610212575b600080fd5b6101e7600e5481565b6040516101f491906119de565b60405180910390f35b61021061020b366004611b14565b6104d9565b005b610210610220366004611c89565b6105e1565b610248610233366004611d57565b600c6020526000908152604090205460ff1681565b6040516101f49190611d7e565b610289610263366004611d8c565b80516020818301810180516003825292820191909301209152546001600160a01b031681565b6040516101f49190611dd8565b6102486102a4366004611de6565b6001600160a01b031660009081526020819052604090205460ff1690565b6101e760055481565b6102106102d9366004611de6565b6107d8565b6102106102ec366004611e6b565b610878565b6103046102ff366004611d57565b610a1d565b6040516101f4929190611f6d565b610210610320366004611f8d565b610a73565b61032d610b17565b6040516101f49190612090565b610210610348366004611de6565b610bf0565b610210610c80565b610210610c94565b610210610d19565b610378610373366004611d57565b610ef4565b6040516101f49291906120a1565b610248610394366004611d57565b600d6020526000908152604090205460ff1681565b6103786103b7366004611d57565b610fdc565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b0316610289565b6103ff6103fa366004611d57565b611053565b6040516101f491906120af565b600a5461041f906001600160a01b031681565b6040516101f49190612102565b61021061043a36600461213a565b6110ff565b61024861044d3660046121ac565b611207565b600454610100900460ff16610248565b6102106104703660046121fa565b611285565b610248610483366004611de6565b6001600160a01b031660009081526001602052604090205460ff1690565b6102106104af3660046122a1565b5050565b600b5461041f906001600160a01b031681565b6102106104d4366004611de6565b611361565b6104e16113b8565b60006001600160a01b03166003836040516104fc919061230b565b908152604051908190036020019020546001600160a01b03160361055857600280546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0161055683826123e7565b505b80600383604051610569919061230b565b90815260405190819003602001812080546001600160a01b039390931673ffffffffffffffffffffffffffffffffffffffff19909316929092179091557f17b2f9f5748931099ffee882b5b64f4a560b5c55da9b4f4e396dae3bb9f98cb5906105d590849084906124a7565b60405180910390a15050565b60008281526008602052604090205481146106175760405162461bcd60e51b815260040161060e906124f9565b60405180910390fd5b6000610685898989896040516020016106339493929190612561565b6040516020818303038152906040528051906020012086868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061142c92505050565b6001600160a01b03811660009081526020819052604090205490915060ff166106c05760405162461bcd60e51b815260040161060e906125d7565b600e8990556000805b87518110156107b357600b5488516001600160a01b039091169063b6aed0cb908a90849081106106fb576106fb6125e7565b602002602001015161070c90612607565b426040518363ffffffff1660e01b815260040161072a92919061263d565b600060405180830381600087803b15801561074457600080fd5b505af1158015610758573d6000803e3d6000fd5b505050508188828151811061076f5761076f6125e7565b602002602001015161078090612607565b60405160200161079192919061263d565b60408051601f19818403018152919052805160209091012091506001016106c9565b506000908152600d60205260409020805460ff19166001179055505050505050505050565b6107e06113b8565b6001600160a01b03811660009081526020819052604090205460ff166108185760405162461bcd60e51b815260040161060e906125d7565b6001600160a01b038116600090815260016020819052604091829020805460ff19169091179055517ffe64c7181f0fc60e300dc02cca368cdfa94d7ca45902de3b9a9d80070e7609369061086d908390611dd8565b60405180910390a150565b600b546040517fb201246f0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063b201246f906108c7908790879087908790600401612773565b60006040518083038186803b1580156108df57600080fd5b505afa1580156108f3573d6000803e3d6000fd5b5050505060008460405160200161090a91906127ac565b60408051601f1981840301815291815281516020928301206000818152600c90935291205490915060ff16156109525760405162461bcd60e51b815260040161060e906127ec565b6001600c60008760405160200161096991906127ac565b60408051808303601f190181529181528151602092830120835282820193909352908201600020805460ff191693151593909317909255600a546001600160a01b0316916399a3ad21916109c291908901908901611de6565b87604001356040518363ffffffff1660e01b81526004016109e49291906127fc565b600060405180830381600087803b1580156109fe57600080fd5b505af1158015610a12573d6000803e3d6000fd5b505050505050505050565b604080516060808201835260008083526020830191909152918101829052600080610a4785610fdc565b9150915081610a5c5760009590945092505050565b600094855260086020526040909420549492505050565b60045460ff1615610a965760405162461bcd60e51b815260040161060e90612864565b60048054600160ff1991821681179092556001600160a01b0387166000908152602081815260408083208054851686179055908490529081902080549092169092179055517ffe64c7181f0fc60e300dc02cca368cdfa94d7ca45902de3b9a9d80070e76093690610b08908790611dd8565b60405180910390a15050505050565b60606002805480602002602001604051908101604052809291908181526020016000905b82821015610be7578382906000526020600020018054610b5a9061232b565b80601f0160208091040260200160405190810160405280929190818152602001828054610b869061232b565b8015610bd35780601f10610ba857610100808354040283529160200191610bd3565b820191906000526020600020905b815481529060010190602001808311610bb657829003601f168201915b505050505081526020019060010190610b3b565b50505050905090565b610bf86113b8565b6001600160a01b03811660009081526001602052604090205460ff16610c305760405162461bcd60e51b815260040161060e906128a6565b6001600160a01b03811660009081526001602052604090819020805460ff19169055517f0f279980343c7ca542fde9fa5396555068efb5cd560d9cf9c191aa2911079b479061086d908390611dd8565b610c886113b8565b610c926000611458565b565b610c9c6113b8565b600a546040517f36d2da900000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906336d2da9090610ce5903390600401611dd8565b600060405180830381600087803b158015610cff57600080fd5b505af1158015610d13573d6000803e3d6000fd5b50505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015610d645750825b905060008267ffffffffffffffff166001148015610d815750303b155b905081158015610d8f575080155b15610dc6576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610dfa57845468ff00000000000000001916680100000000000000001785555b610e03336114d6565b60006005556001600955604051610e19906119c9565b604051809103906000f080158015610e35573d6000803e3d6000fd5b50600b80546001600160a01b039290921673ffffffffffffffffffffffffffffffffffffffff199283168117909155600a805490921681179091556040517fbd726cf82ac9c3260b1495107182e336e0654b25c10915648c0cc15b2bb72cbf91610e9e91611dd8565b60405180910390a18315610eed57845468ff0000000000000000191685556040517fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290610b08906001906128d1565b5050505050565b604080516060808201835260008083526020808401839052838501829052858252600681528482208551938401909552845483526001850180549295869493909284019190610f429061232b565b80601f0160208091040260200160405190810160405280929190818152602001828054610f6e9061232b565b8015610fbb5780601f10610f9057610100808354040283529160200191610fbb565b820191906000526020600020905b815481529060010190602001808311610f9e57829003601f168201915b50505091835250506002919091015460209091015280519094149492505050565b6040805160608082018352600080835260208301919091529181018290526000838152600760205260408120549081900361104057505060408051606081018252600080825282516020818101855282825283015291810182905290939092509050565b61104981610ef4565b9250925050915091565b6002818154811061106357600080fd5b90600052602060002001600091509050805461107e9061232b565b80601f01602080910402602001604051908101604052809291908181526020018280546110aa9061232b565b80156110f75780601f106110cc576101008083540402835291602001916110f7565b820191906000526020600020905b8154815290600101906020018083116110da57829003601f168201915b505050505081565b600061114d833561111360208601866128df565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061142c92505050565b6001600160a01b03811660009081526020819052604090205490915060ff166111885760405162461bcd60e51b815260040161060e906125d7565b6001600160a01b03811660009081526001602052604090205460ff166111c05760405162461bcd60e51b815260040161060e906128a6565b6111c9836114e7565b6040517fd6555bff8670bd3008dc064c30bb56d6ac7cb14ae801e36146fe4e7c6a504a58906111fa908535906119de565b60405180910390a1505050565b600080805b835181101561126c5781848281518110611228576112286125e7565b602002602001015161123990612607565b60405160200161124a92919061263d565b60408051601f198184030181529190528051602090910120915060010161120c565b506000908152600d602052604090205460ff1692915050565b6001600160a01b03851660009081526020819052604090205460ff16806112be5760405162461bcd60e51b815260040161060e9061298c565b81156113365760006112f28787866040516020016112de939291906129c4565b60405160208183030381529060405261158b565b90506000611300828761142c565b9050876001600160a01b0316816001600160a01b0316146113335760405162461bcd60e51b815260040161060e90612a40565b50505b5050506001600160a01b039091166000908152602081905260409020805460ff191660011790555050565b6113696113b8565b6001600160a01b0381166113ac5760006040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161060e9190611dd8565b6113b581611458565b50565b336113ea7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610c9257336040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040161060e9190611dd8565b60008060008061143c86866115c6565b92509250925061144c8282611613565b50909150505b92915050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6114de611715565b6113b58161177c565b8035600090815260066020526040902081906115038282612bb3565b50506009546000908152600760205260409020813590819055611527600143612bd3565b4060405160200161153992919061263d565b60408051601f19818403018152918152815160209283012060098054600090815260089094529183205580549161156f83612be6565b9190505550600554816040013511156113b55760400135600555565b60006115978251611784565b826040516020016115a9929190612bff565b604051602081830303815290604052805190602001209050919050565b600080600083516041036116005760208401516040850151606086015160001a6115f288828585611825565b95509550955050505061160c565b50508151600091506002905b9250925092565b600082600381111561162757611627612c3b565b03611630575050565b600182600381111561164457611644612c3b565b0361167b576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600282600381111561168f5761168f612c3b565b036116c8576040517ffce698f700000000000000000000000000000000000000000000000000000000815261060e9082906004016119de565b60038260038111156116dc576116dc612c3b565b036104af57806040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260040161060e91906119de565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16610c92576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611369611715565b60606000611791836118e7565b600101905060008167ffffffffffffffff8111156117b1576117b16119ec565b6040519080825280601f01601f1916602001820160405280156117db576020820181803683370190505b5090508181016020015b600019017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85049450846117e5575b509392505050565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084111561186057506000915060039050826118dd565b6000600188888888604051600081526020016040526040516118859493929190612c5a565b6020604051602081039080840390855afa1580156118a7573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166118d3575060009250600191508290506118dd565b9250600091508190505b9450945094915050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310611930577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef8100000000831061195c576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061197a57662386f26fc10000830492506010015b6305f5e1008310611992576305f5e100830492506008015b61271083106119a657612710830492506004015b606483106119b8576064830492506002015b600a83106114525760010192915050565b6125ae80612c9083390190565b805b82525050565b6020810161145282846119d6565b634e487b7160e01b600052604160045260246000fd5b601f19601f830116810181811067ffffffffffffffff82111715611a2857611a286119ec565b6040525050565b6000611a3a60405190565b9050611a468282611a02565b919050565b600067ffffffffffffffff821115611a6557611a656119ec565b601f19601f83011660200192915050565b82818337506000910152565b6000611a95611a9084611a4b565b611a2f565b9050828152838383011115611aac57611aac600080fd5b611aba836020830184611a76565b9392505050565b600082601f830112611ad557611ad5600080fd5b611aba83833560208501611a82565b60006001600160a01b038216611452565b611afe81611ae4565b81146113b557600080fd5b803561145281611af5565b60008060408385031215611b2a57611b2a600080fd5b823567ffffffffffffffff811115611b4457611b44600080fd5b611b5085828601611ac1565b925050611b608460208501611b09565b90509250929050565b80611afe565b803561145281611b69565b600067ffffffffffffffff821115611b9457611b946119ec565b5060209081020190565b6000611bac611a9084611b7a565b83815290506020808201908402830185811115611bcb57611bcb600080fd5b835b81811015611c0a57803567ffffffffffffffff811115611bef57611bef600080fd5b611bfb88828801611ac1565b84525060209283019201611bcd565b5050509392505050565b600082601f830112611c2857611c28600080fd5b611aba83833560208501611b9e565b60008083601f840112611c4c57611c4c600080fd5b50813567ffffffffffffffff811115611c6757611c67600080fd5b602083019150836001820283011115611c8257611c82600080fd5b9250929050565b60008060008060008060008060e0898b031215611ca857611ca8600080fd5b611cb28a8a611b6f565b9750611cc18a60208b01611b6f565b9650611cd08a60408b01611b6f565b9550606089013567ffffffffffffffff811115611cef57611cef600080fd5b611cfb8b828c01611c14565b955050608089013567ffffffffffffffff811115611d1b57611d1b600080fd5b611d278b828c01611c37565b9450945050611d398a60a08b01611b6f565b9150611d488a60c08b01611b6f565b90509295985092959890939650565b600060208284031215611d6c57611d6c600080fd5b611aba8383611b6f565b8015156119d8565b602081016114528284611d76565b600060208284031215611da157611da1600080fd5b813567ffffffffffffffff811115611dbb57611dbb600080fd5b611dc784828501611ac1565b949350505050565b6119d881611ae4565b602081016114528284611dcf565b600060208284031215611dfb57611dfb600080fd5b611aba8383611b09565b600060808284031215611e1a57611e1a600080fd5b50919050565b60008083601f840112611e3557611e35600080fd5b50813567ffffffffffffffff811115611e5057611e50600080fd5b602083019150836020820283011115611c8257611c82600080fd5b60008060008060c08587031215611e8457611e84600080fd5b611e8e8686611e05565b9350608085013567ffffffffffffffff811115611ead57611ead600080fd5b611eb987828801611e20565b9350935050611ecb8660a08701611b6f565b905092959194509250565b60005b83811015611ef1578181015183820152602001611ed9565b50506000910152565b6000611f04825190565b808452602084019350611f1b818560208601611ed6565b601f01601f19169290920192915050565b80516000906060840190611f4085826119d6565b5060208301518482036020860152611f588282611efa565b915050604083015161181d60408601826119d6565b60408101611f7b82856119d6565b8181036020830152611dc78184611f2c565b600080600080600060608688031215611fa857611fa8600080fd5b611fb28787611b09565b9450602086013567ffffffffffffffff811115611fd157611fd1600080fd5b611fdd88828901611c37565b9450945050604086013567ffffffffffffffff811115611fff57611fff600080fd5b61200b88828901611c37565b92509250509295509295909350565b6000611aba8383611efa565b60200190565b6000612036825190565b808452602084019350836020820285016120508560200190565b60005b84811015612084578383038852815161206c848261201a565b93505060208201602098909801979150600101612053565b50909695505050505050565b60208082528101611aba818461202c565b60408101611f7b8285611d76565b60208082528101611aba8184611efa565b60006114526001600160a01b0383166120d7565b90565b6001600160a01b031690565b6000611452826120c0565b6000611452826120e3565b6119d8816120ee565b6020810161145282846120f9565b600060608284031215611e1a57611e1a600080fd5b600060208284031215611e1a57611e1a600080fd5b6000806040838503121561215057612150600080fd5b823567ffffffffffffffff81111561216a5761216a600080fd5b61217685828601612110565b925050602083013567ffffffffffffffff81111561219657612196600080fd5b6121a285828601612125565b9150509250929050565b6000602082840312156121c1576121c1600080fd5b813567ffffffffffffffff8111156121db576121db600080fd5b611dc784828501611c14565b801515611afe565b8035611452816121e7565b600080600080600060a0868803121561221557612215600080fd5b61221f8787611b09565b945061222e8760208801611b09565b9350604086013567ffffffffffffffff81111561224d5761224d600080fd5b61225988828901611ac1565b935050606086013567ffffffffffffffff81111561227957612279600080fd5b61228588828901611ac1565b92505061229587608088016121ef565b90509295509295909350565b600080602083850312156122b7576122b7600080fd5b823567ffffffffffffffff8111156122d1576122d1600080fd5b6122dd85828601611c37565b92509250509250929050565b60006122f3825190565b612301818560208601611ed6565b9290920192915050565b61145281836122e9565b634e487b7160e01b600052602260045260246000fd5b60028104600182168061233f57607f821691505b602082108103611e1a57611e1a612315565b60006114526120d48381565b61236683612351565b815460001960089490940293841b1916921b91909117905550565b600061238e81848461235d565b505050565b818110156104af576123a6600082612381565b600101612393565b601f82111561238e576000818152602090206020601f850104810160208510156123d55750805b610eed6020601f860104830182612393565b815167ffffffffffffffff811115612401576124016119ec565b61240b825461232b565b6124168282856123ae565b506020601f82116001811461244b57600083156124335750848201515b600019600885021c1981166002850217855550610eed565b600084815260208120601f198516915b8281101561247b578785015182556020948501946001909201910161245b565b50848210156124985783870151600019601f87166008021c191681555b50505050600202600101905550565b604080825281016124b88185611efa565b9050611aba6020830184611dcf565b600e8152602081017f496e76616c696420666f726b494400000000000000000000000000000000000081529050612026565b60208082528101611452816124c7565b6000612513825190565b8084526020840193508360208202850161252d8560200190565b60005b848110156120845783830388528151612549848261201a565b93505060208201602098909801979150600101612530565b6080810161256f82876119d6565b61257c60208301866119d6565b61258960408301856119d6565b818103606083015261259b8184612509565b9695505050505050565b60168152602081017f656e636c6176654944206e6f742061747465737465640000000000000000000081529050612026565b60208082528101611452816125a5565b634e487b7160e01b600052603260045260246000fd5b6000611452825190565b6000612611825190565b6020830161261e816125fd565b9250506020811015611e1a576000196020919091036008021b16919050565b6040810161264b82856119d6565b611aba60208301846119d6565b5060006114526020830183611b09565b5060006114526020830183611b6f565b67ffffffffffffffff8116611afe565b803561145281612678565b5060006114526020830183612688565b67ffffffffffffffff81166119d8565b6126bd8180612658565b6126c78382611dcf565b506126d56020820182612658565b6126e26020840182611dcf565b506126f06040820182612668565b6126fd60408401826119d6565b5061270b6060820182612693565b61238e60608401826126a3565b82818337505050565b81835260208301925060007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561275c5761275c600080fd5b60208302925061276d838584612718565b50500190565b60c0810161278182876126b3565b8181036080830152612794818587612721565b90506127a360a08301846119d6565b95945050505050565b6080810161145282846126b3565b60188152602081017f7769746864726177616c20616c7265616479207370656e74000000000000000081529050612026565b60208082528101611452816127ba565b6040810161264b8285611dcf565b60228152602081017f6e6574776f726b2073656372657420616c726561647920696e697469616c697a81527f6564000000000000000000000000000000000000000000000000000000000000602082015290505b60400190565b602080825281016114528161280a565b60198152602081017f656e636c6176654944206e6f7420612073657175656e6365720000000000000081529050612026565b6020808252810161145281612874565b600067ffffffffffffffff8216611452565b6119d8816128b6565b6020810161145282846128c8565b6000808335601e19368590030181126128fa576128fa600080fd5b8301915050803567ffffffffffffffff81111561291957612919600080fd5b602082019150600181023603821315611c8257611c82600080fd5b60238152602081017f726573706f6e64696e67206174746573746572206973206e6f7420617474657381527f74656400000000000000000000000000000000000000000000000000000000006020820152905061285e565b6020808252810161145281612934565b60006114528260601b90565b60006114528261299c565b6119d86129bf82611ae4565b6129a8565b6129ce81856129b3565b6014016129db81846129b3565b601401611dc781836122e9565b602c8152602081017f63616c63756c61746564206164647265737320616e642061747465737465724981527f4420646f6e74206d6174636800000000000000000000000000000000000000006020820152905061285e565b60208082528101611452816129e8565b6000813561145281611b69565b600081611452565b612a6e82612a5d565b612a7a6120d482612a5d565b8255505050565b8267ffffffffffffffff811115612a9a57612a9a6119ec565b612aa4825461232b565b612aaf8282856123ae565b506000601f821160018114612ae45760008315612acc5750848201355b600019600885021c1981166002850217855550612b3e565b600084815260209020601f19841690835b82811015612b155787850135825560209485019460019092019101612af5565b5084821015612b32576000196008601f8716021c19878501351681555b50506001600284020184555b505050505050565b61238e838383612a81565b612b5a82612351565b80612a7a565b8180612b6b81612a50565b9050612b778184612a65565b5050612b8660208301836128df565b612b94818360018601612b46565b50506040820180612ba482612a50565b9050610d138160028501612b51565b6104af8282612b60565b634e487b7160e01b600052601160045260246000fd5b8181038181111561145257611452612bbd565b600060018201612bf857612bf8612bbd565b5060010190565b7f19457468657265756d205369676e6564204d6573736167653a0a0000000000008152601a01612c2f81846122e9565b9050611aba81836122e9565b634e487b7160e01b600052602160045260246000fd5b60ff81166119d8565b60808101612c6882876119d6565b612c756020830186612c51565b612c8260408301856119d6565b6127a360608301846119d656fe608060405234801561001057600080fd5b5061001a33610027565b610022610098565b61014a565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100e85760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146101475780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b612455806101596000396000f3fe6080604052600436106101115760003560e01c80638da5cb5b116100a5578063b1454caa11610074578063b6aed0cb11610059578063b6aed0cb1461038b578063e138a8d2146103ab578063f2fde38b146103cb57610185565b8063b1454caa1461034b578063b201246f1461036b57610185565b80638da5cb5b146102a65780639730886d146102eb57806399a3ad211461030b578063ab53bddc1461032b57610185565b8063346633fb116100e1578063346633fb1461023e57806336d2da9014610251578063485cc95514610271578063715018a61461029157610185565b8062a1b815146101a65780630fcfbd11146101d15780630fe9188e146101f157806333a88c721461021157610185565b36610185576040517f346633fb000000000000000000000000000000000000000000000000000000008152309063346633fb90349061015690339083906004016111ea565b6000604051808303818588803b15801561016f57600080fd5b505af1158015610183573d6000803e3d6000fd5b005b60405162461bcd60e51b815260040161019d90611239565b60405180910390fd5b3480156101b257600080fd5b506101bb6103eb565b6040516101c89190611249565b60405180910390f35b3480156101dd57600080fd5b506101bb6101ec366004611272565b610477565b3480156101fd57600080fd5b5061018361020c3660046112c5565b6104d6565b34801561021d57600080fd5b5061023161022c366004611272565b61051c565b6040516101c891906112ec565b61018361024c36600461130e565b61056e565b34801561025d57600080fd5b5061018361026c366004611346565b6106bd565b34801561027d57600080fd5b5061018361028c366004611365565b61073c565b34801561029d57600080fd5b506101836108a7565b3480156102b257600080fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03166040516101c89190611394565b3480156102f757600080fd5b506101836103063660046113a2565b6108bb565b34801561031757600080fd5b5061018361032636600461130e565b610a27565b34801561033757600080fd5b5061018361034636600461130e565b610aa7565b61035e61035936600461146b565b610b70565b6040516101c891906114f8565b34801561037757600080fd5b50610183610386366004611566565b610c7d565b34801561039757600080fd5b506101836103a63660046115d1565b610d7e565b3480156103b757600080fd5b506101836103c63660046115f1565b610dc4565b3480156103d757600080fd5b506101836103e6366004611346565b610f0f565b600354604080517f1a90a21900000000000000000000000000000000000000000000000000000000815290516000926001600160a01b031691631a90a2199160048083019260209291908290030181865afa15801561044e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104729190611679565b905090565b6000808260405160200161048b9190611837565b60408051601f198184030181529181528151602092830120600081815292839052912054909150806104cf5760405162461bcd60e51b815260040161019d90611886565b9392505050565b6104de610f66565b600081815260046020526040812054900361050b5760405162461bcd60e51b815260040161019d906118c8565b600090815260046020526040812055565b600080826040516020016105309190611837565b60408051601f19818403018152918152815160209283012060008181529283905291205490915080158015906105665750428111155b949350505050565b60003411801561057d57508034145b6105995760405162461bcd60e51b815260040161019d90611930565b60035434906001600160a01b03161561065d5760006105b66103eb565b9050803410156105d85760405162461bcd60e51b815260040161019d90611970565b6105e28134611996565b6003546040519193506000916001600160a01b039091169083908381818185875af1925050503d8060008114610634576040519150601f19603f3d011682016040523d82523d6000602084013e610639565b606091505b505090508061065a5760405162461bcd60e51b815260040161019d90611a01565b50505b600061066833610fda565b9050836001600160a01b0316336001600160a01b03167f50c536ac33a920f00755865b831d17bf4cff0b2e0345f65b16d52bfc004068b684846040516106af929190611a11565b60405180910390a350505050565b6106c5610f66565b6000816001600160a01b03164760405160006040518083038185875af1925050503d8060008114610712576040519150601f19603f3d011682016040523d82523d6000602084013e610717565b606091505b50509050806107385760405162461bcd60e51b815260040161019d90611a5e565b5050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff166000811580156107875750825b905060008267ffffffffffffffff1660011480156107a45750303b155b9050811580156107b2575080155b156107e9576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561081d57845468ff00000000000000001916680100000000000000001785555b61082687611038565b6003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038816179055831561089e57845468ff0000000000000000191685556040517fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29061089590600190611a92565b60405180910390a15b50505050505050565b6108af610f66565b6108b96000611049565b565b60006108c8600130611aa0565b90506108fb7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316336001600160a01b031614806109225750336001600160a01b038216145b61093e5760405162461bcd60e51b815260040161019d90611af5565b600061094a8342611b05565b905060008460405160200161095f9190611837565b60408051601f198184030181529181528151602092830120600081815292839052912054909150156109a35760405162461bcd60e51b815260040161019d90611b70565b6000818152602081815260408220849055600191906109c490880188611346565b6001600160a01b0316815260208101919091526040016000908120906109f06080880160608901611b80565b63ffffffff1681526020808201929092526040016000908120805460018101825590825291902086916004020161089e8282611fbe565b610a2f610f66565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610a7c576040519150601f19603f3d011682016040523d82523d6000602084013e610a81565b606091505b5050905080610aa25760405162461bcd60e51b815260040161019d90611a5e565b505050565b6000610ab4600130611aa0565b9050610ae77f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316336001600160a01b03161480610b0e5750336001600160a01b038216145b610b2a5760405162461bcd60e51b815260040161019d90611af5565b826001600160a01b03167fcd9850463422a7449c406a036e35e5edb6fbe35a64c9f12a2354be98a750c0d383604051610b639190611249565b60405180910390a2505050565b6003546000906001600160a01b031615610c26576000610b8e6103eb565b905080341015610bb05760405162461bcd60e51b815260040161019d90612020565b6003546040516000916001600160a01b03169083908381818185875af1925050503d8060008114610bfd576040519150601f19603f3d011682016040523d82523d6000602084013e610c02565b606091505b5050905080610c235760405162461bcd60e51b815260040161019d90611a01565b50505b610c2f33610fda565b90507fb93c37389233beb85a3a726c3f15c2d15533ee74cb602f20f490dfffef77593733828888888888604051610c6c9796959493929190612030565b60405180910390a195945050505050565b6000818152600460205260408120549003610caa5760405162461bcd60e51b815260040161019d906120eb565b600081815260046020526040902054421015610cd85760405162461bcd60e51b815260040161019d90612137565b600084604051602001610ceb91906121bc565b60405160208183030381529060405280519060200120604051602001610d1191906121fc565b604051602081830303815290604052805190602001209050610d5b84848484604051602001610d40919061221b565b604051602081830303815290604052805190602001206110c7565b610d775760405162461bcd60e51b815260040161019d90612285565b5050505050565b610d86610f66565b60008281526004602052604090205415610db25760405162461bcd60e51b815260040161019d906122ed565b60009182526004602052604090912055565b6000818152600460205260408120549003610df15760405162461bcd60e51b815260040161019d906120eb565b600081815260046020526040902054421015610e1f5760405162461bcd60e51b815260040161019d90612137565b6000610e2e6020860186611346565b610e3e60408701602088016122fd565b610e4e6060880160408901611b80565b610e5e6080890160608a01611b80565b610e6b60808a018a611cd7565b610e7b60c08c0160a08d0161231c565b604051602001610e919796959493929190612030565b604051602081830303815290604052805190602001209050600081604051602001610ebc919061236d565b604051602081830303815290604052805190602001209050610eeb85858584604051602001610d40919061221b565b610f075760405162461bcd60e51b815260040161019d906123d5565b505050505050565b610f17610f66565b6001600160a01b038116610f5a5760006040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161019d9190611394565b610f6381611049565b50565b33610f987f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146108b957336040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040161019d9190611394565b6001600160a01b0381166000908152600260205260408120805467ffffffffffffffff16916001919061100d83856123e5565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550919050565b6110406110df565b610f6381611146565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6000826110d586868561114e565b1495945050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff166108b9576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f176110df565b600081815b848110156111875761117d8287878481811061117157611171612409565b90506020020135611190565b9150600101611153565b50949350505050565b60008183106111ac5760008281526020849052604090206111bb565b60008381526020839052604090205b90505b92915050565b60006001600160a01b0382166111be565b6111de816111c4565b82525050565b806111de565b604081016111f882856111d5565b6104cf60208301846111e4565b600b8152602081017f756e737570706f72746564000000000000000000000000000000000000000000815290505b60200190565b602080825281016111be81611205565b602081016111be82846111e4565b600060c0828403121561126c5761126c600080fd5b50919050565b60006020828403121561128757611287600080fd5b813567ffffffffffffffff8111156112a1576112a1600080fd5b61056684828501611257565b805b8114610f6357600080fd5b80356111be816112ad565b6000602082840312156112da576112da600080fd5b6111bb83836112ba565b8015156111de565b602081016111be82846112e4565b6112af816111c4565b80356111be816112fa565b6000806040838503121561132457611324600080fd5b61132e8484611303565b915061133d84602085016112ba565b90509250929050565b60006020828403121561135b5761135b600080fd5b6111bb8383611303565b6000806040838503121561137b5761137b600080fd5b6113858484611303565b915061133d8460208501611303565b602081016111be82846111d5565b600080604083850312156113b8576113b8600080fd5b823567ffffffffffffffff8111156113d2576113d2600080fd5b6113de85828601611257565b92505061133d84602085016112ba565b63ffffffff81166112af565b80356111be816113ee565b60008083601f84011261141a5761141a600080fd5b50813567ffffffffffffffff81111561143557611435600080fd5b60208301915083600182028301111561145057611450600080fd5b9250929050565b60ff81166112af565b80356111be81611457565b60008060008060006080868803121561148657611486600080fd5b61149087876113fa565b945061149f87602088016113fa565b9350604086013567ffffffffffffffff8111156114be576114be600080fd5b6114ca88828901611405565b93509350506114dc8760608801611460565b90509295509295909350565b67ffffffffffffffff81166111de565b602081016111be82846114e8565b60006080828403121561126c5761126c600080fd5b60008083601f84011261153057611530600080fd5b50813567ffffffffffffffff81111561154b5761154b600080fd5b60208301915083602082028301111561145057611450600080fd5b60008060008060c0858703121561157f5761157f600080fd5b6115898686611506565b9350608085013567ffffffffffffffff8111156115a8576115a8600080fd5b6115b48782880161151b565b93509350506115c68660a087016112ba565b905092959194509250565b600080604083850312156115e7576115e7600080fd5b61132e84846112ba565b6000806000806060858703121561160a5761160a600080fd5b843567ffffffffffffffff81111561162457611624600080fd5b61163087828801611257565b945050602085013567ffffffffffffffff81111561165057611650600080fd5b61165c8782880161151b565b93509350506115c686604087016112ba565b80516111be816112ad565b60006020828403121561168e5761168e600080fd5b6111bb838361166e565b5060006111be6020830183611303565b67ffffffffffffffff81166112af565b80356111be816116a8565b5060006111be60208301836116b8565b5060006111be60208301836113fa565b63ffffffff81166111de565b6000808335601e193685900301811261170a5761170a600080fd5b830160208101925035905067ffffffffffffffff81111561172d5761172d600080fd5b3681900382131561145057611450600080fd5b82818337506000910152565b818352602083019250611760828483611740565b50601f01601f19160190565b5060006111be6020830183611460565b60ff81166111de565b600060c083016117958380611698565b61179f85826111d5565b506117ad60208401846116c3565b6117ba60208601826114e8565b506117c860408401846116d3565b6117d560408601826116e3565b506117e360608401846116d3565b6117f060608601826116e3565b506117fe60808401846116ef565b858303608087015261181183828461174c565b9250505061182260a084018461176c565b61182f60a086018261177c565b509392505050565b602080825281016111bb8184611785565b60218152602081017f54686973206d65737361676520776173206e65766572207375626d69747465648152601760f91b602082015290505b60400190565b602080825281016111be81611848565b601a8152602081017f537461746520726f6f7420646f6573206e6f742065786973742e00000000000081529050611233565b602080825281016111be81611896565b60308152602081017f417474656d7074696e6720746f2073656e642076616c756520776974686f757481527f2070726f766964696e672045746865720000000000000000000000000000000060208201529050611880565b602080825281016111be816118d8565b60208082527f496e73756666696369656e742066756e647320746f2073656e642076616c75659101908152611233565b602080825281016111be81611940565b634e487b7160e01b600052601160045260246000fd5b818103818111156111be576111be611980565b60248152602081017f4661696c656420746f2073656e64206665657320746f206665657320636f6e7481527f726163740000000000000000000000000000000000000000000000000000000060208201529050611880565b602080825281016111be816119a9565b60408101611a1f82856111e4565b6104cf60208301846114e8565b60148152602081017f6661696c65642073656e64696e672076616c756500000000000000000000000081529050611233565b602080825281016111be81611a2c565b60006111be82611a7c565b90565b67ffffffffffffffff1690565b6111de81611a6e565b602081016111be8284611a89565b6001600160a01b039182169190811690828203908111156111be576111be611980565b60118152602081017f4e6f74206f776e6572206f722073656c6600000000000000000000000000000081529050611233565b602080825281016111be81611ac3565b808201808211156111be576111be611980565b60218152602081017f4d657373616765207375626d6974746564206d6f7265207468616e206f6e636581527f210000000000000000000000000000000000000000000000000000000000000060208201529050611880565b602080825281016111be81611b18565b600060208284031215611b9557611b95600080fd5b6111bb83836113fa565b600081356111be816112fa565b60006001600160a01b03835b81169019929092169190911792915050565b60006111be826111c4565b60006111be82611bca565b611be982611bd5565b611bf4818354611bac565b8255505050565b600081356111be816116a8565b60007bffffffffffffffff0000000000000000000000000000000000000000611bb88460a01b90565b60006111be67ffffffffffffffff8316611a7c565b611c4f82611c31565b611bf4818354611c08565b600081356111be816113ee565b60007fffffffff00000000000000000000000000000000000000000000000000000000611bb88460e01b90565b600063ffffffff82166111be565b611cab82611c94565b611bf4818354611c67565b600063ffffffff83611bb8565b611ccc82611c94565b611bf4818354611cb6565b6000808335601e1936859003018112611cf257611cf2600080fd5b8301915050803567ffffffffffffffff811115611d1157611d11600080fd5b60208201915060018102360382131561145057611450600080fd5b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052602260045260246000fd5b600281046001821680611d6c57607f821691505b60208210810361126c5761126c611d42565b60006111be611a798381565b611d9383611d7e565b815460001960089490940293841b1916921b91909117905550565b6000610aa2818484611d8a565b8181101561073857611dce600082611dae565b600101611dbb565b601f821115610aa2576000818152602090206020601f85010481016020851015611dfd5750805b610d776020601f860104830182611dbb565b8267ffffffffffffffff811115611e2857611e28611d2c565b611e328254611d58565b611e3d828285611dd6565b506000601f821160018114611e725760008315611e5a5750848201355b600019600885021c1981166002850217855550610f07565b600084815260209020601f19841690835b82811015611ea35787850135825560209485019460019092019101611e83565b5084821015611ec0576000196008601f8716021c19878501351681555b5050505060020260010190555050565b610aa2838383611e0f565b600081356111be81611457565b600060ff82166111be565b611efc82611ee8565b815460ff191660ff821617611bf4565b808280611f1881611b9f565b9050611f248184611be0565b50506020830180611f3482611bfb565b9050611f408184611c46565b50506040830180611f5082611c5a565b9050611f5c8184611ca2565b5050506060820180611f6d82611c5a565b9050611f7c8160018501611cc3565b5050611f8b6080830183611cd7565b611f99818360028601611ed0565b505060a0820180611fa982611edb565b9050611fb88160038501611ef3565b50505050565b6107388282611f0c565b60258152602081017f496e73756666696369656e742066756e647320746f207075626c697368206d6581527f737361676500000000000000000000000000000000000000000000000000000060208201529050611880565b602080825281016111be81611fc8565b60c0810161203e828a6111d5565b61204b60208301896114e8565b61205860408301886116e3565b61206560608301876116e3565b818103608083015261207881858761174c565b905061208760a083018461177c565b98975050505050505050565b602a8152602081017f526f6f74206973206e6f74207075626c6973686564206f6e2074686973206d6581527f7373616765206275732e0000000000000000000000000000000000000000000060208201529050611880565b602080825281016111be81612093565b60218152602081017f526f6f74206973206e6f7420636f6e736964657265642066696e616c207965748152601760f91b60208201529050611880565b602080825281016111be816120fb565b5060006111be60208301836112ba565b6121618180611698565b61216b83826111d5565b506121796020820182611698565b61218660208401826111d5565b506121946040820182612147565b6121a160408401826111e4565b506121af60608201826116c3565b610aa260608401826114e8565b608081016111be8284612157565b60018152602081017f760000000000000000000000000000000000000000000000000000000000000081529050611233565b6040808252810161220c816121ca565b90506111be60208301846111e4565b61222581836111e4565b602001919050565b60338152602081017f496e76616c696420696e636c7573696f6e2070726f6f6620666f722076616c7581527f65207472616e73666572206d6573736167652e0000000000000000000000000060208201529050611880565b602080825281016111be8161222d565b60258152602081017f526f6f7420616c726561647920616464656420746f20746865206d657373616781527f652062757300000000000000000000000000000000000000000000000000000060208201529050611880565b602080825281016111be81612295565b60006020828403121561231257612312600080fd5b6111bb83836116b8565b60006020828403121561233157612331600080fd5b6111bb8383611460565b60018152602081017f6d0000000000000000000000000000000000000000000000000000000000000081529050611233565b6040808252810161220c8161233b565b60308152602081017f496e76616c696420696e636c7573696f6e2070726f6f6620666f722063726f7381527f7320636861696e206d6573736167652e0000000000000000000000000000000060208201529050611880565b602080825281016111be8161237d565b67ffffffffffffffff9182169190811690828201908111156111be576111be611980565b634e487b7160e01b600052603260045260246000fdfea26469706673582212209046d260e6ecf02a9b545045265133ebd2a8a091d8cfe42d8fe9829451348f2664736f6c634300081c0033a26469706673582212206fbeb4fa662306572375051ef628ba8cd5106387c138927f0349e546931828e964736f6c634300081c0033", + 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\":\"requester\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"requestReport\",\"type\":\"string\"}],\"name\":\"NetworkSecretRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"attester\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"requester\",\"type\":\"address\"}],\"name\":\"NetworkSecretResponded\",\"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\"},{\"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\":\"bytes[]\",\"name\":\"crossChainHashes\",\"type\":\"bytes[]\"}],\"name\":\"isBundleAvailable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"isBundleSaved\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"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: "0x6080604052348015600f57600080fd5b50601733601b565b608c565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b61531d8061009b6000396000f3fe608060405234801561001057600080fd5b50600436106101d95760003560e01c80638129fc1c11610104578063a25eb31c116100a2578063db5d91b111610071578063db5d91b114610475578063e34fbfc8146104a1578063e874eb20146104b4578063f2fde38b146104c757600080fd5b8063a25eb31c1461042c578063a4ab2faa1461043f578063a52f433c14610452578063d4fab8871461046257600080fd5b806387059edb116100de57806387059edb146103a95780638da5cb5b146103bc57806398077e86146103ec578063a1a227fa1461040c57600080fd5b80638129fc1c1461035d5780638236a7ba14610365578063841548261461038657600080fd5b8063476657381161017c5780636a30d26c1161014b5780636a30d26c146103255780636b9707d61461033a578063715018a61461034d578063728109961461035557600080fd5b806347665738146102cb5780635371a216146102de578063568699c8146102f157806368e103831461031257600080fd5b80632f0cb9e3116101b85780632f0cb9e3146102255780633e60a22f1461025557806343348b2f14610296578063440c953b146102c257600080fd5b80620ddd27146101de57806303e72e48146101fd578063073b6ef314610212575b600080fd5b6101e7600e5481565b6040516101f49190611a56565b60405180910390f35b61021061020b366004611b8c565b6104da565b005b610210610220366004611d01565b6105e2565b610248610233366004611dcf565b600c6020526000908152604090205460ff1681565b6040516101f49190611df6565b610289610263366004611e04565b80516020818301810180516003825292820191909301209152546001600160a01b031681565b6040516101f49190611e50565b6102486102a4366004611e5e565b6001600160a01b031660009081526020819052604090205460ff1690565b6101e760055481565b6102106102d9366004611e5e565b6107d9565b6102106102ec366004611ee3565b610879565b6103046102ff366004611dcf565b610a1e565b6040516101f4929190611fe5565b610210610320366004612005565b610a74565b61032d610b18565b6040516101f49190612108565b610210610348366004611e5e565b610bf1565b610210610c81565b610210610c95565b610210610d1a565b610378610373366004611dcf565b610ef5565b6040516101f4929190612119565b610248610394366004611dcf565b600d6020526000908152604090205460ff1681565b6103786103b7366004611dcf565b610fdd565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b0316610289565b6103ff6103fa366004611dcf565b611054565b6040516101f49190612127565b600a5461041f906001600160a01b031681565b6040516101f4919061217a565b61021061043a3660046121b2565b611100565b61024861044d366004612224565b611208565b600454610100900460ff16610248565b610210610470366004612272565b611286565b610248610483366004611e5e565b6001600160a01b031660009081526001602052604090205460ff1690565b6102106104af366004612319565b61138e565b600b5461041f906001600160a01b031681565b6102106104d5366004611e5e565b6113d5565b6104e261142c565b60006001600160a01b03166003836040516104fd9190612383565b908152604051908190036020019020546001600160a01b03160361055957600280546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace01610557838261245f565b505b8060038360405161056a9190612383565b90815260405190819003602001812080546001600160a01b039390931673ffffffffffffffffffffffffffffffffffffffff19909316929092179091557f17b2f9f5748931099ffee882b5b64f4a560b5c55da9b4f4e396dae3bb9f98cb5906105d6908490849061251f565b60405180910390a15050565b60008281526008602052604090205481146106185760405162461bcd60e51b815260040161060f90612571565b60405180910390fd5b60006106868989898960405160200161063494939291906125d9565b6040516020818303038152906040528051906020012086868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506114a092505050565b6001600160a01b03811660009081526020819052604090205490915060ff166106c15760405162461bcd60e51b815260040161060f9061264f565b600e8990556000805b87518110156107b457600b5488516001600160a01b039091169063b6aed0cb908a90849081106106fc576106fc61265f565b602002602001015161070d9061267f565b426040518363ffffffff1660e01b815260040161072b9291906126b5565b600060405180830381600087803b15801561074557600080fd5b505af1158015610759573d6000803e3d6000fd5b50505050818882815181106107705761077061265f565b60200260200101516107819061267f565b6040516020016107929291906126b5565b60408051601f19818403018152919052805160209091012091506001016106ca565b506000908152600d60205260409020805460ff19166001179055505050505050505050565b6107e161142c565b6001600160a01b03811660009081526020819052604090205460ff166108195760405162461bcd60e51b815260040161060f9061264f565b6001600160a01b038116600090815260016020819052604091829020805460ff19169091179055517ffe64c7181f0fc60e300dc02cca368cdfa94d7ca45902de3b9a9d80070e7609369061086e908390611e50565b60405180910390a150565b600b546040517fb201246f0000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063b201246f906108c89087908790879087906004016127eb565b60006040518083038186803b1580156108e057600080fd5b505afa1580156108f4573d6000803e3d6000fd5b5050505060008460405160200161090b9190612824565b60408051601f1981840301815291815281516020928301206000818152600c90935291205490915060ff16156109535760405162461bcd60e51b815260040161060f90612864565b6001600c60008760405160200161096a9190612824565b60408051808303601f190181529181528151602092830120835282820193909352908201600020805460ff191693151593909317909255600a546001600160a01b0316916399a3ad21916109c391908901908901611e5e565b87604001356040518363ffffffff1660e01b81526004016109e5929190612874565b600060405180830381600087803b1580156109ff57600080fd5b505af1158015610a13573d6000803e3d6000fd5b505050505050505050565b604080516060808201835260008083526020830191909152918101829052600080610a4885610fdd565b9150915081610a5d5760009590945092505050565b600094855260086020526040909420549492505050565b60045460ff1615610a975760405162461bcd60e51b815260040161060f906128dc565b60048054600160ff1991821681179092556001600160a01b0387166000908152602081815260408083208054851686179055908490529081902080549092169092179055517ffe64c7181f0fc60e300dc02cca368cdfa94d7ca45902de3b9a9d80070e76093690610b09908790611e50565b60405180910390a15050505050565b60606002805480602002602001604051908101604052809291908181526020016000905b82821015610be8578382906000526020600020018054610b5b906123a3565b80601f0160208091040260200160405190810160405280929190818152602001828054610b87906123a3565b8015610bd45780601f10610ba957610100808354040283529160200191610bd4565b820191906000526020600020905b815481529060010190602001808311610bb757829003601f168201915b505050505081526020019060010190610b3c565b50505050905090565b610bf961142c565b6001600160a01b03811660009081526001602052604090205460ff16610c315760405162461bcd60e51b815260040161060f9061291e565b6001600160a01b03811660009081526001602052604090819020805460ff19169055517f0f279980343c7ca542fde9fa5396555068efb5cd560d9cf9c191aa2911079b479061086e908390611e50565b610c8961142c565b610c9360006114cc565b565b610c9d61142c565b600a546040517f36d2da900000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906336d2da9090610ce6903390600401611e50565b600060405180830381600087803b158015610d0057600080fd5b505af1158015610d14573d6000803e3d6000fd5b50505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015610d655750825b905060008267ffffffffffffffff166001148015610d825750303b155b905081158015610d90575080155b15610dc7576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610dfb57845468ff00000000000000001916680100000000000000001785555b610e043361154a565b60006005556001600955604051610e1a90611a41565b604051809103906000f080158015610e36573d6000803e3d6000fd5b50600b80546001600160a01b039290921673ffffffffffffffffffffffffffffffffffffffff199283168117909155600a805490921681179091556040517fbd726cf82ac9c3260b1495107182e336e0654b25c10915648c0cc15b2bb72cbf91610e9f91611e50565b60405180910390a18315610eee57845468ff0000000000000000191685556040517fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290610b0990600190612949565b5050505050565b604080516060808201835260008083526020808401839052838501829052858252600681528482208551938401909552845483526001850180549295869493909284019190610f43906123a3565b80601f0160208091040260200160405190810160405280929190818152602001828054610f6f906123a3565b8015610fbc5780601f10610f9157610100808354040283529160200191610fbc565b820191906000526020600020905b815481529060010190602001808311610f9f57829003601f168201915b50505091835250506002919091015460209091015280519094149492505050565b6040805160608082018352600080835260208301919091529181018290526000838152600760205260408120549081900361104157505060408051606081018252600080825282516020818101855282825283015291810182905290939092509050565b61104a81610ef5565b9250925050915091565b6002818154811061106457600080fd5b90600052602060002001600091509050805461107f906123a3565b80601f01602080910402602001604051908101604052809291908181526020018280546110ab906123a3565b80156110f85780601f106110cd576101008083540402835291602001916110f8565b820191906000526020600020905b8154815290600101906020018083116110db57829003601f168201915b505050505081565b600061114e83356111146020860186612957565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506114a092505050565b6001600160a01b03811660009081526020819052604090205490915060ff166111895760405162461bcd60e51b815260040161060f9061264f565b6001600160a01b03811660009081526001602052604090205460ff166111c15760405162461bcd60e51b815260040161060f9061291e565b6111ca8361155b565b6040517fd6555bff8670bd3008dc064c30bb56d6ac7cb14ae801e36146fe4e7c6a504a58906111fb90853590611a56565b60405180910390a1505050565b600080805b835181101561126d57818482815181106112295761122961265f565b602002602001015161123a9061267f565b60405160200161124b9291906126b5565b60408051601f198184030181529190528051602090910120915060010161120d565b506000908152600d602052604090205460ff1692915050565b6001600160a01b03851660009081526020819052604090205460ff16806112bf5760405162461bcd60e51b815260040161060f90612a04565b81156113375760006112f38787866040516020016112df93929190612a3c565b6040516020818303038152906040526115ff565b9050600061130182876114a0565b9050876001600160a01b0316816001600160a01b0316146113345760405162461bcd60e51b815260040161060f90612ab8565b50505b6001600160a01b03808616600081815260208190526040808220805460ff191660011790555191928916917fb869e23ebc7c717d76e345eee8ec282612603e45c44f7ae5494b197c8d9d1be19190a3505050505050565b336001600160a01b03167f0b0ecdedd12079aa2d6c5e0186026c711cb0c8d04f1b724ba5880fb6328d430183836040516113c9929190612ae8565b60405180910390a25050565b6113dd61142c565b6001600160a01b0381166114205760006040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161060f9190611e50565b611429816114cc565b50565b3361145e7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610c9357336040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040161060f9190611e50565b6000806000806114b0868661163a565b9250925092506114c08282611687565b50909150505b92915050565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b61155261178d565b611429816117f4565b8035600090815260066020526040902081906115778282612c5d565b5050600954600090815260076020526040902081359081905561159b600143612c7d565b406040516020016115ad9291906126b5565b60408051601f1981840301815291815281516020928301206009805460009081526008909452918320558054916115e383612c90565b9190505550600554816040013511156114295760400135600555565b600061160b82516117fc565b8260405160200161161d929190612ca9565b604051602081830303815290604052805190602001209050919050565b600080600083516041036116745760208401516040850151606086015160001a6116668882858561189d565b955095509550505050611680565b50508151600091506002905b9250925092565b600082600381111561169b5761169b612ce5565b036116a4575050565b60018260038111156116b8576116b8612ce5565b036116ef576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600282600381111561170357611703612ce5565b0361173c576040517ffce698f700000000000000000000000000000000000000000000000000000000815261060f908290600401611a56565b600382600381111561175057611750612ce5565b0361178957806040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260040161060f9190611a56565b5050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16610c93576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113dd61178d565b606060006118098361195f565b600101905060008167ffffffffffffffff81111561182957611829611a64565b6040519080825280601f01601f191660200182016040528015611853576020820181803683370190505b5090508181016020015b600019017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a850494508461185d575b509392505050565b600080807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411156118d85750600091506003905082611955565b6000600188888888604051600081526020016040526040516118fd9493929190612d04565b6020604051602081039080840390855afa15801561191f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661194b57506000925060019150829050611955565b9250600091508190505b9450945094915050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106119a8577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef810000000083106119d4576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106119f257662386f26fc10000830492506010015b6305f5e1008310611a0a576305f5e100830492506008015b6127108310611a1e57612710830492506004015b60648310611a30576064830492506002015b600a83106114c65760010192915050565b6125ae80612d3a83390190565b805b82525050565b602081016114c68284611a4e565b634e487b7160e01b600052604160045260246000fd5b601f19601f830116810181811067ffffffffffffffff82111715611aa057611aa0611a64565b6040525050565b6000611ab260405190565b9050611abe8282611a7a565b919050565b600067ffffffffffffffff821115611add57611add611a64565b601f19601f83011660200192915050565b82818337506000910152565b6000611b0d611b0884611ac3565b611aa7565b9050828152838383011115611b2457611b24600080fd5b611b32836020830184611aee565b9392505050565b600082601f830112611b4d57611b4d600080fd5b611b3283833560208501611afa565b60006001600160a01b0382166114c6565b611b7681611b5c565b811461142957600080fd5b80356114c681611b6d565b60008060408385031215611ba257611ba2600080fd5b823567ffffffffffffffff811115611bbc57611bbc600080fd5b611bc885828601611b39565b925050611bd88460208501611b81565b90509250929050565b80611b76565b80356114c681611be1565b600067ffffffffffffffff821115611c0c57611c0c611a64565b5060209081020190565b6000611c24611b0884611bf2565b83815290506020808201908402830185811115611c4357611c43600080fd5b835b81811015611c8257803567ffffffffffffffff811115611c6757611c67600080fd5b611c7388828801611b39565b84525060209283019201611c45565b5050509392505050565b600082601f830112611ca057611ca0600080fd5b611b3283833560208501611c16565b60008083601f840112611cc457611cc4600080fd5b50813567ffffffffffffffff811115611cdf57611cdf600080fd5b602083019150836001820283011115611cfa57611cfa600080fd5b9250929050565b60008060008060008060008060e0898b031215611d2057611d20600080fd5b611d2a8a8a611be7565b9750611d398a60208b01611be7565b9650611d488a60408b01611be7565b9550606089013567ffffffffffffffff811115611d6757611d67600080fd5b611d738b828c01611c8c565b955050608089013567ffffffffffffffff811115611d9357611d93600080fd5b611d9f8b828c01611caf565b9450945050611db18a60a08b01611be7565b9150611dc08a60c08b01611be7565b90509295985092959890939650565b600060208284031215611de457611de4600080fd5b611b328383611be7565b801515611a50565b602081016114c68284611dee565b600060208284031215611e1957611e19600080fd5b813567ffffffffffffffff811115611e3357611e33600080fd5b611e3f84828501611b39565b949350505050565b611a5081611b5c565b602081016114c68284611e47565b600060208284031215611e7357611e73600080fd5b611b328383611b81565b600060808284031215611e9257611e92600080fd5b50919050565b60008083601f840112611ead57611ead600080fd5b50813567ffffffffffffffff811115611ec857611ec8600080fd5b602083019150836020820283011115611cfa57611cfa600080fd5b60008060008060c08587031215611efc57611efc600080fd5b611f068686611e7d565b9350608085013567ffffffffffffffff811115611f2557611f25600080fd5b611f3187828801611e98565b9350935050611f438660a08701611be7565b905092959194509250565b60005b83811015611f69578181015183820152602001611f51565b50506000910152565b6000611f7c825190565b808452602084019350611f93818560208601611f4e565b601f01601f19169290920192915050565b80516000906060840190611fb88582611a4e565b5060208301518482036020860152611fd08282611f72565b91505060408301516118956040860182611a4e565b60408101611ff38285611a4e565b8181036020830152611e3f8184611fa4565b60008060008060006060868803121561202057612020600080fd5b61202a8787611b81565b9450602086013567ffffffffffffffff81111561204957612049600080fd5b61205588828901611caf565b9450945050604086013567ffffffffffffffff81111561207757612077600080fd5b61208388828901611caf565b92509250509295509295909350565b6000611b328383611f72565b60200190565b60006120ae825190565b808452602084019350836020820285016120c88560200190565b60005b848110156120fc57838303885281516120e48482612092565b935050602082016020989098019791506001016120cb565b50909695505050505050565b60208082528101611b3281846120a4565b60408101611ff38285611dee565b60208082528101611b328184611f72565b60006114c66001600160a01b03831661214f565b90565b6001600160a01b031690565b60006114c682612138565b60006114c68261215b565b611a5081612166565b602081016114c68284612171565b600060608284031215611e9257611e92600080fd5b600060208284031215611e9257611e92600080fd5b600080604083850312156121c8576121c8600080fd5b823567ffffffffffffffff8111156121e2576121e2600080fd5b6121ee85828601612188565b925050602083013567ffffffffffffffff81111561220e5761220e600080fd5b61221a8582860161219d565b9150509250929050565b60006020828403121561223957612239600080fd5b813567ffffffffffffffff81111561225357612253600080fd5b611e3f84828501611c8c565b801515611b76565b80356114c68161225f565b600080600080600060a0868803121561228d5761228d600080fd5b6122978787611b81565b94506122a68760208801611b81565b9350604086013567ffffffffffffffff8111156122c5576122c5600080fd5b6122d188828901611b39565b935050606086013567ffffffffffffffff8111156122f1576122f1600080fd5b6122fd88828901611b39565b92505061230d8760808801612267565b90509295509295909350565b6000806020838503121561232f5761232f600080fd5b823567ffffffffffffffff81111561234957612349600080fd5b61235585828601611caf565b92509250509250929050565b600061236b825190565b612379818560208601611f4e565b9290920192915050565b6114c68183612361565b634e487b7160e01b600052602260045260246000fd5b6002810460018216806123b757607f821691505b602082108103611e9257611e9261238d565b60006114c661214c8381565b6123de836123c9565b815460001960089490940293841b1916921b91909117905550565b60006124068184846123d5565b505050565b818110156117895761241e6000826123f9565b60010161240b565b601f821115612406576000818152602090206020601f8501048101602085101561244d5750805b610eee6020601f86010483018261240b565b815167ffffffffffffffff81111561247957612479611a64565b61248382546123a3565b61248e828285612426565b506020601f8211600181146124c357600083156124ab5750848201515b600019600885021c1981166002850217855550610eee565b600084815260208120601f198516915b828110156124f357878501518255602094850194600190920191016124d3565b50848210156125105783870151600019601f87166008021c191681555b50505050600202600101905550565b604080825281016125308185611f72565b9050611b326020830184611e47565b600e8152602081017f496e76616c696420666f726b49440000000000000000000000000000000000008152905061209e565b602080825281016114c68161253f565b600061258b825190565b808452602084019350836020820285016125a58560200190565b60005b848110156120fc57838303885281516125c18482612092565b935050602082016020989098019791506001016125a8565b608081016125e78287611a4e565b6125f46020830186611a4e565b6126016040830185611a4e565b81810360608301526126138184612581565b9695505050505050565b60168152602081017f656e636c6176654944206e6f74206174746573746564000000000000000000008152905061209e565b602080825281016114c68161261d565b634e487b7160e01b600052603260045260246000fd5b60006114c6825190565b6000612689825190565b6020830161269681612675565b9250506020811015611e92576000196020919091036008021b16919050565b604081016126c38285611a4e565b611b326020830184611a4e565b5060006114c66020830183611b81565b5060006114c66020830183611be7565b67ffffffffffffffff8116611b76565b80356114c6816126f0565b5060006114c66020830183612700565b67ffffffffffffffff8116611a50565b61273581806126d0565b61273f8382611e47565b5061274d60208201826126d0565b61275a6020840182611e47565b5061276860408201826126e0565b6127756040840182611a4e565b50612783606082018261270b565b612406606084018261271b565b82818337505050565b81835260208301925060007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156127d4576127d4600080fd5b6020830292506127e5838584612790565b50500190565b60c081016127f9828761272b565b818103608083015261280c818587612799565b905061281b60a0830184611a4e565b95945050505050565b608081016114c6828461272b565b60188152602081017f7769746864726177616c20616c7265616479207370656e7400000000000000008152905061209e565b602080825281016114c681612832565b604081016126c38285611e47565b60228152602081017f6e6574776f726b2073656372657420616c726561647920696e697469616c697a81527f6564000000000000000000000000000000000000000000000000000000000000602082015290505b60400190565b602080825281016114c681612882565b60198152602081017f656e636c6176654944206e6f7420612073657175656e636572000000000000008152905061209e565b602080825281016114c6816128ec565b600067ffffffffffffffff82166114c6565b611a508161292e565b602081016114c68284612940565b6000808335601e193685900301811261297257612972600080fd5b8301915050803567ffffffffffffffff81111561299157612991600080fd5b602082019150600181023603821315611cfa57611cfa600080fd5b60238152602081017f726573706f6e64696e67206174746573746572206973206e6f7420617474657381527f7465640000000000000000000000000000000000000000000000000000000000602082015290506128d6565b602080825281016114c6816129ac565b60006114c68260601b90565b60006114c682612a14565b611a50612a3782611b5c565b612a20565b612a468185612a2b565b601401612a538184612a2b565b601401611e3f8183612361565b602c8152602081017f63616c63756c61746564206164647265737320616e642061747465737465724981527f4420646f6e74206d617463680000000000000000000000000000000000000000602082015290506128d6565b602080825281016114c681612a60565b818352602083019250612adc828483611aee565b50601f01601f19160190565b60208082528101611e3f818486612ac8565b600081356114c681611be1565b6000816114c6565b612b1882612b07565b612b2461214c82612b07565b8255505050565b8267ffffffffffffffff811115612b4457612b44611a64565b612b4e82546123a3565b612b59828285612426565b506000601f821160018114612b8e5760008315612b765750848201355b600019600885021c1981166002850217855550612be8565b600084815260209020601f19841690835b82811015612bbf5787850135825560209485019460019092019101612b9f565b5084821015612bdc576000196008601f8716021c19878501351681555b50506001600284020184555b505050505050565b612406838383612b2b565b612c04826123c9565b80612b24565b8180612c1581612afa565b9050612c218184612b0f565b5050612c306020830183612957565b612c3e818360018601612bf0565b50506040820180612c4e82612afa565b9050610d148160028501612bfb565b6117898282612c0a565b634e487b7160e01b600052601160045260246000fd5b818103818111156114c6576114c6612c67565b600060018201612ca257612ca2612c67565b5060010190565b7f19457468657265756d205369676e6564204d6573736167653a0a0000000000008152601a01612cd98184612361565b9050611b328183612361565b634e487b7160e01b600052602160045260246000fd5b60ff8116611a50565b60808101612d128287611a4e565b612d1f6020830186612cfb565b612d2c6040830185611a4e565b61281b6060830184611a4e56fe608060405234801561001057600080fd5b5061001a33610027565b610022610098565b61014a565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100e85760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146101475780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b612455806101596000396000f3fe6080604052600436106101115760003560e01c80638da5cb5b116100a5578063b1454caa11610074578063b6aed0cb11610059578063b6aed0cb1461038b578063e138a8d2146103ab578063f2fde38b146103cb57610185565b8063b1454caa1461034b578063b201246f1461036b57610185565b80638da5cb5b146102a65780639730886d146102eb57806399a3ad211461030b578063ab53bddc1461032b57610185565b8063346633fb116100e1578063346633fb1461023e57806336d2da9014610251578063485cc95514610271578063715018a61461029157610185565b8062a1b815146101a65780630fcfbd11146101d15780630fe9188e146101f157806333a88c721461021157610185565b36610185576040517f346633fb000000000000000000000000000000000000000000000000000000008152309063346633fb90349061015690339083906004016111ea565b6000604051808303818588803b15801561016f57600080fd5b505af1158015610183573d6000803e3d6000fd5b005b60405162461bcd60e51b815260040161019d90611239565b60405180910390fd5b3480156101b257600080fd5b506101bb6103eb565b6040516101c89190611249565b60405180910390f35b3480156101dd57600080fd5b506101bb6101ec366004611272565b610477565b3480156101fd57600080fd5b5061018361020c3660046112c5565b6104d6565b34801561021d57600080fd5b5061023161022c366004611272565b61051c565b6040516101c891906112ec565b61018361024c36600461130e565b61056e565b34801561025d57600080fd5b5061018361026c366004611346565b6106bd565b34801561027d57600080fd5b5061018361028c366004611365565b61073c565b34801561029d57600080fd5b506101836108a7565b3480156102b257600080fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b03166040516101c89190611394565b3480156102f757600080fd5b506101836103063660046113a2565b6108bb565b34801561031757600080fd5b5061018361032636600461130e565b610a27565b34801561033757600080fd5b5061018361034636600461130e565b610aa7565b61035e61035936600461146b565b610b70565b6040516101c891906114f8565b34801561037757600080fd5b50610183610386366004611566565b610c7d565b34801561039757600080fd5b506101836103a63660046115d1565b610d7e565b3480156103b757600080fd5b506101836103c63660046115f1565b610dc4565b3480156103d757600080fd5b506101836103e6366004611346565b610f0f565b600354604080517f1a90a21900000000000000000000000000000000000000000000000000000000815290516000926001600160a01b031691631a90a2199160048083019260209291908290030181865afa15801561044e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104729190611679565b905090565b6000808260405160200161048b9190611837565b60408051601f198184030181529181528151602092830120600081815292839052912054909150806104cf5760405162461bcd60e51b815260040161019d90611886565b9392505050565b6104de610f66565b600081815260046020526040812054900361050b5760405162461bcd60e51b815260040161019d906118c8565b600090815260046020526040812055565b600080826040516020016105309190611837565b60408051601f19818403018152918152815160209283012060008181529283905291205490915080158015906105665750428111155b949350505050565b60003411801561057d57508034145b6105995760405162461bcd60e51b815260040161019d90611930565b60035434906001600160a01b03161561065d5760006105b66103eb565b9050803410156105d85760405162461bcd60e51b815260040161019d90611970565b6105e28134611996565b6003546040519193506000916001600160a01b039091169083908381818185875af1925050503d8060008114610634576040519150601f19603f3d011682016040523d82523d6000602084013e610639565b606091505b505090508061065a5760405162461bcd60e51b815260040161019d90611a01565b50505b600061066833610fda565b9050836001600160a01b0316336001600160a01b03167f50c536ac33a920f00755865b831d17bf4cff0b2e0345f65b16d52bfc004068b684846040516106af929190611a11565b60405180910390a350505050565b6106c5610f66565b6000816001600160a01b03164760405160006040518083038185875af1925050503d8060008114610712576040519150601f19603f3d011682016040523d82523d6000602084013e610717565b606091505b50509050806107385760405162461bcd60e51b815260040161019d90611a5e565b5050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff166000811580156107875750825b905060008267ffffffffffffffff1660011480156107a45750303b155b9050811580156107b2575080155b156107e9576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561081d57845468ff00000000000000001916680100000000000000001785555b61082687611038565b6003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b038816179055831561089e57845468ff0000000000000000191685556040517fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29061089590600190611a92565b60405180910390a15b50505050505050565b6108af610f66565b6108b96000611049565b565b60006108c8600130611aa0565b90506108fb7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316336001600160a01b031614806109225750336001600160a01b038216145b61093e5760405162461bcd60e51b815260040161019d90611af5565b600061094a8342611b05565b905060008460405160200161095f9190611837565b60408051601f198184030181529181528151602092830120600081815292839052912054909150156109a35760405162461bcd60e51b815260040161019d90611b70565b6000818152602081815260408220849055600191906109c490880188611346565b6001600160a01b0316815260208101919091526040016000908120906109f06080880160608901611b80565b63ffffffff1681526020808201929092526040016000908120805460018101825590825291902086916004020161089e8282611fbe565b610a2f610f66565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610a7c576040519150601f19603f3d011682016040523d82523d6000602084013e610a81565b606091505b5050905080610aa25760405162461bcd60e51b815260040161019d90611a5e565b505050565b6000610ab4600130611aa0565b9050610ae77f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316336001600160a01b03161480610b0e5750336001600160a01b038216145b610b2a5760405162461bcd60e51b815260040161019d90611af5565b826001600160a01b03167fcd9850463422a7449c406a036e35e5edb6fbe35a64c9f12a2354be98a750c0d383604051610b639190611249565b60405180910390a2505050565b6003546000906001600160a01b031615610c26576000610b8e6103eb565b905080341015610bb05760405162461bcd60e51b815260040161019d90612020565b6003546040516000916001600160a01b03169083908381818185875af1925050503d8060008114610bfd576040519150601f19603f3d011682016040523d82523d6000602084013e610c02565b606091505b5050905080610c235760405162461bcd60e51b815260040161019d90611a01565b50505b610c2f33610fda565b90507fb93c37389233beb85a3a726c3f15c2d15533ee74cb602f20f490dfffef77593733828888888888604051610c6c9796959493929190612030565b60405180910390a195945050505050565b6000818152600460205260408120549003610caa5760405162461bcd60e51b815260040161019d906120eb565b600081815260046020526040902054421015610cd85760405162461bcd60e51b815260040161019d90612137565b600084604051602001610ceb91906121bc565b60405160208183030381529060405280519060200120604051602001610d1191906121fc565b604051602081830303815290604052805190602001209050610d5b84848484604051602001610d40919061221b565b604051602081830303815290604052805190602001206110c7565b610d775760405162461bcd60e51b815260040161019d90612285565b5050505050565b610d86610f66565b60008281526004602052604090205415610db25760405162461bcd60e51b815260040161019d906122ed565b60009182526004602052604090912055565b6000818152600460205260408120549003610df15760405162461bcd60e51b815260040161019d906120eb565b600081815260046020526040902054421015610e1f5760405162461bcd60e51b815260040161019d90612137565b6000610e2e6020860186611346565b610e3e60408701602088016122fd565b610e4e6060880160408901611b80565b610e5e6080890160608a01611b80565b610e6b60808a018a611cd7565b610e7b60c08c0160a08d0161231c565b604051602001610e919796959493929190612030565b604051602081830303815290604052805190602001209050600081604051602001610ebc919061236d565b604051602081830303815290604052805190602001209050610eeb85858584604051602001610d40919061221b565b610f075760405162461bcd60e51b815260040161019d906123d5565b505050505050565b610f17610f66565b6001600160a01b038116610f5a5760006040517f1e4fbdf700000000000000000000000000000000000000000000000000000000815260040161019d9190611394565b610f6381611049565b50565b33610f987f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146108b957336040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040161019d9190611394565b6001600160a01b0381166000908152600260205260408120805467ffffffffffffffff16916001919061100d83856123e5565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550919050565b6110406110df565b610f6381611146565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6000826110d586868561114e565b1495945050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff166108b9576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f176110df565b600081815b848110156111875761117d8287878481811061117157611171612409565b90506020020135611190565b9150600101611153565b50949350505050565b60008183106111ac5760008281526020849052604090206111bb565b60008381526020839052604090205b90505b92915050565b60006001600160a01b0382166111be565b6111de816111c4565b82525050565b806111de565b604081016111f882856111d5565b6104cf60208301846111e4565b600b8152602081017f756e737570706f72746564000000000000000000000000000000000000000000815290505b60200190565b602080825281016111be81611205565b602081016111be82846111e4565b600060c0828403121561126c5761126c600080fd5b50919050565b60006020828403121561128757611287600080fd5b813567ffffffffffffffff8111156112a1576112a1600080fd5b61056684828501611257565b805b8114610f6357600080fd5b80356111be816112ad565b6000602082840312156112da576112da600080fd5b6111bb83836112ba565b8015156111de565b602081016111be82846112e4565b6112af816111c4565b80356111be816112fa565b6000806040838503121561132457611324600080fd5b61132e8484611303565b915061133d84602085016112ba565b90509250929050565b60006020828403121561135b5761135b600080fd5b6111bb8383611303565b6000806040838503121561137b5761137b600080fd5b6113858484611303565b915061133d8460208501611303565b602081016111be82846111d5565b600080604083850312156113b8576113b8600080fd5b823567ffffffffffffffff8111156113d2576113d2600080fd5b6113de85828601611257565b92505061133d84602085016112ba565b63ffffffff81166112af565b80356111be816113ee565b60008083601f84011261141a5761141a600080fd5b50813567ffffffffffffffff81111561143557611435600080fd5b60208301915083600182028301111561145057611450600080fd5b9250929050565b60ff81166112af565b80356111be81611457565b60008060008060006080868803121561148657611486600080fd5b61149087876113fa565b945061149f87602088016113fa565b9350604086013567ffffffffffffffff8111156114be576114be600080fd5b6114ca88828901611405565b93509350506114dc8760608801611460565b90509295509295909350565b67ffffffffffffffff81166111de565b602081016111be82846114e8565b60006080828403121561126c5761126c600080fd5b60008083601f84011261153057611530600080fd5b50813567ffffffffffffffff81111561154b5761154b600080fd5b60208301915083602082028301111561145057611450600080fd5b60008060008060c0858703121561157f5761157f600080fd5b6115898686611506565b9350608085013567ffffffffffffffff8111156115a8576115a8600080fd5b6115b48782880161151b565b93509350506115c68660a087016112ba565b905092959194509250565b600080604083850312156115e7576115e7600080fd5b61132e84846112ba565b6000806000806060858703121561160a5761160a600080fd5b843567ffffffffffffffff81111561162457611624600080fd5b61163087828801611257565b945050602085013567ffffffffffffffff81111561165057611650600080fd5b61165c8782880161151b565b93509350506115c686604087016112ba565b80516111be816112ad565b60006020828403121561168e5761168e600080fd5b6111bb838361166e565b5060006111be6020830183611303565b67ffffffffffffffff81166112af565b80356111be816116a8565b5060006111be60208301836116b8565b5060006111be60208301836113fa565b63ffffffff81166111de565b6000808335601e193685900301811261170a5761170a600080fd5b830160208101925035905067ffffffffffffffff81111561172d5761172d600080fd5b3681900382131561145057611450600080fd5b82818337506000910152565b818352602083019250611760828483611740565b50601f01601f19160190565b5060006111be6020830183611460565b60ff81166111de565b600060c083016117958380611698565b61179f85826111d5565b506117ad60208401846116c3565b6117ba60208601826114e8565b506117c860408401846116d3565b6117d560408601826116e3565b506117e360608401846116d3565b6117f060608601826116e3565b506117fe60808401846116ef565b858303608087015261181183828461174c565b9250505061182260a084018461176c565b61182f60a086018261177c565b509392505050565b602080825281016111bb8184611785565b60218152602081017f54686973206d65737361676520776173206e65766572207375626d69747465648152601760f91b602082015290505b60400190565b602080825281016111be81611848565b601a8152602081017f537461746520726f6f7420646f6573206e6f742065786973742e00000000000081529050611233565b602080825281016111be81611896565b60308152602081017f417474656d7074696e6720746f2073656e642076616c756520776974686f757481527f2070726f766964696e672045746865720000000000000000000000000000000060208201529050611880565b602080825281016111be816118d8565b60208082527f496e73756666696369656e742066756e647320746f2073656e642076616c75659101908152611233565b602080825281016111be81611940565b634e487b7160e01b600052601160045260246000fd5b818103818111156111be576111be611980565b60248152602081017f4661696c656420746f2073656e64206665657320746f206665657320636f6e7481527f726163740000000000000000000000000000000000000000000000000000000060208201529050611880565b602080825281016111be816119a9565b60408101611a1f82856111e4565b6104cf60208301846114e8565b60148152602081017f6661696c65642073656e64696e672076616c756500000000000000000000000081529050611233565b602080825281016111be81611a2c565b60006111be82611a7c565b90565b67ffffffffffffffff1690565b6111de81611a6e565b602081016111be8284611a89565b6001600160a01b039182169190811690828203908111156111be576111be611980565b60118152602081017f4e6f74206f776e6572206f722073656c6600000000000000000000000000000081529050611233565b602080825281016111be81611ac3565b808201808211156111be576111be611980565b60218152602081017f4d657373616765207375626d6974746564206d6f7265207468616e206f6e636581527f210000000000000000000000000000000000000000000000000000000000000060208201529050611880565b602080825281016111be81611b18565b600060208284031215611b9557611b95600080fd5b6111bb83836113fa565b600081356111be816112fa565b60006001600160a01b03835b81169019929092169190911792915050565b60006111be826111c4565b60006111be82611bca565b611be982611bd5565b611bf4818354611bac565b8255505050565b600081356111be816116a8565b60007bffffffffffffffff0000000000000000000000000000000000000000611bb88460a01b90565b60006111be67ffffffffffffffff8316611a7c565b611c4f82611c31565b611bf4818354611c08565b600081356111be816113ee565b60007fffffffff00000000000000000000000000000000000000000000000000000000611bb88460e01b90565b600063ffffffff82166111be565b611cab82611c94565b611bf4818354611c67565b600063ffffffff83611bb8565b611ccc82611c94565b611bf4818354611cb6565b6000808335601e1936859003018112611cf257611cf2600080fd5b8301915050803567ffffffffffffffff811115611d1157611d11600080fd5b60208201915060018102360382131561145057611450600080fd5b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052602260045260246000fd5b600281046001821680611d6c57607f821691505b60208210810361126c5761126c611d42565b60006111be611a798381565b611d9383611d7e565b815460001960089490940293841b1916921b91909117905550565b6000610aa2818484611d8a565b8181101561073857611dce600082611dae565b600101611dbb565b601f821115610aa2576000818152602090206020601f85010481016020851015611dfd5750805b610d776020601f860104830182611dbb565b8267ffffffffffffffff811115611e2857611e28611d2c565b611e328254611d58565b611e3d828285611dd6565b506000601f821160018114611e725760008315611e5a5750848201355b600019600885021c1981166002850217855550610f07565b600084815260209020601f19841690835b82811015611ea35787850135825560209485019460019092019101611e83565b5084821015611ec0576000196008601f8716021c19878501351681555b5050505060020260010190555050565b610aa2838383611e0f565b600081356111be81611457565b600060ff82166111be565b611efc82611ee8565b815460ff191660ff821617611bf4565b808280611f1881611b9f565b9050611f248184611be0565b50506020830180611f3482611bfb565b9050611f408184611c46565b50506040830180611f5082611c5a565b9050611f5c8184611ca2565b5050506060820180611f6d82611c5a565b9050611f7c8160018501611cc3565b5050611f8b6080830183611cd7565b611f99818360028601611ed0565b505060a0820180611fa982611edb565b9050611fb88160038501611ef3565b50505050565b6107388282611f0c565b60258152602081017f496e73756666696369656e742066756e647320746f207075626c697368206d6581527f737361676500000000000000000000000000000000000000000000000000000060208201529050611880565b602080825281016111be81611fc8565b60c0810161203e828a6111d5565b61204b60208301896114e8565b61205860408301886116e3565b61206560608301876116e3565b818103608083015261207881858761174c565b905061208760a083018461177c565b98975050505050505050565b602a8152602081017f526f6f74206973206e6f74207075626c6973686564206f6e2074686973206d6581527f7373616765206275732e0000000000000000000000000000000000000000000060208201529050611880565b602080825281016111be81612093565b60218152602081017f526f6f74206973206e6f7420636f6e736964657265642066696e616c207965748152601760f91b60208201529050611880565b602080825281016111be816120fb565b5060006111be60208301836112ba565b6121618180611698565b61216b83826111d5565b506121796020820182611698565b61218660208401826111d5565b506121946040820182612147565b6121a160408401826111e4565b506121af60608201826116c3565b610aa260608401826114e8565b608081016111be8284612157565b60018152602081017f760000000000000000000000000000000000000000000000000000000000000081529050611233565b6040808252810161220c816121ca565b90506111be60208301846111e4565b61222581836111e4565b602001919050565b60338152602081017f496e76616c696420696e636c7573696f6e2070726f6f6620666f722076616c7581527f65207472616e73666572206d6573736167652e0000000000000000000000000060208201529050611880565b602080825281016111be8161222d565b60258152602081017f526f6f7420616c726561647920616464656420746f20746865206d657373616781527f652062757300000000000000000000000000000000000000000000000000000060208201529050611880565b602080825281016111be81612295565b60006020828403121561231257612312600080fd5b6111bb83836116b8565b60006020828403121561233157612331600080fd5b6111bb8383611460565b60018152602081017f6d0000000000000000000000000000000000000000000000000000000000000081529050611233565b6040808252810161220c8161233b565b60308152602081017f496e76616c696420696e636c7573696f6e2070726f6f6620666f722063726f7381527f7320636861696e206d6573736167652e0000000000000000000000000000000060208201529050611880565b602080825281016111be8161237d565b67ffffffffffffffff9182169190811690828201908111156111be576111be611980565b634e487b7160e01b600052603260045260246000fdfea26469706673582212209046d260e6ecf02a9b545045265133ebd2a8a091d8cfe42d8fe9829451348f2664736f6c634300081c0033a26469706673582212204fc49cf676f6209e494e1c7c64ce47f23c42b2af6d8db63f5317b2767b5e28b164736f6c634300081c0033", } // ManagementContractABI is the input ABI used to generate the binding from. @@ -1438,6 +1438,304 @@ func (_ManagementContract *ManagementContractFilterer) ParseLogManagementContrac return event, nil } +// ManagementContractNetworkSecretRequestedIterator is returned from FilterNetworkSecretRequested and is used to iterate over the raw logs and unpacked data for NetworkSecretRequested events raised by the ManagementContract contract. +type ManagementContractNetworkSecretRequestedIterator struct { + Event *ManagementContractNetworkSecretRequested // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ManagementContractNetworkSecretRequestedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ManagementContractNetworkSecretRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ManagementContractNetworkSecretRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ManagementContractNetworkSecretRequestedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ManagementContractNetworkSecretRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ManagementContractNetworkSecretRequested represents a NetworkSecretRequested event raised by the ManagementContract contract. +type ManagementContractNetworkSecretRequested struct { + Requester common.Address + RequestReport string + Raw types.Log // Blockchain specific contextual infos +} + +// FilterNetworkSecretRequested is a free log retrieval operation binding the contract event 0x0b0ecdedd12079aa2d6c5e0186026c711cb0c8d04f1b724ba5880fb6328d4301. +// +// Solidity: event NetworkSecretRequested(address indexed requester, string requestReport) +func (_ManagementContract *ManagementContractFilterer) FilterNetworkSecretRequested(opts *bind.FilterOpts, requester []common.Address) (*ManagementContractNetworkSecretRequestedIterator, error) { + + var requesterRule []interface{} + for _, requesterItem := range requester { + requesterRule = append(requesterRule, requesterItem) + } + + logs, sub, err := _ManagementContract.contract.FilterLogs(opts, "NetworkSecretRequested", requesterRule) + if err != nil { + return nil, err + } + return &ManagementContractNetworkSecretRequestedIterator{contract: _ManagementContract.contract, event: "NetworkSecretRequested", logs: logs, sub: sub}, nil +} + +// WatchNetworkSecretRequested is a free log subscription operation binding the contract event 0x0b0ecdedd12079aa2d6c5e0186026c711cb0c8d04f1b724ba5880fb6328d4301. +// +// Solidity: event NetworkSecretRequested(address indexed requester, string requestReport) +func (_ManagementContract *ManagementContractFilterer) WatchNetworkSecretRequested(opts *bind.WatchOpts, sink chan<- *ManagementContractNetworkSecretRequested, requester []common.Address) (event.Subscription, error) { + + var requesterRule []interface{} + for _, requesterItem := range requester { + requesterRule = append(requesterRule, requesterItem) + } + + logs, sub, err := _ManagementContract.contract.WatchLogs(opts, "NetworkSecretRequested", requesterRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ManagementContractNetworkSecretRequested) + if err := _ManagementContract.contract.UnpackLog(event, "NetworkSecretRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseNetworkSecretRequested is a log parse operation binding the contract event 0x0b0ecdedd12079aa2d6c5e0186026c711cb0c8d04f1b724ba5880fb6328d4301. +// +// Solidity: event NetworkSecretRequested(address indexed requester, string requestReport) +func (_ManagementContract *ManagementContractFilterer) ParseNetworkSecretRequested(log types.Log) (*ManagementContractNetworkSecretRequested, error) { + event := new(ManagementContractNetworkSecretRequested) + if err := _ManagementContract.contract.UnpackLog(event, "NetworkSecretRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ManagementContractNetworkSecretRespondedIterator is returned from FilterNetworkSecretResponded and is used to iterate over the raw logs and unpacked data for NetworkSecretResponded events raised by the ManagementContract contract. +type ManagementContractNetworkSecretRespondedIterator struct { + Event *ManagementContractNetworkSecretResponded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *ManagementContractNetworkSecretRespondedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(ManagementContractNetworkSecretResponded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(ManagementContractNetworkSecretResponded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *ManagementContractNetworkSecretRespondedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ManagementContractNetworkSecretRespondedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ManagementContractNetworkSecretResponded represents a NetworkSecretResponded event raised by the ManagementContract contract. +type ManagementContractNetworkSecretResponded struct { + Attester common.Address + Requester common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterNetworkSecretResponded is a free log retrieval operation binding the contract event 0xb869e23ebc7c717d76e345eee8ec282612603e45c44f7ae5494b197c8d9d1be1. +// +// Solidity: event NetworkSecretResponded(address indexed attester, address indexed requester) +func (_ManagementContract *ManagementContractFilterer) FilterNetworkSecretResponded(opts *bind.FilterOpts, attester []common.Address, requester []common.Address) (*ManagementContractNetworkSecretRespondedIterator, error) { + + var attesterRule []interface{} + for _, attesterItem := range attester { + attesterRule = append(attesterRule, attesterItem) + } + var requesterRule []interface{} + for _, requesterItem := range requester { + requesterRule = append(requesterRule, requesterItem) + } + + logs, sub, err := _ManagementContract.contract.FilterLogs(opts, "NetworkSecretResponded", attesterRule, requesterRule) + if err != nil { + return nil, err + } + return &ManagementContractNetworkSecretRespondedIterator{contract: _ManagementContract.contract, event: "NetworkSecretResponded", logs: logs, sub: sub}, nil +} + +// WatchNetworkSecretResponded is a free log subscription operation binding the contract event 0xb869e23ebc7c717d76e345eee8ec282612603e45c44f7ae5494b197c8d9d1be1. +// +// Solidity: event NetworkSecretResponded(address indexed attester, address indexed requester) +func (_ManagementContract *ManagementContractFilterer) WatchNetworkSecretResponded(opts *bind.WatchOpts, sink chan<- *ManagementContractNetworkSecretResponded, attester []common.Address, requester []common.Address) (event.Subscription, error) { + + var attesterRule []interface{} + for _, attesterItem := range attester { + attesterRule = append(attesterRule, attesterItem) + } + var requesterRule []interface{} + for _, requesterItem := range requester { + requesterRule = append(requesterRule, requesterItem) + } + + logs, sub, err := _ManagementContract.contract.WatchLogs(opts, "NetworkSecretResponded", attesterRule, requesterRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(ManagementContractNetworkSecretResponded) + if err := _ManagementContract.contract.UnpackLog(event, "NetworkSecretResponded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseNetworkSecretResponded is a log parse operation binding the contract event 0xb869e23ebc7c717d76e345eee8ec282612603e45c44f7ae5494b197c8d9d1be1. +// +// Solidity: event NetworkSecretResponded(address indexed attester, address indexed requester) +func (_ManagementContract *ManagementContractFilterer) ParseNetworkSecretResponded(log types.Log) (*ManagementContractNetworkSecretResponded, error) { + event := new(ManagementContractNetworkSecretResponded) + if err := _ManagementContract.contract.UnpackLog(event, "NetworkSecretResponded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + // ManagementContractOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the ManagementContract contract. type ManagementContractOwnershipTransferredIterator struct { Event *ManagementContractOwnershipTransferred // Event containing the contract specifics and raw log diff --git a/contracts/src/management/ManagementContract.sol b/contracts/src/management/ManagementContract.sol index ddae144828..f2029b62b4 100644 --- a/contracts/src/management/ManagementContract.sol +++ b/contracts/src/management/ManagementContract.sol @@ -26,6 +26,8 @@ contract ManagementContract is Initializable, OwnableUpgradeable { event SequencerEnclaveGranted(address enclaveID); event SequencerEnclaveRevoked(address enclaveID); event RollupAdded(bytes32 rollupHash); + event NetworkSecretRequested(address indexed requester, string requestReport); + event NetworkSecretResponded(address indexed attester, address indexed requester); // mapping of enclaveID to whether it is attested mapping(address => bool) private attested; @@ -113,13 +115,13 @@ contract ManagementContract is Initializable, OwnableUpgradeable { } 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"); - } + /* if (block.number > blockNum + 255) { + revert("Block binding too old"); + } - if ((blockhash(blockNum) != blockHash)) { - revert(string(abi.encodePacked("Invalid block binding:", Strings.toString(block.number),":", Strings.toString(uint256(blockHash)), ":", Strings.toString(uint256(blockhash(blockNum)))))); - } */ + if ((blockhash(blockNum) != blockHash)) { + 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"); @@ -178,7 +180,7 @@ contract ManagementContract is Initializable, OwnableUpgradeable { // Enclaves can request the Network Secret given an attestation request report function RequestNetworkSecret(string calldata requestReport) public { - // currently this is a no-op, nodes will monitor for these transactions and respond to them + emit NetworkSecretRequested(msg.sender, requestReport); } function ExtractNativeValue(MessageStructs.Structs.ValueTransferMessage calldata _msg, bytes32[] calldata proof, bytes32 root) external { @@ -200,7 +202,7 @@ contract ManagementContract is Initializable, OwnableUpgradeable { require(isEnclAttested, "responding attester is not attested"); if (verifyAttester) { - + // the data must be signed with by the correct private key // signature = f(PubKey, PrivateKey, message) // address = f(signature, message) @@ -213,6 +215,8 @@ contract ManagementContract is Initializable, OwnableUpgradeable { // mark the requesterID enclave as an attested enclave and store its host address attested[requesterID] = true; + + emit NetworkSecretResponded(attesterID, requesterID); } @@ -263,4 +267,4 @@ contract ManagementContract is Initializable, OwnableUpgradeable { function GetImportantContractKeys() public view returns(string[] memory) { return importantContractKeys; } -} +} \ No newline at end of file diff --git a/design/host/l1_block_processing.md b/design/host/l1_block_processing.md new file mode 100644 index 0000000000..9cbd50a491 --- /dev/null +++ b/design/host/l1_block_processing.md @@ -0,0 +1,75 @@ +# Standardizing L1 Data Processing + +## Requirements + +1. Standardise the way in which we process l1 blocks to find the relevant data needed for processing on the L2 +2. Reduce the processing load on the enclave + +## Current Problems +* Multiple redundant loops through L1 block data +* Inconsistent processing patterns +* Unnecessary load on the enclave +* Scattered responsibility for L1 data extraction + +## Proposed Solution + +Filter logs from blocks using the Management Contract and MessageBus Contract address. Build a map of emitted event types +against the transactions that created them. The events we care about: + +* Initialize secret +* Request Secret +* Secret Response +* Rollup +* Cross chain messages +* Value transfers +* Enclave granted sequencer +* Enclave sequencer revoked + +```go +const ( + RollupTx L1TxType = iota + InitialiseSecretTx + SecretRequestTx + SecretResponseTx + CrossChainMessageTx + CrossChainValueTranserTx + SequencerAddedTx + SequencerRevokedTx + SetImportantContractsTx +) + +// ProcessedL1Data is submitted to the enclave by the guardian +type ProcessedL1Data struct { + BlockHeader *types.Header + Events []L1Event +} + +// L1Event represents a single event type and its associated transactions +type L1Event struct { + Type uint8 + Txs []*L1TxData +} + +// L1TxData represents an L1 transaction that are relevant to us +type L1TxData struct { + Transaction *types.Transaction + Receipt *types.Receipt + Blobs []*kzg4844.Blob // Only populated for blob transactions + SequencerEnclaveID gethcommon.Address // Only non-zero when a new enclave is added as a sequencer + CrossChainMessages CrossChainMessages // Only populated for xchain messages + ValueTransfers ValueTransferEvents // Only populated for xchain transfers + Proof []byte // Some merkle proof TBC +} +``` +## Guardian +In the guardian we do all the transaction extraction to look for the event types we care about and then submit a +`ProcessedL1Data` object to the enclave via gRPC in the `SubmitL1Block` function. + +`TODO` what proof to submit? + +## Enclave side + +On the enclave side we handle each of the `processedData.GetEvents[L1TxType]` individually and don't have duplicate loops +through the transactions. + +Correct ordering of these event processing is going to be the biggest pain point I suspect. diff --git a/go/common/enclave.go b/go/common/enclave.go index 0370757fe0..32ab062f76 100644 --- a/go/common/enclave.go +++ b/go/common/enclave.go @@ -70,13 +70,13 @@ type EnclaveAdmin interface { // MakeActive - backup sequencer enclave can become active at the command of the host MakeActive() SystemError - // SubmitL1Block - Used for the host to submit L1 blocks to the enclave, these may be: + // SubmitL1Block - Used for the host to submit L1 pre-processed blocks to the enclave, these may be: // a. historic block - if the enclave is behind and in the process of catching up with the L1 state // b. the latest block published by the L1, to which the enclave should respond with a rollup // It is the responsibility of the host to gossip the returned rollup // For good functioning the caller should always submit blocks ordered by height // submitting a block before receiving ancestors of it, will result in it being ignored - SubmitL1Block(ctx context.Context, blockHeader *types.Header, receipts []*TxAndReceiptAndBlobs) (*BlockSubmissionResponse, SystemError) + SubmitL1Block(ctx context.Context, processed *ProcessedL1Data) (*BlockSubmissionResponse, SystemError) // SubmitBatch submits a batch received from the sequencer for processing. SubmitBatch(ctx context.Context, batch *ExtBatch) SystemError diff --git a/go/common/host/host.go b/go/common/host/host.go index 992ec20b54..d1479049d3 100644 --- a/go/common/host/host.go +++ b/go/common/host/host.go @@ -55,5 +55,5 @@ type P2PHostService interface { type L1RepoService interface { Service - L1BlockRepository + L1DataService } diff --git a/go/common/host/services.go b/go/common/host/services.go index 7dc8e5aa0e..bda314958c 100644 --- a/go/common/host/services.go +++ b/go/common/host/services.go @@ -10,13 +10,12 @@ import ( gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ten-protocol/go-ten/go/common" - "github.com/ten-protocol/go-ten/go/ethadapter" ) // service names - these are the keys used to register known services with the host const ( P2PName = "p2p" - L1BlockRepositoryName = "l1-block-repo" + L1DataServiceName = "l1-data-service" L1PublisherName = "l1-publisher" L2BatchRepositoryName = "l2-batch-repo" EnclaveServiceName = "enclaves" @@ -76,8 +75,8 @@ type P2PBatchRequestHandler interface { HandleBatchRequest(requestID string, fromSeqNo *big.Int) } -// L1BlockRepository provides an interface for the host to request L1 block data (live-streaming and historical) -type L1BlockRepository interface { +// L1DataService provides an interface for the host to request L1 block data (live-streaming and historical) +type L1DataService interface { // Subscribe will register a block handler to receive new blocks as they arrive, returns unsubscribe func Subscribe(handler L1BlockHandler) func() @@ -85,8 +84,8 @@ type L1BlockRepository interface { // FetchNextBlock returns the next canonical block after a given block hash // It returns the new block, a bool which is true if the block is the current L1 head and a bool if the block is on a different fork to prevBlock FetchNextBlock(prevBlock gethcommon.Hash) (*types.Block, bool, error) - // FetchObscuroReceipts returns the receipts for a given L1 block - FetchObscuroReceipts(block *common.L1Block) (types.Receipts, error) + // GetTenRelevantTransactions returns the events and transactions relevant to Ten + GetTenRelevantTransactions(block *common.L1Block) (*common.ProcessedL1Data, error) } // L1BlockHandler is an interface for receiving new blocks from the repository as they arrive @@ -101,10 +100,8 @@ type L1Publisher interface { InitializeSecret(attestation *common.AttestationReport, encSecret common.EncryptedSharedEnclaveSecret) error // RequestSecret will send a management contract transaction to request a secret from the enclave, returning the L1 head at time of sending RequestSecret(report *common.AttestationReport) (gethcommon.Hash, error) - // ExtractRelevantTenTransactions will return all TEN relevant tx from an L1 block - ExtractRelevantTenTransactions(block *types.Block, receipts types.Receipts) ([]*common.TxAndReceiptAndBlobs, []*ethadapter.L1RollupTx, []*ethadapter.L1SetImportantContractsTx) // FindSecretResponseTx will return the secret response tx from an L1 block - FindSecretResponseTx(block *types.Block) []*ethadapter.L1RespondSecretTx + FindSecretResponseTx(responseTxs []*common.L1TxData) []*common.L1RespondSecretTx // PublishRollup will create and publish a rollup tx to the management contract - fire and forget we don't wait for receipt // todo (#1624) - With a single sequencer, it is problematic if rollup publication fails; handle this case better PublishRollup(producedRollup *common.ExtRollup) diff --git a/go/common/l1_transaction.go b/go/common/l1_transaction.go new file mode 100644 index 0000000000..b11f934ce3 --- /dev/null +++ b/go/common/l1_transaction.go @@ -0,0 +1,139 @@ +package common + +import ( + "math/big" + + gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto/kzg4844" +) + +// L1TenTransaction is an abstraction that transforms an Ethereum transaction into a format that can be consumed more +// easily by TEN. +type L1TenTransaction interface{} + +type L1RollupTx struct { + Rollup EncodedRollup +} + +type L1RollupHashes struct { + BlobHashes []gethcommon.Hash +} + +type L1DepositTx struct { + Amount *big.Int // Amount to be deposited + To *gethcommon.Address // Address the ERC20 Transfer was made to (always be the Management Contract Addr) + Sender *gethcommon.Address // Address that issued the ERC20, the token holder or tx.origin + TokenContract *gethcommon.Address // Address of the ERC20 Contract address that was executed +} + +type L1RespondSecretTx struct { + Secret []byte + RequesterID gethcommon.Address + AttesterID gethcommon.Address + AttesterSig []byte +} + +type L1SetImportantContractsTx struct { + Key string + NewAddress gethcommon.Address +} + +type L1RequestSecretTx struct { + Attestation EncodedAttestationReport +} + +type L1InitializeSecretTx struct { + EnclaveID *gethcommon.Address + InitialSecret []byte + Attestation EncodedAttestationReport +} + +// The following types and structs are used for processing the l1 blocks and categorising the transactions to be processed +// by the enclave. + +// L1TenEventType represents different types of L1 transactions we monitor for +type L1TenEventType uint8 // Change to uint8 for RLP serialization + +const ( + RollupTx L1TenEventType = iota + InitialiseSecretTx + SecretRequestTx + SecretResponseTx + CrossChainMessageTx + CrossChainValueTranserTx + SequencerAddedTx + SequencerRevokedTx + SetImportantContractsTx +) + +// ProcessedL1Data is submitted to the enclave by the guardian +type ProcessedL1Data struct { + BlockHeader *types.Header + Events []L1Event +} + +// L1Event represents a single event type and its associated transactions +type L1Event struct { + Type uint8 + Txs []*L1TxData +} + +// L1TxData represents an L1 transaction that are relevant to us +type L1TxData struct { + Transaction *types.Transaction + Receipt *types.Receipt + Blobs []*kzg4844.Blob // Only populated for blob transactions + SequencerEnclaveID gethcommon.Address // Only non-zero when a new enclave is added as a sequencer + CrossChainMessages CrossChainMessages // Only populated for xchain messages + ValueTransfers ValueTransferEvents // Only populated for xchain transfers + Proof []byte // Some merkle proof TBC +} + +// HasSequencerEnclaveID helper method to check if SequencerEnclaveID is set to avoid custom RLP when we send over grpc +func (tx *L1TxData) HasSequencerEnclaveID() bool { + return tx.SequencerEnclaveID != (gethcommon.Address{}) +} + +func (p *ProcessedL1Data) AddEvent(tenEventType L1TenEventType, tx *L1TxData) { + eventType := uint8(tenEventType) + + for i := range p.Events { + if p.Events[i].Type != eventType { + continue + } + + txHash := tx.Transaction.Hash() + + // check for duplicate transaction + for _, existingTx := range p.Events[i].Txs { + if existingTx.Transaction.Hash() == txHash { + return // Skip duplicate transaction + } + } + + p.Events[i].Txs = append(p.Events[i].Txs, tx) + return + } + + p.Events = append(p.Events, L1Event{ + Type: eventType, + Txs: []*L1TxData{tx}, + }) +} + +func (p *ProcessedL1Data) GetEvents(txType L1TenEventType) []*L1TxData { + if p == nil || len(p.Events) == 0 { + return nil + } + + for _, event := range p.Events { + if event.Type == uint8(txType) { + if event.Txs == nil { + return nil + } + return event.Txs + } + } + return nil +} diff --git a/go/common/rpc/generated/enclave.pb.go b/go/common/rpc/generated/enclave.pb.go index 1757f9ced8..3ebc26bfd5 100644 --- a/go/common/rpc/generated/enclave.pb.go +++ b/go/common/rpc/generated/enclave.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.2 -// protoc v5.28.3 +// protoc-gen-go v1.32.0 +// protoc v4.25.3 // source: enclave.proto package generated @@ -2000,8 +2000,8 @@ type SubmitBlockRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - EncodedBlock []byte `protobuf:"bytes,1,opt,name=encodedBlock,proto3" json:"encodedBlock,omitempty"` - EncodedReceipts []byte `protobuf:"bytes,2,opt,name=encodedReceipts,proto3" json:"encodedReceipts,omitempty"` + EncodedBlock []byte `protobuf:"bytes,1,opt,name=encodedBlock,proto3" json:"encodedBlock,omitempty"` + EncodedProcessedData []byte `protobuf:"bytes,2,opt,name=encodedProcessedData,proto3" json:"encodedProcessedData,omitempty"` } func (x *SubmitBlockRequest) Reset() { @@ -2043,9 +2043,9 @@ func (x *SubmitBlockRequest) GetEncodedBlock() []byte { return nil } -func (x *SubmitBlockRequest) GetEncodedReceipts() []byte { +func (x *SubmitBlockRequest) GetEncodedProcessedData() []byte { if x != nil { - return x.EncodedReceipts + return x.EncodedProcessedData } return nil } @@ -3833,363 +3833,364 @@ var file_enclave_proto_rawDesc = []byte{ 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x52, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x62, + 0x72, 0x52, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x6c, 0x0a, 0x12, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x65, 0x6e, 0x63, 0x6f, - 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x28, 0x0a, 0x0f, 0x65, 0x6e, 0x63, 0x6f, - 0x64, 0x65, 0x64, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0f, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, - 0x74, 0x73, 0x22, 0xb0, 0x01, 0x0a, 0x13, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x17, 0x62, 0x6c, + 0x64, 0x65, 0x64, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x32, 0x0a, 0x14, 0x65, 0x6e, 0x63, 0x6f, + 0x64, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x14, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x50, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x22, 0xb0, 0x01, 0x0a, + 0x13, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x17, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x75, 0x62, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, + 0x64, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x73, 0x67, 0x52, 0x17, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x75, 0x62, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, - 0x73, 0x67, 0x52, 0x17, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x73, - 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x16, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x79, 0x73, - 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x3a, 0x0a, 0x0e, 0x45, 0x6e, 0x63, 0x43, 0x61, 0x6c, 0x6c, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x65, 0x6e, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x73, 0x22, 0x83, 0x01, 0x0a, 0x0f, 0x45, 0x6e, 0x63, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x16, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, - 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x16, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x45, 0x6e, - 0x63, 0x6c, 0x61, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, - 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, - 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x0b, 0x73, 0x79, 0x73, 0x74, - 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x42, 0x0a, 0x12, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, - 0x05, 0x62, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x45, 0x78, 0x74, 0x42, 0x61, 0x74, 0x63, - 0x68, 0x4d, 0x73, 0x67, 0x52, 0x05, 0x62, 0x61, 0x74, 0x63, 0x68, 0x22, 0x4f, 0x0a, 0x13, 0x53, - 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, - 0x74, 0x65, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, - 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x0d, 0x0a, 0x0b, - 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x48, 0x0a, 0x0c, 0x53, - 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x73, - 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x16, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x79, 0x73, - 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x50, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x64, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x72, 0x4f, 0x72, 0x48, 0x61, - 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, - 0x72, 0x4f, 0x72, 0x48, 0x61, 0x73, 0x68, 0x22, 0x5f, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x43, 0x6f, - 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, - 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x38, - 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, - 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x0b, 0x73, 0x79, 0x73, - 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x58, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x34, 0x0a, 0x15, - 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x15, 0x65, 0x6e, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0x4d, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x52, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, + 0x3a, 0x0a, 0x0e, 0x45, 0x6e, 0x63, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x28, 0x0a, 0x0f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x50, 0x61, + 0x72, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x65, 0x6e, 0x63, 0x72, + 0x79, 0x70, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x83, 0x01, 0x0a, 0x0f, + 0x45, 0x6e, 0x63, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x36, 0x0a, 0x16, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x16, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x22, 0x24, 0x0a, 0x12, 0x55, 0x6e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x22, 0x4f, 0x0a, 0x13, 0x55, 0x6e, 0x73, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, - 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, - 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x0b, 0x73, 0x79, 0x73, - 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x67, 0x0a, 0x13, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x38, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x52, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x22, 0x0b, 0x0a, 0x09, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x41, 0x72, 0x67, 0x73, 0x22, 0xc0, - 0x01, 0x0a, 0x14, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x4d, 0x73, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, - 0x16, 0x0a, 0x06, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x06, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x45, 0x6e, 0x63, 0x6c, 0x61, - 0x76, 0x65, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x45, 0x6e, 0x63, 0x6c, - 0x61, 0x76, 0x65, 0x49, 0x44, 0x12, 0x20, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x48, 0x6f, 0x73, 0x74, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x38, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x52, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x22, 0xae, 0x01, 0x0a, 0x1a, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x73, 0x67, - 0x12, 0x56, 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x53, 0x65, 0x63, 0x72, - 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x65, - 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x73, 0x67, 0x52, - 0x17, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, - 0x74, 0x65, 0x64, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x52, 0x05, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x22, 0x47, 0x0a, 0x17, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x14, 0x0a, - 0x05, 0x63, 0x61, 0x75, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x61, - 0x75, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x31, 0x48, 0x65, 0x61, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6c, 0x31, 0x48, 0x65, 0x61, 0x64, 0x22, 0x89, 0x01, 0x0a, 0x0d, - 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x73, 0x67, 0x12, 0x16, 0x0a, - 0x06, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x53, - 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, - 0x65, 0x12, 0x14, 0x0a, 0x05, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x05, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x6f, 0x70, 0x69, 0x63, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x18, 0x0a, - 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, - 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x6e, 0x0a, 0x0b, 0x45, 0x78, 0x74, 0x42, 0x61, - 0x74, 0x63, 0x68, 0x4d, 0x73, 0x67, 0x12, 0x31, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x64, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x73, - 0x67, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x78, 0x48, - 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x74, 0x78, 0x48, - 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x78, 0x73, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x03, 0x74, 0x78, 0x73, 0x22, 0xaa, 0x05, 0x0a, 0x0e, 0x42, 0x61, 0x74, 0x63, - 0x68, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, - 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x50, 0x72, - 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x50, 0x72, 0x6f, 0x6f, 0x66, - 0x12, 0x12, 0x0a, 0x04, 0x52, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, - 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x54, 0x78, 0x48, 0x61, 0x73, 0x68, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x54, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, - 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x4e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x10, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, - 0x72, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x4e, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, - 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x72, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x4e, 0x6f, - 0x12, 0x20, 0x0a, 0x0b, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x48, 0x61, 0x73, 0x68, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x48, 0x61, - 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x78, 0x74, 0x72, 0x61, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x05, 0x45, 0x78, 0x74, 0x72, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, - 0x69, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, - 0x69, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x47, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x07, 0x47, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, - 0x54, 0x69, 0x6d, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x54, 0x69, 0x6d, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x42, 0x61, 0x73, 0x65, 0x46, 0x65, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x07, 0x42, 0x61, 0x73, 0x65, 0x46, 0x65, 0x65, 0x12, 0x44, 0x0a, 0x1d, 0x4c, 0x61, + 0x72, 0x22, 0x42, 0x0a, 0x12, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x05, 0x62, 0x61, 0x74, 0x63, 0x68, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x2e, 0x45, 0x78, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x73, 0x67, 0x52, 0x05, + 0x62, 0x61, 0x74, 0x63, 0x68, 0x22, 0x4f, 0x0a, 0x13, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, + 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0b, + 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x79, + 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x0d, 0x0a, 0x0b, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x48, 0x0a, 0x0c, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x52, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, + 0x50, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x72, 0x4f, 0x72, 0x48, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x0d, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x72, 0x4f, 0x72, 0x48, 0x61, 0x73, + 0x68, 0x22, 0x5f, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x22, 0x58, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x02, 0x69, 0x64, 0x12, 0x34, 0x0a, 0x15, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, + 0x74, 0x65, 0x64, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x15, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4d, 0x0a, 0x11, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x0b, + 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x24, 0x0a, 0x12, 0x55, + 0x6e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, + 0x64, 0x22, 0x4f, 0x0a, 0x13, 0x55, 0x6e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x22, 0x67, 0x0a, 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x38, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x0b, + 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x0b, 0x0a, 0x09, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x41, 0x72, 0x67, 0x73, 0x22, 0xc0, 0x01, 0x0a, 0x14, 0x41, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x4d, 0x73, + 0x67, 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x06, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x75, 0x62, + 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x50, 0x75, 0x62, 0x4b, 0x65, + 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x49, 0x44, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x49, 0x44, 0x12, + 0x20, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x12, 0x38, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x0b, + 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xae, 0x01, 0x0a, 0x1a, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x73, 0x67, 0x12, 0x56, 0x0a, 0x17, 0x70, 0x72, + 0x6f, 0x64, 0x75, 0x63, 0x65, 0x64, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x65, + 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x73, 0x67, 0x52, 0x17, 0x70, 0x72, 0x6f, 0x64, 0x75, + 0x63, 0x65, 0x64, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x73, 0x12, 0x38, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x47, 0x0a, 0x17, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x61, 0x75, 0x73, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x61, 0x75, 0x73, 0x65, 0x12, 0x16, 0x0a, + 0x06, 0x6c, 0x31, 0x48, 0x65, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6c, + 0x31, 0x48, 0x65, 0x61, 0x64, 0x22, 0x89, 0x01, 0x0a, 0x0d, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x73, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x65, 0x6e, 0x64, 0x65, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, + 0x1a, 0x0a, 0x08, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x08, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x4e, + 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x4e, 0x6f, 0x6e, 0x63, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x05, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x22, 0x6e, 0x0a, 0x0b, 0x45, 0x78, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4d, 0x73, 0x67, + 0x12, 0x31, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x42, 0x61, 0x74, + 0x63, 0x68, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x52, 0x06, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x74, 0x78, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, + 0x10, 0x0a, 0x03, 0x74, 0x78, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x74, 0x78, + 0x73, 0x22, 0xaa, 0x05, 0x0a, 0x0e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x4d, 0x73, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, + 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x05, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x12, 0x0a, 0x04, 0x52, 0x6f, + 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x16, + 0x0a, 0x06, 0x54, 0x78, 0x48, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, + 0x54, 0x78, 0x48, 0x61, 0x73, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x2a, + 0x0a, 0x10, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x72, 0x4f, 0x72, 0x64, 0x65, 0x72, + 0x4e, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, + 0x63, 0x65, 0x72, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x4e, 0x6f, 0x12, 0x20, 0x0a, 0x0b, 0x52, 0x65, + 0x63, 0x65, 0x69, 0x70, 0x74, 0x48, 0x61, 0x73, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0b, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, + 0x45, 0x78, 0x74, 0x72, 0x61, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x45, 0x78, 0x74, + 0x72, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x12, 0x1a, 0x0a, 0x08, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x08, 0x47, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x18, 0x0a, 0x07, + 0x47, 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x47, + 0x61, 0x73, 0x55, 0x73, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x0c, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x42, 0x61, + 0x73, 0x65, 0x46, 0x65, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x42, 0x61, 0x73, + 0x65, 0x46, 0x65, 0x65, 0x12, 0x44, 0x0a, 0x1d, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x49, 0x6e, + 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x48, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x1d, 0x4c, 0x61, 0x74, + 0x65, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x40, 0x0a, 0x1b, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x72, 0x6f, 0x73, 0x73, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x1d, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, - 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, - 0x12, 0x40, 0x0a, 0x1b, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, - 0x64, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x18, - 0x0f, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x1b, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x48, 0x61, - 0x73, 0x68, 0x12, 0x48, 0x0a, 0x12, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, - 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x43, 0x72, 0x6f, 0x73, 0x73, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x73, 0x67, 0x52, 0x12, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x18, 0x11, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x0c, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, - 0x12, 0x1a, 0x0a, 0x08, 0x43, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x18, 0x12, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x08, 0x43, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x0e, - 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x72, 0x65, 0x65, 0x18, 0x13, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x54, 0x72, 0x65, 0x65, 0x22, 0x9c, 0x01, 0x0a, 0x0c, 0x45, 0x78, 0x74, 0x52, 0x6f, 0x6c, 0x6c, - 0x75, 0x70, 0x4d, 0x73, 0x67, 0x12, 0x32, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, - 0x64, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x73, - 0x67, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x61, 0x74, - 0x63, 0x68, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x0d, 0x62, 0x61, 0x74, 0x63, 0x68, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x12, - 0x32, 0x0a, 0x14, 0x63, 0x61, 0x6c, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x52, 0x6f, 0x6c, 0x6c, 0x75, - 0x70, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x14, 0x63, - 0x61, 0x6c, 0x6c, 0x64, 0x61, 0x74, 0x61, 0x52, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x22, 0xdb, 0x02, 0x0a, 0x0f, 0x52, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x48, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x50, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2c, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x72, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x31, 0x48, 0x65, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, - 0x31, 0x48, 0x65, 0x61, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x4e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x50, 0x72, 0x6f, 0x6f, - 0x66, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x4e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, - 0x12, 0x0a, 0x04, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x54, - 0x69, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x49, 0x44, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x49, - 0x44, 0x12, 0x48, 0x0a, 0x12, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, - 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x73, 0x67, 0x52, 0x12, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, - 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x4c, 0x61, 0x73, - 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x71, 0x4e, 0x6f, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x0e, 0x4c, 0x61, 0x73, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x71, 0x4e, - 0x6f, 0x22, 0xc9, 0x01, 0x0a, 0x11, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x73, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x65, 0x63, 0x72, 0x65, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, - 0x20, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x49, 0x44, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x49, - 0x44, 0x12, 0x1e, 0x0a, 0x0a, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x49, 0x44, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x49, - 0x44, 0x12, 0x20, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x12, 0x38, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, - 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x52, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x61, 0x0a, - 0x0d, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x4d, 0x73, 0x67, 0x12, 0x16, - 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, - 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, - 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, - 0x69, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, - 0x32, 0xfc, 0x10, 0x0a, 0x0c, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x3f, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x2e, 0x67, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, - 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0b, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x1d, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x41, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1e, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x41, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x57, 0x0a, 0x0e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x53, 0x65, - 0x63, 0x72, 0x65, 0x74, 0x12, 0x20, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, - 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x64, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x53, 0x65, 0x63, 0x72, 0x65, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0b, 0x49, - 0x6e, 0x69, 0x74, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x12, 0x1d, 0x2e, 0x67, 0x65, 0x6e, - 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x45, 0x6e, 0x63, 0x6c, 0x61, - 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x65, 0x6e, 0x65, - 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x09, 0x45, - 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x49, 0x44, 0x12, 0x1b, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, - 0x61, 0x74, 0x65, 0x64, 0x2e, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x49, 0x44, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, - 0x64, 0x2e, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5d, 0x0a, 0x10, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x22, 0x2e, 0x67, 0x65, 0x6e, 0x65, - 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, - 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x50, 0x0a, 0x0d, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4c, 0x31, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, - 0x64, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, - 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0c, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x65, 0x64, 0x52, 0x50, 0x43, 0x12, 0x19, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x64, 0x2e, 0x45, 0x6e, 0x63, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x45, 0x6e, - 0x63, 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x4e, 0x0a, 0x0b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x1d, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x1b, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x72, + 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x12, 0x48, 0x0a, 0x12, + 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, + 0x61, 0x74, 0x65, 0x64, 0x2e, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, + 0x73, 0x67, 0x52, 0x12, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, + 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x43, 0x6f, + 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x43, 0x6f, + 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x54, 0x72, 0x65, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, + 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x72, 0x65, 0x65, 0x22, 0x9c, + 0x01, 0x0a, 0x0c, 0x45, 0x78, 0x74, 0x52, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x4d, 0x73, 0x67, 0x12, + 0x32, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, + 0x75, 0x70, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x52, 0x06, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x62, 0x61, 0x74, 0x63, 0x68, 0x50, 0x61, 0x79, 0x6c, + 0x6f, 0x61, 0x64, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0d, 0x62, 0x61, 0x74, 0x63, + 0x68, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x12, 0x32, 0x0a, 0x14, 0x63, 0x61, 0x6c, + 0x6c, 0x64, 0x61, 0x74, 0x61, 0x52, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x14, 0x63, 0x61, 0x6c, 0x6c, 0x64, 0x61, 0x74, + 0x61, 0x52, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x22, 0xdb, 0x02, + 0x0a, 0x0f, 0x52, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x73, + 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, + 0x68, 0x12, 0x2c, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x4c, 0x31, 0x48, 0x65, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x11, 0x43, 0x6f, + 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4c, 0x31, 0x48, 0x65, 0x61, 0x64, 0x12, + 0x20, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x4e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x12, 0x16, 0x0a, 0x06, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x06, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x69, 0x6d, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1c, 0x0a, + 0x09, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x49, 0x44, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x09, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x49, 0x44, 0x12, 0x48, 0x0a, 0x12, 0x43, + 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x65, 0x64, 0x2e, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x73, + 0x67, 0x52, 0x12, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x4c, 0x61, 0x73, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, + 0x53, 0x65, 0x71, 0x4e, 0x6f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x4c, 0x61, 0x73, + 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x71, 0x4e, 0x6f, 0x22, 0xc9, 0x01, 0x0a, 0x11, + 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x73, + 0x67, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x06, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x65, 0x72, 0x49, 0x44, 0x12, 0x1e, 0x0a, 0x0a, 0x41, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x49, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0a, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x72, 0x49, 0x44, 0x12, 0x20, 0x0a, 0x0b, 0x48, + 0x6f, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x38, 0x0a, + 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x0b, 0x73, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x61, 0x0a, 0x0d, 0x57, 0x69, 0x74, 0x68, 0x64, + 0x72, 0x61, 0x77, 0x61, 0x6c, 0x4d, 0x73, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x1a, + 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x32, 0xfc, 0x10, 0x0a, 0x0c, 0x45, + 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x3f, 0x0a, 0x06, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, + 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x19, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0b, + 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x2e, 0x67, 0x65, + 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x0e, + 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x20, + 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, + 0x61, 0x74, 0x65, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x21, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x47, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x74, 0x65, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0b, 0x49, 0x6e, 0x69, 0x74, 0x45, 0x6e, 0x63, + 0x6c, 0x61, 0x76, 0x65, 0x12, 0x1d, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, + 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, + 0x49, 0x6e, 0x69, 0x74, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x09, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, + 0x49, 0x44, 0x12, 0x1b, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x45, + 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1c, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x45, 0x6e, 0x63, 0x6c, + 0x61, 0x76, 0x65, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x5d, 0x0a, 0x10, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x4b, 0x65, 0x79, 0x12, 0x22, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, + 0x52, 0x50, 0x43, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x65, 0x64, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x50, + 0x0a, 0x0d, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4c, 0x31, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, + 0x1d, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x75, 0x62, 0x6d, + 0x69, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, - 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x39, 0x0a, 0x04, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x16, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, - 0x74, 0x65, 0x64, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x17, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x74, 0x6f, 0x70, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x07, 0x47, 0x65, - 0x74, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x19, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, - 0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1a, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x47, 0x65, 0x74, - 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x48, - 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x1b, 0x2e, 0x67, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, - 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0b, 0x55, 0x6e, 0x73, 0x75, - 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x1d, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, - 0x74, 0x65, 0x64, 0x2e, 0x55, 0x6e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x64, 0x2e, 0x55, 0x6e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x45, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x14, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, - 0x74, 0x65, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x1e, 0x2e, - 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x45, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x1a, 0x2e, 0x67, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, - 0x74, 0x65, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x53, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, - 0x63, 0x68, 0x42, 0x79, 0x53, 0x65, 0x71, 0x4e, 0x6f, 0x12, 0x21, 0x2e, 0x67, 0x65, 0x6e, 0x65, - 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x42, 0x79, - 0x53, 0x65, 0x71, 0x4e, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, - 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x0d, 0x47, - 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1f, 0x2e, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x6c, - 0x75, 0x70, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, - 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, - 0x6c, 0x75, 0x70, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x4e, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x61, 0x74, 0x63, 0x68, - 0x12, 0x1d, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1e, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x51, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x6c, 0x75, - 0x70, 0x12, 0x1e, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x69, 0x0a, 0x14, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x72, - 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x26, 0x2e, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, - 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, - 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x6c, 0x0a, 0x15, 0x44, 0x65, 0x62, 0x75, 0x67, 0x54, 0x72, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, - 0x61, 0x74, 0x65, 0x64, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x54, 0x72, 0x61, 0x63, 0x65, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x28, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x44, 0x65, - 0x62, 0x75, 0x67, 0x54, 0x72, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, - 0x0f, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x32, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, - 0x12, 0x21, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x4c, 0x32, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, - 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x6c, 0x0a, 0x15, 0x47, 0x65, 0x74, - 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x12, 0x27, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x47, - 0x65, 0x74, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x67, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x74, 0x61, 0x6c, - 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x66, 0x0a, 0x13, 0x45, 0x6e, 0x63, 0x6c, 0x61, - 0x76, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, - 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x45, 0x6e, 0x63, 0x6c, 0x61, - 0x76, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, - 0x64, 0x2e, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x4b, 0x0a, 0x0a, 0x4d, 0x61, 0x6b, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x12, 0x1c, 0x2e, - 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x4d, 0x61, 0x6b, 0x65, 0x41, 0x63, - 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x4d, 0x61, 0x6b, 0x65, 0x41, 0x63, 0x74, 0x69, - 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x0c, - 0x41, 0x64, 0x64, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x72, 0x12, 0x1e, 0x2e, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x53, 0x65, 0x71, 0x75, - 0x65, 0x6e, 0x63, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x53, 0x65, 0x71, 0x75, - 0x65, 0x6e, 0x63, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, - 0x17, 0x5a, 0x15, 0x65, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x47, 0x0a, 0x0c, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x52, 0x50, 0x43, + 0x12, 0x19, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x45, 0x6e, 0x63, + 0x43, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x65, + 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x45, 0x6e, 0x63, 0x43, 0x61, 0x6c, 0x6c, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0b, 0x53, 0x75, 0x62, + 0x6d, 0x69, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x1d, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, + 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x65, 0x64, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x04, 0x53, 0x74, 0x6f, + 0x70, 0x12, 0x16, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x74, + 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x12, + 0x19, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, + 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x1b, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, + 0x64, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0b, 0x55, 0x6e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, + 0x65, 0x12, 0x1d, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x55, 0x6e, + 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1e, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x55, 0x6e, 0x73, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x45, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x12, 0x14, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x41, 0x72, 0x67, 0x73, 0x1a, 0x1e, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x65, 0x64, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x45, 0x0a, 0x08, 0x47, 0x65, 0x74, + 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x1a, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, + 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x47, 0x65, + 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x53, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x42, 0x79, 0x53, 0x65, + 0x71, 0x4e, 0x6f, 0x12, 0x21, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, + 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x42, 0x79, 0x53, 0x65, 0x71, 0x4e, 0x6f, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x6c, + 0x75, 0x70, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1f, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x44, 0x61, 0x74, 0x61, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x65, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x44, 0x61, 0x74, + 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0b, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x1d, 0x2e, 0x67, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x61, 0x74, + 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x42, 0x61, 0x74, 0x63, + 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x0c, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6c, 0x6c, 0x75, 0x70, 0x12, 0x1e, 0x2e, 0x67, 0x65, + 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, + 0x6c, 0x6c, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x65, + 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, + 0x6c, 0x6c, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x69, + 0x0a, 0x14, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x26, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, + 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, + 0x74, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6c, 0x0a, 0x15, 0x44, 0x65, 0x62, + 0x75, 0x67, 0x54, 0x72, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x44, + 0x65, 0x62, 0x75, 0x67, 0x54, 0x72, 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x67, 0x65, + 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x54, 0x72, 0x61, + 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0f, 0x53, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x4c, 0x32, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x21, 0x2e, 0x67, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4c, 0x32, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, + 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x65, + 0x64, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x30, 0x01, 0x12, 0x6c, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x43, + 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x27, 0x2e, 0x67, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x74, 0x61, + 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, + 0x64, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, + 0x63, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x12, 0x66, 0x0a, 0x13, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x50, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, + 0x61, 0x74, 0x65, 0x64, 0x2e, 0x45, 0x6e, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x50, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x26, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x45, 0x6e, 0x63, 0x6c, + 0x61, 0x76, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0a, 0x4d, 0x61, 0x6b, + 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, + 0x74, 0x65, 0x64, 0x2e, 0x4d, 0x61, 0x6b, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, + 0x64, 0x2e, 0x4d, 0x61, 0x6b, 0x65, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x0c, 0x41, 0x64, 0x64, 0x53, 0x65, 0x71, + 0x75, 0x65, 0x6e, 0x63, 0x65, 0x72, 0x12, 0x1e, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x17, 0x5a, 0x15, 0x65, 0x6e, 0x63, + 0x6c, 0x61, 0x76, 0x65, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4205,7 +4206,7 @@ func file_enclave_proto_rawDescGZIP() []byte { } var file_enclave_proto_msgTypes = make([]protoimpl.MessageInfo, 67) -var file_enclave_proto_goTypes = []any{ +var file_enclave_proto_goTypes = []interface{}{ (*EnclavePublicConfigRequest)(nil), // 0: generated.EnclavePublicConfigRequest (*EnclavePublicConfigResponse)(nil), // 1: generated.EnclavePublicConfigResponse (*GetBatchRequest)(nil), // 2: generated.GetBatchRequest @@ -4377,7 +4378,7 @@ func file_enclave_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_enclave_proto_msgTypes[0].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EnclavePublicConfigRequest); i { case 0: return &v.state @@ -4389,7 +4390,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[1].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EnclavePublicConfigResponse); i { case 0: return &v.state @@ -4401,7 +4402,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[2].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetBatchRequest); i { case 0: return &v.state @@ -4413,7 +4414,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[3].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetBatchBySeqNoRequest); i { case 0: return &v.state @@ -4425,7 +4426,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[4].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetBatchResponse); i { case 0: return &v.state @@ -4437,7 +4438,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[5].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetRollupDataRequest); i { case 0: return &v.state @@ -4449,7 +4450,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[6].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetRollupDataResponse); i { case 0: return &v.state @@ -4461,7 +4462,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[7].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PublicRollupDataMsg); i { case 0: return &v.state @@ -4473,7 +4474,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[8].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StreamL2UpdatesRequest); i { case 0: return &v.state @@ -4485,7 +4486,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[9].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EncodedUpdateResponse); i { case 0: return &v.state @@ -4497,7 +4498,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[10].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Pagination); i { case 0: return &v.state @@ -4509,7 +4510,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[11].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SystemError); i { case 0: return &v.state @@ -4521,7 +4522,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[12].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetTotalContractCountRequest); i { case 0: return &v.state @@ -4533,7 +4534,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[13].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetTotalContractCountResponse); i { case 0: return &v.state @@ -4545,7 +4546,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[14].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DebugTraceTransactionRequest); i { case 0: return &v.state @@ -4557,7 +4558,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[15].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DebugTraceTransactionResponse); i { case 0: return &v.state @@ -4569,7 +4570,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[16].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateBatchRequest); i { case 0: return &v.state @@ -4581,7 +4582,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[17].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateBatchResponse); i { case 0: return &v.state @@ -4593,7 +4594,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[18].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateRollupRequest); i { case 0: return &v.state @@ -4605,7 +4606,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[19].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CreateRollupResponse); i { case 0: return &v.state @@ -4617,7 +4618,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[20].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExportCrossChainDataRequest); i { case 0: return &v.state @@ -4629,7 +4630,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[21].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExportCrossChainDataResponse); i { case 0: return &v.state @@ -4641,7 +4642,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[22].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StatusRequest); i { case 0: return &v.state @@ -4653,7 +4654,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[23].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StatusResponse); i { case 0: return &v.state @@ -4665,7 +4666,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[24].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MakeActiveRequest); i { case 0: return &v.state @@ -4677,7 +4678,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[25].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MakeActiveResponse); i { case 0: return &v.state @@ -4689,7 +4690,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[26].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AddSequencerRequest); i { case 0: return &v.state @@ -4701,7 +4702,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[27].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AddSequencerResponse); i { case 0: return &v.state @@ -4713,7 +4714,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[28].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AttestationRequest); i { case 0: return &v.state @@ -4725,7 +4726,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[29].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AttestationResponse); i { case 0: return &v.state @@ -4737,7 +4738,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[30].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GenerateSecretRequest); i { case 0: return &v.state @@ -4749,7 +4750,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[31].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GenerateSecretResponse); i { case 0: return &v.state @@ -4761,7 +4762,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[32].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*InitEnclaveRequest); i { case 0: return &v.state @@ -4773,7 +4774,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[33].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*InitEnclaveResponse); i { case 0: return &v.state @@ -4785,7 +4786,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[34].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EnclaveIDRequest); i { case 0: return &v.state @@ -4797,7 +4798,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[35].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EnclaveIDResponse); i { case 0: return &v.state @@ -4809,7 +4810,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[36].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RPCEncryptionKeyRequest); i { case 0: return &v.state @@ -4821,7 +4822,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[37].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RPCEncryptionKeyResponse); i { case 0: return &v.state @@ -4833,7 +4834,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[38].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StartRequest); i { case 0: return &v.state @@ -4845,7 +4846,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[39].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StartResponse); i { case 0: return &v.state @@ -4857,7 +4858,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[40].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SubmitBlockRequest); i { case 0: return &v.state @@ -4869,7 +4870,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[41].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SubmitBlockResponse); i { case 0: return &v.state @@ -4881,7 +4882,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[42].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EncCallRequest); i { case 0: return &v.state @@ -4893,7 +4894,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[43].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EncCallResponse); i { case 0: return &v.state @@ -4905,7 +4906,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[44].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SubmitBatchRequest); i { case 0: return &v.state @@ -4917,7 +4918,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[45].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SubmitBatchResponse); i { case 0: return &v.state @@ -4929,7 +4930,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[46].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StopRequest); i { case 0: return &v.state @@ -4941,7 +4942,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[47].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StopResponse); i { case 0: return &v.state @@ -4953,7 +4954,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[48].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetCodeRequest); i { case 0: return &v.state @@ -4965,7 +4966,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[49].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetCodeResponse); i { case 0: return &v.state @@ -4977,7 +4978,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[50].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SubscribeRequest); i { case 0: return &v.state @@ -4989,7 +4990,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[51].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SubscribeResponse); i { case 0: return &v.state @@ -5001,7 +5002,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[52].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UnsubscribeRequest); i { case 0: return &v.state @@ -5013,7 +5014,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[53].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UnsubscribeResponse); i { case 0: return &v.state @@ -5025,7 +5026,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[54].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*HealthCheckResponse); i { case 0: return &v.state @@ -5037,7 +5038,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[55].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EmptyArgs); i { case 0: return &v.state @@ -5049,7 +5050,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[56].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*AttestationReportMsg); i { case 0: return &v.state @@ -5061,7 +5062,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[57].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BlockSubmissionResponseMsg); i { case 0: return &v.state @@ -5073,7 +5074,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[58].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BlockSubmissionErrorMsg); i { case 0: return &v.state @@ -5085,7 +5086,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[59].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CrossChainMsg); i { case 0: return &v.state @@ -5097,7 +5098,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[60].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExtBatchMsg); i { case 0: return &v.state @@ -5109,7 +5110,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[61].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BatchHeaderMsg); i { case 0: return &v.state @@ -5121,7 +5122,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[62].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExtRollupMsg); i { case 0: return &v.state @@ -5133,7 +5134,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[63].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RollupHeaderMsg); i { case 0: return &v.state @@ -5145,7 +5146,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[64].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SecretResponseMsg); i { case 0: return &v.state @@ -5157,7 +5158,7 @@ func file_enclave_proto_init() { return nil } } - file_enclave_proto_msgTypes[65].Exporter = func(v any, i int) any { + file_enclave_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*WithdrawalMsg); i { case 0: return &v.state @@ -5170,7 +5171,7 @@ func file_enclave_proto_init() { } } } - file_enclave_proto_msgTypes[18].OneofWrappers = []any{} + file_enclave_proto_msgTypes[18].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/go/common/rpc/generated/enclave.proto b/go/common/rpc/generated/enclave.proto index 5f03ca7094..efe7663183 100644 --- a/go/common/rpc/generated/enclave.proto +++ b/go/common/rpc/generated/enclave.proto @@ -188,7 +188,7 @@ message StartResponse { message SubmitBlockRequest { bytes encodedBlock = 1; - bytes encodedReceipts = 2; + bytes encodedProcessedData = 2; } message SubmitBlockResponse { diff --git a/go/common/rpc/generated/enclave_grpc.pb.go b/go/common/rpc/generated/enclave_grpc.pb.go index 0e7c2f63e7..6fd57332f4 100644 --- a/go/common/rpc/generated/enclave_grpc.pb.go +++ b/go/common/rpc/generated/enclave_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.5.1 -// - protoc v5.28.3 +// - protoc-gen-go-grpc v1.3.0 +// - protoc v4.25.3 // source: enclave.proto package generated @@ -15,8 +15,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 const ( EnclaveProto_Status_FullMethodName = "/generated.EnclaveProto/Status" @@ -72,7 +72,7 @@ type EnclaveProtoClient interface { CreateRollup(ctx context.Context, in *CreateRollupRequest, opts ...grpc.CallOption) (*CreateRollupResponse, error) ExportCrossChainData(ctx context.Context, in *ExportCrossChainDataRequest, opts ...grpc.CallOption) (*ExportCrossChainDataResponse, error) DebugTraceTransaction(ctx context.Context, in *DebugTraceTransactionRequest, opts ...grpc.CallOption) (*DebugTraceTransactionResponse, error) - StreamL2Updates(ctx context.Context, in *StreamL2UpdatesRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[EncodedUpdateResponse], error) + StreamL2Updates(ctx context.Context, in *StreamL2UpdatesRequest, opts ...grpc.CallOption) (EnclaveProto_StreamL2UpdatesClient, error) GetTotalContractCount(ctx context.Context, in *GetTotalContractCountRequest, opts ...grpc.CallOption) (*GetTotalContractCountResponse, error) EnclavePublicConfig(ctx context.Context, in *EnclavePublicConfigRequest, opts ...grpc.CallOption) (*EnclavePublicConfigResponse, error) MakeActive(ctx context.Context, in *MakeActiveRequest, opts ...grpc.CallOption) (*MakeActiveResponse, error) @@ -88,9 +88,8 @@ func NewEnclaveProtoClient(cc grpc.ClientConnInterface) EnclaveProtoClient { } func (c *enclaveProtoClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (*StatusResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(StatusResponse) - err := c.cc.Invoke(ctx, EnclaveProto_Status_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_Status_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -98,9 +97,8 @@ func (c *enclaveProtoClient) Status(ctx context.Context, in *StatusRequest, opts } func (c *enclaveProtoClient) Attestation(ctx context.Context, in *AttestationRequest, opts ...grpc.CallOption) (*AttestationResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(AttestationResponse) - err := c.cc.Invoke(ctx, EnclaveProto_Attestation_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_Attestation_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -108,9 +106,8 @@ func (c *enclaveProtoClient) Attestation(ctx context.Context, in *AttestationReq } func (c *enclaveProtoClient) GenerateSecret(ctx context.Context, in *GenerateSecretRequest, opts ...grpc.CallOption) (*GenerateSecretResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GenerateSecretResponse) - err := c.cc.Invoke(ctx, EnclaveProto_GenerateSecret_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_GenerateSecret_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -118,9 +115,8 @@ func (c *enclaveProtoClient) GenerateSecret(ctx context.Context, in *GenerateSec } func (c *enclaveProtoClient) InitEnclave(ctx context.Context, in *InitEnclaveRequest, opts ...grpc.CallOption) (*InitEnclaveResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(InitEnclaveResponse) - err := c.cc.Invoke(ctx, EnclaveProto_InitEnclave_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_InitEnclave_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -128,9 +124,8 @@ func (c *enclaveProtoClient) InitEnclave(ctx context.Context, in *InitEnclaveReq } func (c *enclaveProtoClient) EnclaveID(ctx context.Context, in *EnclaveIDRequest, opts ...grpc.CallOption) (*EnclaveIDResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(EnclaveIDResponse) - err := c.cc.Invoke(ctx, EnclaveProto_EnclaveID_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_EnclaveID_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -138,9 +133,8 @@ func (c *enclaveProtoClient) EnclaveID(ctx context.Context, in *EnclaveIDRequest } func (c *enclaveProtoClient) RPCEncryptionKey(ctx context.Context, in *RPCEncryptionKeyRequest, opts ...grpc.CallOption) (*RPCEncryptionKeyResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(RPCEncryptionKeyResponse) - err := c.cc.Invoke(ctx, EnclaveProto_RPCEncryptionKey_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_RPCEncryptionKey_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -148,9 +142,8 @@ func (c *enclaveProtoClient) RPCEncryptionKey(ctx context.Context, in *RPCEncryp } func (c *enclaveProtoClient) SubmitL1Block(ctx context.Context, in *SubmitBlockRequest, opts ...grpc.CallOption) (*SubmitBlockResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SubmitBlockResponse) - err := c.cc.Invoke(ctx, EnclaveProto_SubmitL1Block_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_SubmitL1Block_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -158,9 +151,8 @@ func (c *enclaveProtoClient) SubmitL1Block(ctx context.Context, in *SubmitBlockR } func (c *enclaveProtoClient) EncryptedRPC(ctx context.Context, in *EncCallRequest, opts ...grpc.CallOption) (*EncCallResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(EncCallResponse) - err := c.cc.Invoke(ctx, EnclaveProto_EncryptedRPC_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_EncryptedRPC_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -168,9 +160,8 @@ func (c *enclaveProtoClient) EncryptedRPC(ctx context.Context, in *EncCallReques } func (c *enclaveProtoClient) SubmitBatch(ctx context.Context, in *SubmitBatchRequest, opts ...grpc.CallOption) (*SubmitBatchResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SubmitBatchResponse) - err := c.cc.Invoke(ctx, EnclaveProto_SubmitBatch_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_SubmitBatch_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -178,9 +169,8 @@ func (c *enclaveProtoClient) SubmitBatch(ctx context.Context, in *SubmitBatchReq } func (c *enclaveProtoClient) Stop(ctx context.Context, in *StopRequest, opts ...grpc.CallOption) (*StopResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(StopResponse) - err := c.cc.Invoke(ctx, EnclaveProto_Stop_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_Stop_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -188,9 +178,8 @@ func (c *enclaveProtoClient) Stop(ctx context.Context, in *StopRequest, opts ... } func (c *enclaveProtoClient) GetCode(ctx context.Context, in *GetCodeRequest, opts ...grpc.CallOption) (*GetCodeResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetCodeResponse) - err := c.cc.Invoke(ctx, EnclaveProto_GetCode_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_GetCode_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -198,9 +187,8 @@ func (c *enclaveProtoClient) GetCode(ctx context.Context, in *GetCodeRequest, op } func (c *enclaveProtoClient) Subscribe(ctx context.Context, in *SubscribeRequest, opts ...grpc.CallOption) (*SubscribeResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SubscribeResponse) - err := c.cc.Invoke(ctx, EnclaveProto_Subscribe_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_Subscribe_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -208,9 +196,8 @@ func (c *enclaveProtoClient) Subscribe(ctx context.Context, in *SubscribeRequest } func (c *enclaveProtoClient) Unsubscribe(ctx context.Context, in *UnsubscribeRequest, opts ...grpc.CallOption) (*UnsubscribeResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(UnsubscribeResponse) - err := c.cc.Invoke(ctx, EnclaveProto_Unsubscribe_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_Unsubscribe_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -218,9 +205,8 @@ func (c *enclaveProtoClient) Unsubscribe(ctx context.Context, in *UnsubscribeReq } func (c *enclaveProtoClient) HealthCheck(ctx context.Context, in *EmptyArgs, opts ...grpc.CallOption) (*HealthCheckResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(HealthCheckResponse) - err := c.cc.Invoke(ctx, EnclaveProto_HealthCheck_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_HealthCheck_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -228,9 +214,8 @@ func (c *enclaveProtoClient) HealthCheck(ctx context.Context, in *EmptyArgs, opt } func (c *enclaveProtoClient) GetBatch(ctx context.Context, in *GetBatchRequest, opts ...grpc.CallOption) (*GetBatchResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetBatchResponse) - err := c.cc.Invoke(ctx, EnclaveProto_GetBatch_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_GetBatch_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -238,9 +223,8 @@ func (c *enclaveProtoClient) GetBatch(ctx context.Context, in *GetBatchRequest, } func (c *enclaveProtoClient) GetBatchBySeqNo(ctx context.Context, in *GetBatchBySeqNoRequest, opts ...grpc.CallOption) (*GetBatchResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetBatchResponse) - err := c.cc.Invoke(ctx, EnclaveProto_GetBatchBySeqNo_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_GetBatchBySeqNo_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -248,9 +232,8 @@ func (c *enclaveProtoClient) GetBatchBySeqNo(ctx context.Context, in *GetBatchBy } func (c *enclaveProtoClient) GetRollupData(ctx context.Context, in *GetRollupDataRequest, opts ...grpc.CallOption) (*GetRollupDataResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetRollupDataResponse) - err := c.cc.Invoke(ctx, EnclaveProto_GetRollupData_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_GetRollupData_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -258,9 +241,8 @@ func (c *enclaveProtoClient) GetRollupData(ctx context.Context, in *GetRollupDat } func (c *enclaveProtoClient) CreateBatch(ctx context.Context, in *CreateBatchRequest, opts ...grpc.CallOption) (*CreateBatchResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(CreateBatchResponse) - err := c.cc.Invoke(ctx, EnclaveProto_CreateBatch_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_CreateBatch_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -268,9 +250,8 @@ func (c *enclaveProtoClient) CreateBatch(ctx context.Context, in *CreateBatchReq } func (c *enclaveProtoClient) CreateRollup(ctx context.Context, in *CreateRollupRequest, opts ...grpc.CallOption) (*CreateRollupResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(CreateRollupResponse) - err := c.cc.Invoke(ctx, EnclaveProto_CreateRollup_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_CreateRollup_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -278,9 +259,8 @@ func (c *enclaveProtoClient) CreateRollup(ctx context.Context, in *CreateRollupR } func (c *enclaveProtoClient) ExportCrossChainData(ctx context.Context, in *ExportCrossChainDataRequest, opts ...grpc.CallOption) (*ExportCrossChainDataResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ExportCrossChainDataResponse) - err := c.cc.Invoke(ctx, EnclaveProto_ExportCrossChainData_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_ExportCrossChainData_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -288,22 +268,20 @@ func (c *enclaveProtoClient) ExportCrossChainData(ctx context.Context, in *Expor } func (c *enclaveProtoClient) DebugTraceTransaction(ctx context.Context, in *DebugTraceTransactionRequest, opts ...grpc.CallOption) (*DebugTraceTransactionResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(DebugTraceTransactionResponse) - err := c.cc.Invoke(ctx, EnclaveProto_DebugTraceTransaction_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_DebugTraceTransaction_FullMethodName, in, out, opts...) if err != nil { return nil, err } return out, nil } -func (c *enclaveProtoClient) StreamL2Updates(ctx context.Context, in *StreamL2UpdatesRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[EncodedUpdateResponse], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &EnclaveProto_ServiceDesc.Streams[0], EnclaveProto_StreamL2Updates_FullMethodName, cOpts...) +func (c *enclaveProtoClient) StreamL2Updates(ctx context.Context, in *StreamL2UpdatesRequest, opts ...grpc.CallOption) (EnclaveProto_StreamL2UpdatesClient, error) { + stream, err := c.cc.NewStream(ctx, &EnclaveProto_ServiceDesc.Streams[0], EnclaveProto_StreamL2Updates_FullMethodName, opts...) if err != nil { return nil, err } - x := &grpc.GenericClientStream[StreamL2UpdatesRequest, EncodedUpdateResponse]{ClientStream: stream} + x := &enclaveProtoStreamL2UpdatesClient{stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } @@ -313,13 +291,26 @@ func (c *enclaveProtoClient) StreamL2Updates(ctx context.Context, in *StreamL2Up return x, nil } -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type EnclaveProto_StreamL2UpdatesClient = grpc.ServerStreamingClient[EncodedUpdateResponse] +type EnclaveProto_StreamL2UpdatesClient interface { + Recv() (*EncodedUpdateResponse, error) + grpc.ClientStream +} + +type enclaveProtoStreamL2UpdatesClient struct { + grpc.ClientStream +} + +func (x *enclaveProtoStreamL2UpdatesClient) Recv() (*EncodedUpdateResponse, error) { + m := new(EncodedUpdateResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} func (c *enclaveProtoClient) GetTotalContractCount(ctx context.Context, in *GetTotalContractCountRequest, opts ...grpc.CallOption) (*GetTotalContractCountResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetTotalContractCountResponse) - err := c.cc.Invoke(ctx, EnclaveProto_GetTotalContractCount_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_GetTotalContractCount_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -327,9 +318,8 @@ func (c *enclaveProtoClient) GetTotalContractCount(ctx context.Context, in *GetT } func (c *enclaveProtoClient) EnclavePublicConfig(ctx context.Context, in *EnclavePublicConfigRequest, opts ...grpc.CallOption) (*EnclavePublicConfigResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(EnclavePublicConfigResponse) - err := c.cc.Invoke(ctx, EnclaveProto_EnclavePublicConfig_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_EnclavePublicConfig_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -337,9 +327,8 @@ func (c *enclaveProtoClient) EnclavePublicConfig(ctx context.Context, in *Enclav } func (c *enclaveProtoClient) MakeActive(ctx context.Context, in *MakeActiveRequest, opts ...grpc.CallOption) (*MakeActiveResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(MakeActiveResponse) - err := c.cc.Invoke(ctx, EnclaveProto_MakeActive_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_MakeActive_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -347,9 +336,8 @@ func (c *enclaveProtoClient) MakeActive(ctx context.Context, in *MakeActiveReque } func (c *enclaveProtoClient) AddSequencer(ctx context.Context, in *AddSequencerRequest, opts ...grpc.CallOption) (*AddSequencerResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(AddSequencerResponse) - err := c.cc.Invoke(ctx, EnclaveProto_AddSequencer_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, EnclaveProto_AddSequencer_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -358,7 +346,7 @@ func (c *enclaveProtoClient) AddSequencer(ctx context.Context, in *AddSequencerR // EnclaveProtoServer is the server API for EnclaveProto service. // All implementations must embed UnimplementedEnclaveProtoServer -// for forward compatibility. +// for forward compatibility type EnclaveProtoServer interface { Status(context.Context, *StatusRequest) (*StatusResponse, error) Attestation(context.Context, *AttestationRequest) (*AttestationResponse, error) @@ -381,7 +369,7 @@ type EnclaveProtoServer interface { CreateRollup(context.Context, *CreateRollupRequest) (*CreateRollupResponse, error) ExportCrossChainData(context.Context, *ExportCrossChainDataRequest) (*ExportCrossChainDataResponse, error) DebugTraceTransaction(context.Context, *DebugTraceTransactionRequest) (*DebugTraceTransactionResponse, error) - StreamL2Updates(*StreamL2UpdatesRequest, grpc.ServerStreamingServer[EncodedUpdateResponse]) error + StreamL2Updates(*StreamL2UpdatesRequest, EnclaveProto_StreamL2UpdatesServer) error GetTotalContractCount(context.Context, *GetTotalContractCountRequest) (*GetTotalContractCountResponse, error) EnclavePublicConfig(context.Context, *EnclavePublicConfigRequest) (*EnclavePublicConfigResponse, error) MakeActive(context.Context, *MakeActiveRequest) (*MakeActiveResponse, error) @@ -389,12 +377,9 @@ type EnclaveProtoServer interface { mustEmbedUnimplementedEnclaveProtoServer() } -// UnimplementedEnclaveProtoServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedEnclaveProtoServer struct{} +// UnimplementedEnclaveProtoServer must be embedded to have forward compatible implementations. +type UnimplementedEnclaveProtoServer struct { +} func (UnimplementedEnclaveProtoServer) Status(context.Context, *StatusRequest) (*StatusResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Status not implemented") @@ -459,7 +444,7 @@ func (UnimplementedEnclaveProtoServer) ExportCrossChainData(context.Context, *Ex func (UnimplementedEnclaveProtoServer) DebugTraceTransaction(context.Context, *DebugTraceTransactionRequest) (*DebugTraceTransactionResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method DebugTraceTransaction not implemented") } -func (UnimplementedEnclaveProtoServer) StreamL2Updates(*StreamL2UpdatesRequest, grpc.ServerStreamingServer[EncodedUpdateResponse]) error { +func (UnimplementedEnclaveProtoServer) StreamL2Updates(*StreamL2UpdatesRequest, EnclaveProto_StreamL2UpdatesServer) error { return status.Errorf(codes.Unimplemented, "method StreamL2Updates not implemented") } func (UnimplementedEnclaveProtoServer) GetTotalContractCount(context.Context, *GetTotalContractCountRequest) (*GetTotalContractCountResponse, error) { @@ -475,7 +460,6 @@ func (UnimplementedEnclaveProtoServer) AddSequencer(context.Context, *AddSequenc return nil, status.Errorf(codes.Unimplemented, "method AddSequencer not implemented") } func (UnimplementedEnclaveProtoServer) mustEmbedUnimplementedEnclaveProtoServer() {} -func (UnimplementedEnclaveProtoServer) testEmbeddedByValue() {} // UnsafeEnclaveProtoServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to EnclaveProtoServer will @@ -485,13 +469,6 @@ type UnsafeEnclaveProtoServer interface { } func RegisterEnclaveProtoServer(s grpc.ServiceRegistrar, srv EnclaveProtoServer) { - // If the following call pancis, it indicates UnimplementedEnclaveProtoServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } s.RegisterService(&EnclaveProto_ServiceDesc, srv) } @@ -878,11 +855,21 @@ func _EnclaveProto_StreamL2Updates_Handler(srv interface{}, stream grpc.ServerSt if err := stream.RecvMsg(m); err != nil { return err } - return srv.(EnclaveProtoServer).StreamL2Updates(m, &grpc.GenericServerStream[StreamL2UpdatesRequest, EncodedUpdateResponse]{ServerStream: stream}) + return srv.(EnclaveProtoServer).StreamL2Updates(m, &enclaveProtoStreamL2UpdatesServer{stream}) +} + +type EnclaveProto_StreamL2UpdatesServer interface { + Send(*EncodedUpdateResponse) error + grpc.ServerStream } -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type EnclaveProto_StreamL2UpdatesServer = grpc.ServerStreamingServer[EncodedUpdateResponse] +type enclaveProtoStreamL2UpdatesServer struct { + grpc.ServerStream +} + +func (x *enclaveProtoStreamL2UpdatesServer) Send(m *EncodedUpdateResponse) error { + return x.ServerStream.SendMsg(m) +} func _EnclaveProto_GetTotalContractCount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetTotalContractCountRequest) diff --git a/go/enclave/components/block_processor.go b/go/enclave/components/block_processor.go index 5f7bac53bb..08826dbe0a 100644 --- a/go/enclave/components/block_processor.go +++ b/go/enclave/components/block_processor.go @@ -59,31 +59,31 @@ func NewBlockProcessor(storage storage.Storage, cc *crosschain.Processors, gasOr } } -func (bp *l1BlockProcessor) Process(ctx context.Context, br *common.BlockAndReceipts) (*BlockIngestionType, error) { - defer core.LogMethodDuration(bp.logger, measure.NewStopwatch(), "L1 block processed", log.BlockHashKey, br.BlockHeader.Hash()) +func (bp *l1BlockProcessor) Process(ctx context.Context, processed *common.ProcessedL1Data) (*BlockIngestionType, error) { + defer core.LogMethodDuration(bp.logger, measure.NewStopwatch(), "L1 block processed", log.BlockHashKey, processed.BlockHeader.Hash()) - ingestion, err := bp.tryAndInsertBlock(ctx, br) + ingestion, err := bp.tryAndInsertBlock(ctx, processed.BlockHeader) if err != nil { return nil, err } if !ingestion.PreGenesis { // This requires block to be stored first ... but can permanently fail a block - err = bp.crossChainProcessors.Remote.StoreCrossChainMessages(ctx, br.BlockHeader, br.Receipts()) + err = bp.crossChainProcessors.Remote.StoreCrossChainMessages(ctx, processed.BlockHeader, processed) if err != nil { return nil, errors.New("failed to process cross chain messages") } - err = bp.crossChainProcessors.Remote.StoreCrossChainValueTransfers(ctx, br.BlockHeader, br.Receipts()) + err = bp.crossChainProcessors.Remote.StoreCrossChainValueTransfers(ctx, processed.BlockHeader, processed) if err != nil { return nil, fmt.Errorf("failed to process cross chain transfers. Cause: %w", err) } } // todo @siliev - not sure if this is the best way to update the price, will pick up random stale blocks from forks? - bp.gasOracle.ProcessL1Block(br.BlockHeader) + bp.gasOracle.ProcessL1Block(processed.BlockHeader) - h := br.BlockHeader.Hash() + h := processed.BlockHeader.Hash() bp.currentL1Head = &h bp.lastIngestedBlock.Mark() return ingestion, nil @@ -99,9 +99,7 @@ func (bp *l1BlockProcessor) HealthCheck() (bool, error) { return true, nil } -func (bp *l1BlockProcessor) tryAndInsertBlock(ctx context.Context, br *common.BlockAndReceipts) (*BlockIngestionType, error) { - block := br.BlockHeader - +func (bp *l1BlockProcessor) tryAndInsertBlock(ctx context.Context, block *types.Header) (*BlockIngestionType, error) { // We insert the block into the L1 chain and store it. // in case the block already exists in the database, this will be treated like a fork, because the head changes to // the block that was already saved diff --git a/go/enclave/components/interfaces.go b/go/enclave/components/interfaces.go index 7513675251..a093a799e1 100644 --- a/go/enclave/components/interfaces.go +++ b/go/enclave/components/interfaces.go @@ -41,7 +41,7 @@ func (bit *BlockIngestionType) IsFork() bool { } type L1BlockProcessor interface { - Process(ctx context.Context, br *common.BlockAndReceipts) (*BlockIngestionType, error) + Process(ctx context.Context, processed *common.ProcessedL1Data) (*BlockIngestionType, error) GetHead(context.Context) (*types.Header, error) GetCrossChainContractAddress() *gethcommon.Address HealthCheck() (bool, error) @@ -157,5 +157,5 @@ type RollupProducer interface { type RollupConsumer interface { // ProcessBlobsInBlock - extracts the blob hashes from the block's transactions and builds the blob hashes from the blobs, // compares this with the hashes seen in the block. - ProcessBlobsInBlock(ctx context.Context, b *common.BlockAndReceipts) error + ProcessBlobsInBlock(ctx context.Context, processed *common.ProcessedL1Data) error } diff --git a/go/enclave/components/rollup_consumer.go b/go/enclave/components/rollup_consumer.go index 169c9fe929..c27507dd0e 100644 --- a/go/enclave/components/rollup_consumer.go +++ b/go/enclave/components/rollup_consumer.go @@ -49,16 +49,17 @@ func NewRollupConsumer( } // ProcessBlobsInBlock - processes the blobs in a block, extracts the rollups, verifies the rollups and stores them -func (rc *rollupConsumerImpl) ProcessBlobsInBlock(ctx context.Context, b *common.BlockAndReceipts) error { - defer core.LogMethodDuration(rc.logger, measure.NewStopwatch(), "Rollup consumer processed blobs", log.BlockHashKey, b.BlockHeader.Hash()) +func (rc *rollupConsumerImpl) ProcessBlobsInBlock(ctx context.Context, processed *common.ProcessedL1Data) error { + defer core.LogMethodDuration(rc.logger, measure.NewStopwatch(), "Rollup consumer processed blobs", log.BlockHashKey, processed.BlockHeader.Hash()) - rollups, err := rc.extractAndVerifyRollups(b) + block := processed.BlockHeader + rollups, err := rc.extractAndVerifyRollups(processed) if err != nil { - rc.logger.Error("Failed to extract rollups from block", log.BlockHashKey, b.BlockHeader.Hash(), log.ErrKey, err) + rc.logger.Error("Failed to extract rollups from block", log.BlockHashKey, block.Hash(), log.ErrKey, err) return err } if len(rollups) == 0 { - rc.logger.Trace("No rollups found in block", log.BlockHashKey, b.BlockHeader.Hash()) + rc.logger.Trace("No rollups found in block", log.BlockHashKey, block.Hash()) return nil } @@ -69,7 +70,7 @@ func (rc *rollupConsumerImpl) ProcessBlobsInBlock(ctx context.Context, b *common if len(rollups) > 1 { // todo - we need to sort this out - rc.logger.Warn(fmt.Sprintf("Multiple rollups %d in block %s", len(rollups), b.BlockHeader.Hash())) + rc.logger.Warn(fmt.Sprintf("Multiple rollups %d in block %s", len(rollups), block.Hash())) } for _, rollup := range rollups { @@ -121,21 +122,22 @@ func (rc *rollupConsumerImpl) getSignedRollup(rollups []*common.ExtRollup) ([]*c // It processes each transaction, attempting to extract and verify rollups // If a transaction is not a rollup or fails verification, it's skipped // The function only returns an error if there's a critical failure in rollup reconstruction -func (rc *rollupConsumerImpl) extractAndVerifyRollups(br *common.BlockAndReceipts) ([]*common.ExtRollup, error) { - rollups := make([]*common.ExtRollup, 0, len(*br.RelevantTransactions())) - b := br.BlockHeader - blobs, blobHashes, err := rc.extractBlobsAndHashes(br) +func (rc *rollupConsumerImpl) extractAndVerifyRollups(processed *common.ProcessedL1Data) ([]*common.ExtRollup, error) { + rollupTxs := processed.GetEvents(common.RollupTx) + rollups := make([]*common.ExtRollup, 0, len(rollupTxs)) + + blobs, blobHashes, err := rc.extractBlobsAndHashes(rollupTxs) if err != nil { return nil, err } - for i, tx := range *br.RelevantTransactions() { - t := rc.MgmtContractLib.DecodeTx(tx) + for i, tx := range rollupTxs { + t := rc.MgmtContractLib.DecodeTx(tx.Transaction) if t == nil { continue } - rollupHashes, ok := t.(*ethadapter.L1RollupHashes) + rollupHashes, ok := t.(*common.L1RollupHashes) if !ok { continue } @@ -153,15 +155,15 @@ func (rc *rollupConsumerImpl) extractAndVerifyRollups(br *common.BlockAndReceipt } rollups = append(rollups, r) - rc.logger.Info("Extracted rollup from block", log.RollupHashKey, r.Hash(), log.BlockHashKey, b.Hash()) - } + rc.logger.Info("Extracted rollup from block", log.RollupHashKey, r.Hash(), log.BlockHashKey, processed.BlockHeader.Hash()) + } return rollups, nil } // there may be many rollups in one block so the blobHashes array, so it is possible that the rollupHashes array is a // subset of the blobHashes array -func verifyBlobHashes(rollupHashes *ethadapter.L1RollupHashes, blobHashes []gethcommon.Hash) error { +func verifyBlobHashes(rollupHashes *common.L1RollupHashes, blobHashes []gethcommon.Hash) error { // more efficient lookup blobHashSet := make(map[gethcommon.Hash]struct{}, len(blobHashes)) for _, h := range blobHashes { @@ -180,12 +182,10 @@ func verifyBlobHashes(rollupHashes *ethadapter.L1RollupHashes, blobHashes []geth return nil } -func (rc *rollupConsumerImpl) extractBlobsAndHashes(br *common.BlockAndReceipts) ([]*kzg4844.Blob, []gethcommon.Hash, error) { +func (rc *rollupConsumerImpl) extractBlobsAndHashes(rollupTxs []*common.L1TxData) ([]*kzg4844.Blob, []gethcommon.Hash, error) { blobs := make([]*kzg4844.Blob, 0) - for _, txWithReceipt := range br.TxsWithReceipts { - if txWithReceipt.Blobs != nil { - blobs = append(blobs, txWithReceipt.Blobs...) - } + for _, tx := range rollupTxs { + blobs = append(blobs, tx.Blobs...) } _, blobHashes, err := ethadapter.MakeSidecar(blobs) diff --git a/go/enclave/components/shared_secret_process.go b/go/enclave/components/shared_secret_process.go index 3fdbfcc497..457fc405bc 100644 --- a/go/enclave/components/shared_secret_process.go +++ b/go/enclave/components/shared_secret_process.go @@ -11,7 +11,6 @@ import ( "github.com/ten-protocol/go-ten/go/common/log" "github.com/ten-protocol/go-ten/go/enclave/crypto" "github.com/ten-protocol/go-ten/go/enclave/storage" - "github.com/ten-protocol/go-ten/go/ethadapter" "github.com/ten-protocol/go-ten/go/ethadapter/mgmtcontractlib" ) @@ -36,44 +35,53 @@ func NewSharedSecretProcessor(mgmtcontractlib mgmtcontractlib.MgmtContractLib, a } // ProcessNetworkSecretMsgs we watch for all messages that are requesting or receiving the secret and we store the nodes attested keys -func (ssp *SharedSecretProcessor) ProcessNetworkSecretMsgs(ctx context.Context, br *common.BlockAndReceipts) []*common.ProducedSecretResponse { +func (ssp *SharedSecretProcessor) ProcessNetworkSecretMsgs(ctx context.Context, processed *common.ProcessedL1Data) []*common.ProducedSecretResponse { var responses []*common.ProducedSecretResponse - transactions := br.RelevantTransactions() - block := br.BlockHeader - for _, tx := range *transactions { - t := ssp.mgmtContractLib.DecodeTx(tx) - - // this transaction is for a node that has joined the network and needs to be sent the network secret - if scrtReqTx, ok := t.(*ethadapter.L1RequestSecretTx); ok { - ssp.logger.Info("Process shared secret request.", log.BlockHeightKey, block.Number, log.BlockHashKey, block.Hash(), log.TxKey, tx.Hash()) - resp, err := ssp.processSecretRequest(ctx, scrtReqTx) - if err != nil { - ssp.logger.Error("Failed to process shared secret request.", log.ErrKey, err) - continue - } - responses = append(responses, resp) + block := processed.BlockHeader + + // process initialize secret events + for _, txData := range processed.GetEvents(common.InitialiseSecretTx) { + t := ssp.mgmtContractLib.DecodeTx(txData.Transaction) + initSecretTx, ok := t.(*common.L1InitializeSecretTx) + if !ok { + continue + } + + att, err := common.DecodeAttestation(initSecretTx.Attestation) + if err != nil { + ssp.logger.Error("Could not decode attestation report", log.ErrKey, err) + continue } - // this transaction was created by the genesis node, we need to store their attested key to decrypt their rollup - if initSecretTx, ok := t.(*ethadapter.L1InitializeSecretTx); ok { - // todo (#1580) - ensure that we don't accidentally skip over the real `L1InitializeSecretTx` message. Otherwise - // our node will never be able to speak to other nodes. - // there must be a way to make sure that this transaction can only be sent once. - att, err := common.DecodeAttestation(initSecretTx.Attestation) - if err != nil { - ssp.logger.Error("Could not decode attestation report", log.ErrKey, err) - } - - err = ssp.storeAttestation(ctx, att) - if err != nil { - ssp.logger.Error("Could not store the attestation report.", log.ErrKey, err) - } + if err := ssp.storeAttestation(ctx, att); err != nil { + ssp.logger.Error("Could not store the attestation report.", log.ErrKey, err) } } + + // process secret requests + for _, txData := range processed.GetEvents(common.SecretRequestTx) { + t := ssp.mgmtContractLib.DecodeTx(txData.Transaction) + scrtReqTx, ok := t.(*common.L1RequestSecretTx) + if !ok { + continue + } + ssp.logger.Info("Process shared secret request.", + log.BlockHeightKey, block, + log.BlockHashKey, block.Hash(), + log.TxKey, txData.Transaction.Hash()) + + resp, err := ssp.processSecretRequest(ctx, scrtReqTx) + if err != nil { + ssp.logger.Error("Failed to process shared secret request.", log.ErrKey, err) + continue + } + responses = append(responses, resp) + } + return responses } -func (ssp *SharedSecretProcessor) processSecretRequest(ctx context.Context, req *ethadapter.L1RequestSecretTx) (*common.ProducedSecretResponse, error) { +func (ssp *SharedSecretProcessor) processSecretRequest(ctx context.Context, req *common.L1RequestSecretTx) (*common.ProducedSecretResponse, error) { att, err := common.DecodeAttestation(req.Attestation) if err != nil { return nil, fmt.Errorf("failed to decode attestation - %w", err) diff --git a/go/enclave/crosschain/block_message_extractor.go b/go/enclave/crosschain/block_message_extractor.go index a38d003603..1d496d4a04 100644 --- a/go/enclave/crosschain/block_message_extractor.go +++ b/go/enclave/crosschain/block_message_extractor.go @@ -39,33 +39,22 @@ func (m *blockMessageExtractor) Enabled() bool { return m.GetBusAddress().Big().Cmp(gethcommon.Big0) != 0 } -func (m *blockMessageExtractor) StoreCrossChainValueTransfers(ctx context.Context, block *types.Header, receipts common.L1Receipts) error { +func (m *blockMessageExtractor) StoreCrossChainValueTransfers(ctx context.Context, block *types.Header, processed *common.ProcessedL1Data) error { defer core.LogMethodDuration(m.logger, measure.NewStopwatch(), "BlockHeader value transfer messages processed", log.BlockHashKey, block.Hash()) - /*areReceiptsValid := common.VerifyReceiptHash(block, receipts) - - if !areReceiptsValid && m.Enabled() { - m.logger.Error("Invalid receipts submitted", log.BlockHashKey, block.Hash()) - return fmt.Errorf("receipts do not match the receipt root for the block") - }*/ - - if len(receipts) == 0 { + transferEvents := processed.GetEvents(common.CrossChainValueTranserTx) + if len(transferEvents) == 0 { return nil } - transfers, err := m.getValueTransferMessages(receipts) - if err != nil { - m.logger.Error("Error encountered while getting inbound value transfers from block", log.BlockHashKey, block.Hash(), log.ErrKey, err) - return err - } - - hasTransfers := len(transfers) > 0 - if !hasTransfers { - return nil + var transfers common.ValueTransferEvents + for _, txData := range transferEvents { + if txData.ValueTransfers != nil { + transfers = append(transfers, txData.ValueTransfers...) + } } - m.logger.Trace("Storing value transfers for block", "nr", len(transfers), log.BlockHashKey, block.Hash()) - err = m.storage.StoreValueTransfers(ctx, block.Hash(), transfers) + err := m.storage.StoreValueTransfers(ctx, block.Hash(), transfers) if err != nil { m.logger.Crit("Unable to store the transfers", log.ErrKey, err) return err @@ -77,24 +66,27 @@ func (m *blockMessageExtractor) StoreCrossChainValueTransfers(ctx context.Contex // StoreCrossChainMessages - extracts the cross chain messages for the corresponding block from the receipts. // The messages will be stored in DB storage for later usage. // block - the L1 block for which events are extracted. -// receipts - all of the receipts for the corresponding block. This is validated. -func (m *blockMessageExtractor) StoreCrossChainMessages(ctx context.Context, block *types.Header, receipts common.L1Receipts) error { +// processed - all the txs and events relating to the message bus and management contract identified by the logs. +func (m *blockMessageExtractor) StoreCrossChainMessages(ctx context.Context, block *types.Header, processed *common.ProcessedL1Data) error { defer core.LogMethodDuration(m.logger, measure.NewStopwatch(), "BlockHeader cross chain messages processed", log.BlockHashKey, block.Hash()) - if len(receipts) == 0 { + messageEvents := processed.GetEvents(common.CrossChainMessageTx) + if len(messageEvents) == 0 { return nil } - - lazilyLogReceiptChecksum(block, receipts, m.logger) - messages, err := m.getCrossChainMessages(block, receipts) - if err != nil { - m.logger.Error("Converting receipts to messages failed.", log.ErrKey, err) - return err + var messages common.CrossChainMessages + var receipts types.Receipts + for _, txData := range messageEvents { + if txData.CrossChainMessages != nil { + messages = append(messages, txData.CrossChainMessages...) + receipts = append(receipts, txData.Receipt) + } } + lazilyLogReceiptChecksum(block, receipts, m.logger) if len(messages) > 0 { m.logger.Info(fmt.Sprintf("Storing %d messages for block", len(messages)), log.BlockHashKey, block.Hash()) - err = m.storage.StoreL1Messages(ctx, block.Hash(), messages) + err := m.storage.StoreL1Messages(ctx, block.Hash(), messages) if err != nil { m.logger.Crit("Unable to store the messages", log.ErrKey, err) return err @@ -108,49 +100,3 @@ func (m *blockMessageExtractor) StoreCrossChainMessages(ctx context.Context, blo func (m *blockMessageExtractor) GetBusAddress() *common.L1Address { return m.busAddress } - -// getCrossChainMessages - Converts the relevant logs from the appropriate message bus address to synthetic transactions and returns them -func (m *blockMessageExtractor) getCrossChainMessages(block *types.Header, receipts common.L1Receipts) (common.CrossChainMessages, error) { - if len(receipts) == 0 { - return make(common.CrossChainMessages, 0), nil - } - - // Retrieves the relevant logs from the message bus. - logs, err := filterLogsFromReceipts(receipts, m.GetBusAddress(), &CrossChainEventID) - if err != nil { - m.logger.Error("Error encountered when filtering receipt logs.", log.ErrKey, err) - return make(common.CrossChainMessages, 0), err - } - m.logger.Trace("Extracted cross chain logs from receipts", "logCount", len(logs)) - - messages, err := convertLogsToMessages(logs, CrossChainEventName, MessageBusABI) - if err != nil { - m.logger.Error("Error encountered converting the extracted relevant logs to messages", log.ErrKey, err) - return make(common.CrossChainMessages, 0), err - } - - m.logger.Trace(fmt.Sprintf("Found %d cross chain messages that will be submitted to L2!", len(messages)), log.BlockHashKey, block.Hash()) - - return messages, nil -} - -func (m *blockMessageExtractor) getValueTransferMessages(receipts common.L1Receipts) (common.ValueTransferEvents, error) { - if len(receipts) == 0 { - return make(common.ValueTransferEvents, 0), nil - } - - // Retrieves the relevant logs from the message bus. - logs, err := filterLogsFromReceipts(receipts, m.GetBusAddress(), &ValueTransferEventID) - if err != nil { - m.logger.Error("Error encountered when filtering receipt logs.", log.ErrKey, err) - return make(common.ValueTransferEvents, 0), err - } - - transfers, err := ConvertLogsToValueTransfers(logs, ValueTransferEventName, MessageBusABI) - if err != nil { - m.logger.Error("Error encountered when converting value transfer receipt logs.", log.ErrKey, err) - return make(common.ValueTransferEvents, 0), err - } - - return transfers, nil -} diff --git a/go/enclave/crosschain/common.go b/go/enclave/crosschain/common.go index 68806301ed..847c04d966 100644 --- a/go/enclave/crosschain/common.go +++ b/go/enclave/crosschain/common.go @@ -18,16 +18,24 @@ import ( "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/contracts/generated/ManagementContract" "github.com/ten-protocol/go-ten/contracts/generated/MessageBus" "github.com/ten-protocol/go-ten/go/common" ) var ( - MessageBusABI, _ = abi.JSON(strings.NewReader(MessageBus.MessageBusMetaData.ABI)) - CrossChainEventName = "LogMessagePublished" - CrossChainEventID = MessageBusABI.Events[CrossChainEventName].ID - ValueTransferEventName = "ValueTransfer" - ValueTransferEventID = MessageBusABI.Events["ValueTransfer"].ID + MessageBusABI, _ = abi.JSON(strings.NewReader(MessageBus.MessageBusMetaData.ABI)) + MgmtContractABI, _ = abi.JSON(strings.NewReader(ManagementContract.ManagementContractMetaData.ABI)) + CrossChainEventName = "LogMessagePublished" + CrossChainEventID = MessageBusABI.Events[CrossChainEventName].ID + ValueTransferEventName = "ValueTransfer" + ValueTransferEventID = MessageBusABI.Events["ValueTransfer"].ID + SequencerEnclaveGrantedEventID = MgmtContractABI.Events["SequencerEnclaveGranted"].ID + SequencerEnclaveRevokedEventID = MgmtContractABI.Events["SequencerEnclaveRevoked"].ID + NetworkSecretRequestedID = MgmtContractABI.Events["NetworkSecretRequested"].ID + NetworkSecretRespondedID = MgmtContractABI.Events["NetworkSecretResponded"].ID + RollupAddedID = MgmtContractABI.Events["RollupAdded"].ID + ImportantContractAddressUpdatedID = MgmtContractABI.Events["ImportantContractAddressUpdated"].ID ) func lazilyLogReceiptChecksum(block *types.Header, receipts types.Receipts, logger gethlog.Logger) { @@ -64,7 +72,7 @@ func filterLogsFromReceipts(receipts types.Receipts, address *gethcommon.Address continue } - logsForReceipt, err := filterLogsFromReceipt(receipt, address, topic) + logsForReceipt, err := FilterLogsFromReceipt(receipt, address, topic) if err != nil { return logs, err } @@ -75,8 +83,8 @@ func filterLogsFromReceipts(receipts types.Receipts, address *gethcommon.Address return logs, nil } -// filterLogsFromReceipt - filters the receipt for logs matching address, if provided and matching any of the provided topics. -func filterLogsFromReceipt(receipt *types.Receipt, address *gethcommon.Address, topic *gethcommon.Hash) ([]types.Log, error) { +// FilterLogsFromReceipt - filters the receipt for logs matching address, if provided and matching any of the provided topics. +func FilterLogsFromReceipt(receipt *types.Receipt, address *gethcommon.Address, topic *gethcommon.Hash) ([]types.Log, error) { logs := make([]types.Log, 0) if receipt == nil { @@ -104,8 +112,8 @@ func filterLogsFromReceipt(receipt *types.Receipt, address *gethcommon.Address, return logs, nil } -// convertLogsToMessages - converts the logs of the event to messages. The logs should be filtered, otherwise fails. -func convertLogsToMessages(logs []types.Log, eventName string, messageBusABI abi.ABI) (common.CrossChainMessages, error) { +// ConvertLogsToMessages - converts the logs of the event to messages. The logs should be filtered, otherwise fails. +func ConvertLogsToMessages(logs []types.Log, eventName string, messageBusABI abi.ABI) (common.CrossChainMessages, error) { messages := make(common.CrossChainMessages, 0) for _, log := range logs { @@ -133,7 +141,7 @@ func createCrossChainMessage(event MessageBus.MessageBusLogMessagePublished) Mes } } -// convertLogsToMessages - converts the logs of the event to messages. The logs should be filtered, otherwise fails. +// ConvertLogsToValueTransfers - converts the logs of the event to messages. The logs should be filtered, otherwise fails. func ConvertLogsToValueTransfers(logs []types.Log, eventName string, messageBusABI abi.ABI) (common.ValueTransferEvents, error) { messages := make(common.ValueTransferEvents, 0) @@ -141,11 +149,11 @@ func ConvertLogsToValueTransfers(logs []types.Log, eventName string, messageBusA if len(log.Topics) != 3 { return nil, fmt.Errorf("invalid number of topics in log: %d", len(log.Topics)) } - var event MessageBus.MessageBusValueTransfer err := messageBusABI.UnpackIntoInterface(&event, eventName, log.Data) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to unpack event data: %w\nData length: %d\nEvent: %s", + err, len(log.Data), eventName) } messages = append(messages, common.ValueTransferEvent{ diff --git a/go/enclave/crosschain/interfaces.go b/go/enclave/crosschain/interfaces.go index 251d5f0bd8..6876bbc8ad 100644 --- a/go/enclave/crosschain/interfaces.go +++ b/go/enclave/crosschain/interfaces.go @@ -19,9 +19,9 @@ type ( type BlockMessageExtractor interface { // StoreCrossChainMessages - Verifies receipts belong to block and saves the relevant cross chain messages from the receipts - StoreCrossChainMessages(ctx context.Context, block *types.Header, receipts common.L1Receipts) error + StoreCrossChainMessages(ctx context.Context, block *types.Header, processed *common.ProcessedL1Data) error - StoreCrossChainValueTransfers(ctx context.Context, block *types.Header, receipts common.L1Receipts) error + StoreCrossChainValueTransfers(ctx context.Context, block *types.Header, processed *common.ProcessedL1Data) error // GetBusAddress - Returns the L1 message bus address. GetBusAddress() *common.L1Address diff --git a/go/enclave/crosschain/message_bus_manager.go b/go/enclave/crosschain/message_bus_manager.go index 8d59454262..2ecae0b396 100644 --- a/go/enclave/crosschain/message_bus_manager.go +++ b/go/enclave/crosschain/message_bus_manager.go @@ -110,7 +110,7 @@ func (m *MessageBusManager) GenerateMessageBusDeployTx() (*common.L2Tx, error) { return stx, nil } -// ExtractLocalMessages - Finds relevant logs in the receipts and converts them to cross chain messages. +// ExtractOutboundMessages - Finds relevant logs in the receipts and converts them to cross chain messages. func (m *MessageBusManager) ExtractOutboundMessages(ctx context.Context, receipts common.L2Receipts) (common.CrossChainMessages, error) { logs, err := filterLogsFromReceipts(receipts, m.messageBusAddress, &CrossChainEventID) if err != nil { @@ -118,7 +118,7 @@ func (m *MessageBusManager) ExtractOutboundMessages(ctx context.Context, receipt return make(common.CrossChainMessages, 0), err } - messages, err := convertLogsToMessages(logs, CrossChainEventName, MessageBusABI) + messages, err := ConvertLogsToMessages(logs, CrossChainEventName, MessageBusABI) if err != nil { m.logger.Error("Error converting messages from L2 message bus!", log.ErrKey, err) return make(common.CrossChainMessages, 0), err diff --git a/go/enclave/enclave.go b/go/enclave/enclave.go index 3664def898..5e75133cfb 100644 --- a/go/enclave/enclave.go +++ b/go/enclave/enclave.go @@ -262,11 +262,11 @@ func (e *enclaveImpl) StreamL2Updates() (chan common.StreamL2UpdatesResponse, fu } // SubmitL1Block is used to update the enclave with an additional L1 block. -func (e *enclaveImpl) SubmitL1Block(ctx context.Context, blockHeader *types.Header, receipts []*common.TxAndReceiptAndBlobs) (*common.BlockSubmissionResponse, common.SystemError) { +func (e *enclaveImpl) SubmitL1Block(ctx context.Context, processed *common.ProcessedL1Data) (*common.BlockSubmissionResponse, common.SystemError) { if systemError := checkStopping(e.stopControl); systemError != nil { return nil, systemError } - return e.adminAPI.SubmitL1Block(ctx, blockHeader, receipts) + return e.adminAPI.SubmitL1Block(ctx, processed) } func (e *enclaveImpl) SubmitBatch(ctx context.Context, extBatch *common.ExtBatch) common.SystemError { diff --git a/go/enclave/enclave_admin_service.go b/go/enclave/enclave_admin_service.go index b635ebec81..0b84c6f4ba 100644 --- a/go/enclave/enclave_admin_service.go +++ b/go/enclave/enclave_admin_service.go @@ -138,12 +138,8 @@ func NewEnclaveAdminAPI(config *enclaveconfig.EnclaveConfig, storage storage.Sto return eas } -func (e *enclaveAdminService) AddSequencer(id common.EnclaveID, proof types.Receipt) common.SystemError { - e.mainMutex.Lock() - defer e.mainMutex.Unlock() - +func (e *enclaveAdminService) AddSequencer(id common.EnclaveID, _ types.Receipt) common.SystemError { // todo - use the proof - err := e.storage.StoreNodeType(context.Background(), id, common.BackupSequencer) if err != nil { return responses.ToInternalError(err) @@ -177,19 +173,16 @@ func (e *enclaveAdminService) MakeActive() common.SystemError { } // SubmitL1Block is used to update the enclave with an additional L1 block. -func (e *enclaveAdminService) SubmitL1Block(ctx context.Context, blockHeader *types.Header, receipts []*common.TxAndReceiptAndBlobs) (*common.BlockSubmissionResponse, common.SystemError) { +func (e *enclaveAdminService) SubmitL1Block(ctx context.Context, processed *common.ProcessedL1Data) (*common.BlockSubmissionResponse, common.SystemError) { e.dataInMutex.Lock() defer e.dataInMutex.Unlock() + blockHeader := processed.BlockHeader e.logger.Info("SubmitL1Block", log.BlockHeightKey, blockHeader.Number, log.BlockHashKey, blockHeader.Hash()) - // If the block and receipts do not match, reject the block. - br, err := common.ParseBlockAndReceipts(blockHeader, receipts) - if err != nil { - return nil, e.rejectBlockErr(ctx, fmt.Errorf("could not submit L1 block. Cause: %w", err)) - } + // TODO verify proof provided with block processed.Proof - result, err := e.ingestL1Block(ctx, br) + result, err := e.ingestL1Block(ctx, processed) if err != nil { return nil, e.rejectBlockErr(ctx, fmt.Errorf("could not submit L1 block. Cause: %w", err)) } @@ -203,7 +196,7 @@ func (e *enclaveAdminService) SubmitL1Block(ctx context.Context, blockHeader *ty return nil, e.rejectBlockErr(ctx, fmt.Errorf("could not submit L1 block. Cause: %w", err)) } - bsr := &common.BlockSubmissionResponse{ProducedSecretResponses: e.sharedSecretProcessor.ProcessNetworkSecretMsgs(ctx, br)} + bsr := &common.BlockSubmissionResponse{ProducedSecretResponses: e.sharedSecretProcessor.ProcessNetworkSecretMsgs(ctx, processed)} return bsr, nil } @@ -471,25 +464,36 @@ func (e *enclaveAdminService) streamEventsForNewHeadBatch(ctx context.Context, b } } -func (e *enclaveAdminService) ingestL1Block(ctx context.Context, br *common.BlockAndReceipts) (*components.BlockIngestionType, error) { - e.logger.Info("Start ingesting block", log.BlockHashKey, br.BlockHeader.Hash()) - ingestion, err := e.l1BlockProcessor.Process(ctx, br) +func (e *enclaveAdminService) ingestL1Block(ctx context.Context, processed *common.ProcessedL1Data) (*components.BlockIngestionType, error) { + e.logger.Info("Start ingesting block", log.BlockHashKey, processed.BlockHeader.Hash()) + ingestion, err := e.l1BlockProcessor.Process(ctx, processed) if err != nil { // only warn for unexpected errors if errors.Is(err, errutil.ErrBlockAncestorNotFound) || errors.Is(err, errutil.ErrBlockAlreadyProcessed) { - e.logger.Debug("Did not ingest block", log.ErrKey, err, log.BlockHashKey, br.BlockHeader.Hash()) + e.logger.Debug("Did not ingest block", log.ErrKey, err, log.BlockHashKey, processed.BlockHeader.Hash()) } else { - e.logger.Warn("Failed ingesting block", log.ErrKey, err, log.BlockHashKey, br.BlockHeader.Hash()) + e.logger.Warn("Failed ingesting block", log.ErrKey, err, log.BlockHashKey, processed.BlockHeader.Hash()) } return nil, err } - err = e.rollupConsumer.ProcessBlobsInBlock(ctx, br) + err = e.rollupConsumer.ProcessBlobsInBlock(ctx, processed) if err != nil && !errors.Is(err, components.ErrDuplicateRollup) { - e.logger.Error("Encountered error while processing l1 block", log.ErrKey, err) + e.logger.Error("Encountered error while processing l1 block rollups", log.ErrKey, err) // Unsure what to do here; block has been stored } + // todo handle sequencer revoked - could move all of this into a separate processor + sequencerAddedTxs := processed.GetEvents(common.SequencerAddedTx) + for _, tx := range sequencerAddedTxs { + if tx.HasSequencerEnclaveID() { + err = e.AddSequencer(tx.SequencerEnclaveID, *tx.Receipt) + if err != nil { + e.logger.Crit("Encountered error while adding sequencer enclaveID", log.ErrKey, err) + } + } + } + if ingestion.IsFork() { e.registry.OnL1Reorg(ingestion) err := e.service.OnL1Fork(ctx, ingestion.ChainFork) diff --git a/go/enclave/rpc_server.go b/go/enclave/rpc_server.go index 90d2f6b572..7d87fa6210 100644 --- a/go/enclave/rpc_server.go +++ b/go/enclave/rpc_server.go @@ -142,19 +142,13 @@ func (s *RPCServer) RPCEncryptionKey(ctx context.Context, _ *generated.RPCEncryp } func (s *RPCServer) SubmitL1Block(ctx context.Context, request *generated.SubmitBlockRequest) (*generated.SubmitBlockResponse, error) { - bl, err := s.decodeBlock(request.EncodedBlock) - if err != nil { - s.logger.Error("Error decoding block", log.ErrKey, err) - return nil, err - } - - txReceiptsAndBlobs, err := s.decodeReceiptsAndBlobs(request.EncodedReceipts) + processedData, err := s.decodeProcessedData(request.EncodedProcessedData) if err != nil { s.logger.Error("Error decoding receipts", log.ErrKey, err) return nil, err } - blockSubmissionResponse, err := s.enclave.SubmitL1Block(ctx, bl, txReceiptsAndBlobs) + blockSubmissionResponse, err := s.enclave.SubmitL1Block(ctx, processedData) if err != nil { var rejErr *errutil.BlockRejectError isReject := errors.As(err, &rejErr) @@ -427,25 +421,16 @@ func (s *RPCServer) EnclavePublicConfig(ctx context.Context, _ *generated.Enclav }, nil } -func (s *RPCServer) decodeBlock(encodedBlock []byte) (*types.Header, error) { - block := types.Header{} - err := rlp.DecodeBytes(encodedBlock, &block) - if err != nil { - return nil, fmt.Errorf("unable to decode block, bytes=%x, err=%w", encodedBlock, err) - } - return &block, nil -} - -// decodeReceiptsAndBlobs - converts the rlp encoded bytes to receipts if possible. -func (s *RPCServer) decodeReceiptsAndBlobs(encodedReceipts []byte) ([]*common.TxAndReceiptAndBlobs, error) { - receipts := make([]*common.TxAndReceiptAndBlobs, 0) +// decodeProcessedData - converts the rlp encoded bytes to processed if possible. +func (s *RPCServer) decodeProcessedData(encodedData []byte) (*common.ProcessedL1Data, error) { + var processed common.ProcessedL1Data - err := rlp.DecodeBytes(encodedReceipts, &receipts) + err := rlp.DecodeBytes(encodedData, &processed) if err != nil { - return nil, fmt.Errorf("unable to decode receipts, bytes=%x, err=%w", encodedReceipts, err) + return nil, fmt.Errorf("unable to decode receipts, bytes=%x, err=%w", encodedData, err) } - return receipts, nil + return &processed, nil } func toRPCError(err common.SystemError) *generated.SystemError { diff --git a/go/ethadapter/blob.go b/go/ethadapter/blob.go index d16441c71b..c91022be66 100644 --- a/go/ethadapter/blob.go +++ b/go/ethadapter/blob.go @@ -151,5 +151,6 @@ func ReconstructRollup(blobs []*kzg4844.Blob) (*common.ExtRollup, error) { if err := rlp.DecodeBytes(data, &rollup); err != nil { return nil, fmt.Errorf("could not decode rollup bytes. Cause: %w", err) } + return &rollup, nil } diff --git a/go/ethadapter/erc20contractlib/erc20_contract_lib.go b/go/ethadapter/erc20contractlib/erc20_contract_lib.go index 162d0f4da8..2f465b663f 100644 --- a/go/ethadapter/erc20contractlib/erc20_contract_lib.go +++ b/go/ethadapter/erc20contractlib/erc20_contract_lib.go @@ -4,11 +4,11 @@ import ( "math/big" "strings" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ten-protocol/go-ten/go/ethadapter" + "github.com/ten-protocol/go-ten/go/common" + "github.com/ethereum/go-ethereum/accounts/abi" gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" ) const methodBytesLen = 4 @@ -17,10 +17,10 @@ const methodBytesLen = 4 type ERC20ContractLib interface { // DecodeTx receives a *types.Transaction and converts it to an common.L1Transaction // returns nil if the transaction is not convertible - DecodeTx(tx *types.Transaction) ethadapter.L1Transaction + DecodeTx(tx *types.Transaction) common.L1TenTransaction // CreateDepositTx receives an common.L1Transaction and converts it to an eth transaction - CreateDepositTx(tx *ethadapter.L1DepositTx) types.TxData + CreateDepositTx(tx *common.L1DepositTx) types.TxData } // erc20ContractLibImpl takes a mgmtContractAddr and processes multiple erc20ContractAddrs @@ -44,7 +44,7 @@ func NewERC20ContractLib(mgmtContractAddr *gethcommon.Address, contractAddrs ... } } -func (c *erc20ContractLibImpl) CreateDepositTx(tx *ethadapter.L1DepositTx) types.TxData { +func (c *erc20ContractLibImpl) CreateDepositTx(tx *common.L1DepositTx) types.TxData { data, err := c.contractABI.Pack("transfer", &tx.To, tx.Amount) if err != nil { panic(err) @@ -56,7 +56,7 @@ func (c *erc20ContractLibImpl) CreateDepositTx(tx *ethadapter.L1DepositTx) types } } -func (c *erc20ContractLibImpl) DecodeTx(tx *types.Transaction) ethadapter.L1Transaction { +func (c *erc20ContractLibImpl) DecodeTx(tx *types.Transaction) common.L1TenTransaction { if !c.isRelevant(tx) { return nil } @@ -92,7 +92,7 @@ func (c *erc20ContractLibImpl) DecodeTx(tx *types.Transaction) ethadapter.L1Tran panic(err) } - return ðadapter.L1DepositTx{ + return &common.L1DepositTx{ Amount: amount.(*big.Int), To: &toAddr, TokenContract: tx.To(), diff --git a/go/ethadapter/geth_rpc_client.go b/go/ethadapter/geth_rpc_client.go index a9290cad6e..298b8af7e2 100644 --- a/go/ethadapter/geth_rpc_client.go +++ b/go/ethadapter/geth_rpc_client.go @@ -151,6 +151,13 @@ func (e *gethRPCClient) TransactionReceipt(hash gethcommon.Hash) (*types.Receipt return e.client.TransactionReceipt(ctx, hash) } +func (e *gethRPCClient) TransactionByHash(hash gethcommon.Hash) (*types.Transaction, bool, error) { + ctx, cancel := context.WithTimeout(context.Background(), e.timeout) + defer cancel() + + return e.client.TransactionByHash(ctx, hash) +} + func (e *gethRPCClient) Nonce(account gethcommon.Address) (uint64, error) { ctx, cancel := context.WithTimeout(context.Background(), e.timeout) defer cancel() diff --git a/go/ethadapter/interface.go b/go/ethadapter/interface.go index 1245da18d4..59e4daa770 100644 --- a/go/ethadapter/interface.go +++ b/go/ethadapter/interface.go @@ -21,6 +21,7 @@ type EthClient interface { BlockByNumber(n *big.Int) (*types.Block, error) // retrieves a block given a number - returns head block if n is nil SendTransaction(signedTx *types.Transaction) error // issues an ethereum transaction (expects signed tx) TransactionReceipt(hash gethcommon.Hash) (*types.Receipt, error) // fetches the ethereum transaction receipt + TransactionByHash(hash gethcommon.Hash) (*types.Transaction, bool, error) // fetches the ethereum tx Nonce(address gethcommon.Address) (uint64, error) // fetches the account nonce to use in the next transaction BalanceAt(account gethcommon.Address, blockNumber *big.Int) (*big.Int, error) // fetches the balance of the account GetLogs(q ethereum.FilterQuery) ([]types.Log, error) // fetches the logs for a given query diff --git a/go/ethadapter/l1_transaction.go b/go/ethadapter/l1_transaction.go deleted file mode 100644 index e9e2f867bc..0000000000 --- a/go/ethadapter/l1_transaction.go +++ /dev/null @@ -1,78 +0,0 @@ -package ethadapter - -import ( - "crypto/ecdsa" - "fmt" - "math/big" - - "github.com/ten-protocol/go-ten/go/common" - - gethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" -) - -// L1Transaction is an abstraction that transforms an Ethereum transaction into a format that can be consumed more -// easily by TEN. -type L1Transaction interface{} - -type L1RollupTx struct { - Rollup common.EncodedRollup -} - -type L1RollupHashes struct { - BlobHashes []gethcommon.Hash -} - -type L1DepositTx struct { - Amount *big.Int // Amount to be deposited - To *gethcommon.Address // Address the ERC20 Transfer was made to (always be the Management Contract Addr) - Sender *gethcommon.Address // Address that issued the ERC20, the token holder or tx.origin - TokenContract *gethcommon.Address // Address of the ERC20 Contract address that was executed -} - -type L1RespondSecretTx struct { - Secret []byte - RequesterID gethcommon.Address - AttesterID gethcommon.Address - AttesterSig []byte -} - -type L1SetImportantContractsTx struct { - Key string - NewAddress gethcommon.Address -} - -// Sign signs the payload with a given private key -func (l *L1RespondSecretTx) Sign(privateKey *ecdsa.PrivateKey) *L1RespondSecretTx { - var data []byte - data = append(data, l.AttesterID.Bytes()...) - data = append(data, l.RequesterID.Bytes()...) - data = append(data, string(l.Secret)...) - - ethereumMessageHash := func(data []byte) []byte { - prefix := fmt.Sprintf("\x19Ethereum Signed Message:\n%d", len(data)) - return crypto.Keccak256([]byte(prefix), data) - } - - hashedData := ethereumMessageHash(data) - // sign the hash - signedHash, err := crypto.Sign(hashedData, privateKey) - if err != nil { - return nil - } - - // set recovery id to 27; prevent malleable signatures - signedHash[64] += 27 - l.AttesterSig = signedHash - return l -} - -type L1RequestSecretTx struct { - Attestation common.EncodedAttestationReport -} - -type L1InitializeSecretTx struct { - EnclaveID *gethcommon.Address - InitialSecret []byte - Attestation common.EncodedAttestationReport -} diff --git a/go/ethadapter/mgmtcontractlib/mgmt_contract_lib.go b/go/ethadapter/mgmtcontractlib/mgmt_contract_lib.go index d6184cc4d0..839db94354 100644 --- a/go/ethadapter/mgmtcontractlib/mgmt_contract_lib.go +++ b/go/ethadapter/mgmtcontractlib/mgmt_contract_lib.go @@ -25,13 +25,13 @@ const methodBytesLen = 4 // messages for call requests, and converting ethereum transactions into L1Transactions. type MgmtContractLib interface { IsMock() bool - CreateBlobRollup(t *ethadapter.L1RollupTx) (types.TxData, error) - CreateRequestSecret(tx *ethadapter.L1RequestSecretTx) types.TxData - CreateRespondSecret(tx *ethadapter.L1RespondSecretTx, verifyAttester bool) types.TxData - CreateInitializeSecret(tx *ethadapter.L1InitializeSecretTx) types.TxData + CreateBlobRollup(t *common.L1RollupTx) (types.TxData, error) + CreateRequestSecret(tx *common.L1RequestSecretTx) types.TxData + CreateRespondSecret(tx *common.L1RespondSecretTx, verifyAttester bool) types.TxData + CreateInitializeSecret(tx *common.L1InitializeSecretTx) types.TxData // DecodeTx receives a *types.Transaction and converts it to a common.L1Transaction - DecodeTx(tx *types.Transaction) ethadapter.L1Transaction + DecodeTx(tx *types.Transaction) common.L1TenTransaction GetContractAddr() *gethcommon.Address // The methods below are used to create call messages for mgmt contract data and unpack the responses @@ -75,7 +75,7 @@ func (c *contractLibImpl) GetContractAddr() *gethcommon.Address { return c.addr } -func (c *contractLibImpl) DecodeTx(tx *types.Transaction) ethadapter.L1Transaction { +func (c *contractLibImpl) DecodeTx(tx *types.Transaction) common.L1TenTransaction { if tx.To() == nil || tx.To().Hex() != c.addr.Hex() || len(tx.Data()) == 0 { return nil } @@ -88,7 +88,7 @@ func (c *contractLibImpl) DecodeTx(tx *types.Transaction) ethadapter.L1Transacti switch method.Name { case AddRollupMethod: if tx.Type() == types.BlobTxType { - return ðadapter.L1RollupHashes{ + return &common.L1RollupHashes{ BlobHashes: tx.BlobHashes(), } } else { @@ -116,7 +116,7 @@ func (c *contractLibImpl) DecodeTx(tx *types.Transaction) ethadapter.L1Transacti } // CreateBlobRollup creates a BlobTx, encoding the rollup data into blobs. -func (c *contractLibImpl) CreateBlobRollup(t *ethadapter.L1RollupTx) (types.TxData, error) { +func (c *contractLibImpl) CreateBlobRollup(t *common.L1RollupTx) (types.TxData, error) { decodedRollup, err := common.DecodeRollup(t.Rollup) if err != nil { panic(err) @@ -161,7 +161,7 @@ func (c *contractLibImpl) CreateBlobRollup(t *ethadapter.L1RollupTx) (types.TxDa }, nil } -func (c *contractLibImpl) CreateRequestSecret(tx *ethadapter.L1RequestSecretTx) types.TxData { +func (c *contractLibImpl) CreateRequestSecret(tx *common.L1RequestSecretTx) types.TxData { data, err := c.contractABI.Pack(RequestSecretMethod, base64EncodeToString(tx.Attestation)) if err != nil { panic(err) @@ -173,7 +173,7 @@ func (c *contractLibImpl) CreateRequestSecret(tx *ethadapter.L1RequestSecretTx) } } -func (c *contractLibImpl) CreateRespondSecret(tx *ethadapter.L1RespondSecretTx, verifyAttester bool) types.TxData { +func (c *contractLibImpl) CreateRespondSecret(tx *common.L1RespondSecretTx, verifyAttester bool) types.TxData { data, err := c.contractABI.Pack( RespondSecretMethod, tx.AttesterID, @@ -191,7 +191,7 @@ func (c *contractLibImpl) CreateRespondSecret(tx *ethadapter.L1RespondSecretTx, } } -func (c *contractLibImpl) CreateInitializeSecret(tx *ethadapter.L1InitializeSecretTx) types.TxData { +func (c *contractLibImpl) CreateInitializeSecret(tx *common.L1InitializeSecretTx) types.TxData { data, err := c.contractABI.Pack( InitializeSecretMethod, tx.EnclaveID, @@ -319,7 +319,7 @@ func (c *contractLibImpl) DecodeImportantAddressResponse(callResponse []byte) (g return address, nil } -func (c *contractLibImpl) unpackInitSecretTx(tx *types.Transaction, method *abi.Method, contractCallData map[string]interface{}) *ethadapter.L1InitializeSecretTx { +func (c *contractLibImpl) unpackInitSecretTx(tx *types.Transaction, method *abi.Method, contractCallData map[string]interface{}) *common.L1InitializeSecretTx { err := method.Inputs.UnpackIntoMap(contractCallData, tx.Data()[methodBytesLen:]) if err != nil { panic(err) @@ -335,12 +335,12 @@ func (c *contractLibImpl) unpackInitSecretTx(tx *types.Transaction, method *abi. } // todo (#1275) - add the other fields - return ðadapter.L1InitializeSecretTx{ + return &common.L1InitializeSecretTx{ Attestation: att, } } -func (c *contractLibImpl) unpackRequestSecretTx(tx *types.Transaction, method *abi.Method, contractCallData map[string]interface{}) *ethadapter.L1RequestSecretTx { +func (c *contractLibImpl) unpackRequestSecretTx(tx *types.Transaction, method *abi.Method, contractCallData map[string]interface{}) *common.L1RequestSecretTx { err := method.Inputs.UnpackIntoMap(contractCallData, tx.Data()[methodBytesLen:]) if err != nil { panic(err) @@ -354,12 +354,12 @@ func (c *contractLibImpl) unpackRequestSecretTx(tx *types.Transaction, method *a if err != nil { c.logger.Crit("could not decode attestation request.", log.ErrKey, err) } - return ðadapter.L1RequestSecretTx{ + return &common.L1RequestSecretTx{ Attestation: att, } } -func (c *contractLibImpl) unpackRespondSecretTx(tx *types.Transaction, method *abi.Method, contractCallData map[string]interface{}) *ethadapter.L1RespondSecretTx { +func (c *contractLibImpl) unpackRespondSecretTx(tx *types.Transaction, method *abi.Method, contractCallData map[string]interface{}) *common.L1RespondSecretTx { err := method.Inputs.UnpackIntoMap(contractCallData, tx.Data()[methodBytesLen:]) if err != nil { c.logger.Crit("could not unpack transaction.", log.ErrKey, err) @@ -392,14 +392,14 @@ func (c *contractLibImpl) unpackRespondSecretTx(tx *types.Transaction, method *a c.logger.Crit("could not decode responseSecret data") } - return ðadapter.L1RespondSecretTx{ + return &common.L1RespondSecretTx{ AttesterID: attesterAddr, RequesterID: requesterAddr, Secret: responseSecretBytes[:], } } -func (c *contractLibImpl) unpackSetImportantContractsTx(tx *types.Transaction, method *abi.Method, contractCallData map[string]interface{}) (*ethadapter.L1SetImportantContractsTx, error) { +func (c *contractLibImpl) unpackSetImportantContractsTx(tx *types.Transaction, method *abi.Method, contractCallData map[string]interface{}) (*common.L1SetImportantContractsTx, error) { err := method.Inputs.UnpackIntoMap(contractCallData, tx.Data()[methodBytesLen:]) if err != nil { return nil, fmt.Errorf("could not unpack transaction. Cause: %w", err) @@ -423,7 +423,7 @@ func (c *contractLibImpl) unpackSetImportantContractsTx(tx *types.Transaction, m return nil, fmt.Errorf("could not decode newAddress data") } - return ðadapter.L1SetImportantContractsTx{ + return &common.L1SetImportantContractsTx{ Key: keyString, NewAddress: contractAddress, }, nil diff --git a/go/host/container/host_container.go b/go/host/container/host_container.go index f361e8ae28..ddf1d1a24e 100644 --- a/go/host/container/host_container.go +++ b/go/host/container/host_container.go @@ -145,13 +145,16 @@ func NewHostContainerFromConfig(cfg *hostconfig.HostConfig, logger gethlog.Logge }, logger) mgmtContractLib := mgmtcontractlib.NewMgmtContractLib(&cfg.ManagementContractAddress, logger) - obscuroRelevantContracts := []gethcommon.Address{cfg.ManagementContractAddress, cfg.MessageBusAddress} - l1Repo := l1.NewL1Repository(l1Client, obscuroRelevantContracts, logger) beaconClient := ethadapter.NewBeaconHTTPClient(new(http.Client), cfg.L1BeaconUrl) - beaconFallback := ethadapter.NewBeaconHTTPClient(new(http.Client), cfg.L1BlobArchiveUrl) // we can add more fallback clients as they become available + beaconFallback := ethadapter.NewBeaconHTTPClient(new(http.Client), cfg.L1BlobArchiveUrl) blobResolver := l1.NewBlobResolver(ethadapter.NewL1BeaconClient(beaconClient, beaconFallback)) - return NewHostContainer(cfg, services, aggP2P, l1Client, l1Repo, enclaveClients, mgmtContractLib, ethWallet, rpcServer, logger, metricsService, blobResolver) + contractAddresses := map[l1.ContractType][]gethcommon.Address{ + l1.MgmtContract: {cfg.ManagementContractAddress}, + l1.MsgBus: {cfg.MessageBusAddress}, + } + l1Data := l1.NewL1DataService(l1Client, logger, mgmtContractLib, blobResolver, contractAddresses) + return NewHostContainer(cfg, services, aggP2P, l1Client, l1Data, enclaveClients, mgmtContractLib, ethWallet, rpcServer, logger, metricsService, blobResolver) } // NewHostContainer builds a host container with dependency injection rather than from config. diff --git a/go/host/enclave/guardian.go b/go/host/enclave/guardian.go index 323ee2fc27..d5212ad009 100644 --- a/go/host/enclave/guardian.go +++ b/go/host/enclave/guardian.go @@ -46,7 +46,7 @@ const ( type guardianServiceLocator interface { P2P() host.P2P L1Publisher() host.L1Publisher - L1Repo() host.L1BlockRepository + L1Data() host.L1DataService L2Repo() host.L2BatchRepository LogSubs() host.LogSubscriptionManager Enclaves() host.EnclaveService @@ -142,7 +142,7 @@ func (g *Guardian) Start() error { txUnsub := g.sl.P2P().SubscribeForTx(g) // note: not keeping the unsubscribe functions because the lifespan of the guardian is the same as the host - l1Unsub := g.sl.L1Repo().Subscribe(g) + l1Unsub := g.sl.L1Data().Subscribe(g) batchesUnsub := g.sl.L2Repo().SubscribeNewBatches(g) g.cleanupFuncs = []func(){txUnsub, l1Unsub, batchesUnsub} @@ -351,11 +351,17 @@ func (g *Guardian) provideSecret() error { // keep checking L1 blocks until we find a secret response for our request or timeout err = retry.Do(func() error { - nextBlock, _, err := g.sl.L1Repo().FetchNextBlock(awaitFromBlock) + nextBlock, _, err := g.sl.L1Data().FetchNextBlock(awaitFromBlock) if err != nil { return fmt.Errorf("next block after block=%s not found - %w", awaitFromBlock, err) } - secretRespTxs := g.sl.L1Publisher().FindSecretResponseTx(nextBlock) + + processedData, err := g.sl.L1Data().GetTenRelevantTransactions(nextBlock) + if err != nil { + return fmt.Errorf("failed to extract Ten transactions from block=%s", nextBlock.Hash()) + } + secretResponseEvents := processedData.GetEvents(common.SecretResponseTx) + secretRespTxs := g.sl.L1Publisher().FindSecretResponseTx(secretResponseEvents) for _, scrt := range secretRespTxs { if scrt.RequesterID.Hex() == g.enclaveID.Hex() { err = g.enclaveClient.InitEnclave(context.Background(), scrt.Secret) @@ -415,7 +421,7 @@ func (g *Guardian) catchupWithL1() error { enclaveHead = g.l1StartHash } - l1Block, isLatest, err := g.sl.L1Repo().FetchNextBlock(enclaveHead) + l1Block, isLatest, err := g.sl.L1Data().FetchNextBlock(enclaveHead) if err != nil { if errors.Is(err, l1.ErrNoNextBlock) { if g.state.hostL1Head == gethutil.EmptyHash { @@ -465,14 +471,15 @@ func (g *Guardian) submitL1Block(block *common.L1Block, isLatest bool) (bool, er g.logger.Debug("Unable to submit block, enclave is busy processing data") return false, nil } - receipts, err := g.sl.L1Repo().FetchObscuroReceipts(block) + processedData, err := g.sl.L1Data().GetTenRelevantTransactions(block) if err != nil { g.submitDataLock.Unlock() // lock must be released before returning - return false, fmt.Errorf("could not fetch obscuro receipts for block=%s - %w", block.Hash(), err) + return false, fmt.Errorf("could not extract ten transaction for block=%s - %w", block.Hash(), err) } - txsReceiptsAndBlobs, rollupTxs, contractAddressTxs := g.sl.L1Publisher().ExtractRelevantTenTransactions(block, receipts) - resp, err := g.enclaveClient.SubmitL1Block(context.Background(), block.Header(), txsReceiptsAndBlobs) + rollupTxs, syncContracts := g.getRollupsAndContractAddrTxs(*processedData) + + resp, err := g.enclaveClient.SubmitL1Block(context.Background(), processedData) g.submitDataLock.Unlock() // lock is only guarding the enclave call, so we can release it now if err != nil { if strings.Contains(err.Error(), errutil.ErrBlockAlreadyProcessed.Error()) { @@ -481,7 +488,7 @@ func (g *Guardian) submitL1Block(block *common.L1Block, isLatest bool) (bool, er // note: logging this because we don't expect it to happen often and would like visibility on that. g.logger.Info("L1 block already processed by enclave, trying the next block", "block", block.Hash()) nextHeight := big.NewInt(0).Add(block.Number(), big.NewInt(1)) - nextCanonicalBlock, err := g.sl.L1Repo().FetchBlockByHeight(nextHeight) + nextCanonicalBlock, err := g.sl.L1Data().FetchBlockByHeight(nextHeight) if err != nil { return false, fmt.Errorf("failed to fetch next block after forking block=%s: %w", block.Hash(), err) } @@ -492,7 +499,7 @@ func (g *Guardian) submitL1Block(block *common.L1Block, isLatest bool) (bool, er } // successfully processed block, update the state g.state.OnProcessedBlock(block.Hash()) - g.processL1BlockTransactions(block, rollupTxs, contractAddressTxs) + g.processL1BlockTransactions(block, rollupTxs, syncContracts) if err != nil { return false, fmt.Errorf("submitted block to enclave but could not store the block processing result. Cause: %w", err) @@ -506,7 +513,7 @@ func (g *Guardian) submitL1Block(block *common.L1Block, isLatest bool) (bool, er return true, nil } -func (g *Guardian) processL1BlockTransactions(block *common.L1Block, rollupTxs []*ethadapter.L1RollupTx, contractAddressTxs []*ethadapter.L1SetImportantContractsTx) { +func (g *Guardian) processL1BlockTransactions(block *common.L1Block, rollupTxs []*common.L1RollupTx, syncContracts bool) { // TODO (@will) this should be removed and pulled from the L1 err := g.storage.AddBlock(block.Header()) if err != nil { @@ -534,7 +541,7 @@ func (g *Guardian) processL1BlockTransactions(block *common.L1Block, rollupTxs [ } } - if len(contractAddressTxs) > 0 { + if syncContracts { go func() { err := g.sl.L1Publisher().ResyncImportantContracts() if err != nil { @@ -654,8 +661,10 @@ func (g *Guardian) periodicRollupProduction() { // or the size of accumulated batches is > g.maxRollupSize timeExpired := time.Since(lastSuccessfulRollup) > g.rollupInterval sizeExceeded := estimatedRunningRollupSize >= g.maxRollupSize - if timeExpired || sizeExceeded { - g.logger.Info("Trigger rollup production.", "timeExpired", timeExpired, "sizeExceeded", sizeExceeded) + // if rollup retry takes longer than the block time then we need to allow time to publish + rollupJustPublished := time.Since(lastSuccessfulRollup) >= g.blockTime + if timeExpired || sizeExceeded && !rollupJustPublished { + g.logger.Info("Trigger rollup production.", "timeExpired", timeExpired, "sizeExceeded", sizeExceeded, "rollupJustPublished", rollupJustPublished) producedRollup, err := g.enclaveClient.CreateRollup(context.Background(), fromBatch) if err != nil { g.logger.Error("Unable to create rollup", log.BatchSeqNoKey, fromBatch, log.ErrKey, err) @@ -815,3 +824,28 @@ func (g *Guardian) evictEnclaveFromHAPool() { } go g.sl.Enclaves().EvictEnclave(g.enclaveID) } + +func (g *Guardian) getRollupsAndContractAddrTxs(processed common.ProcessedL1Data) ([]*common.L1RollupTx, bool) { + rollupTxs := make([]*common.L1RollupTx, 0) + var syncContracts bool + syncContracts = false + + for _, txData := range processed.GetEvents(common.RollupTx) { + encodedRlp, err := ethadapter.DecodeBlobs(txData.Blobs) + if err != nil { + g.logger.Crit("could not decode blobs.", log.ErrKey, err) + continue + } + + rlp := &common.L1RollupTx{ + Rollup: encodedRlp, + } + rollupTxs = append(rollupTxs, rlp) + } + + // if any contracts have been updated then we need to resync + if len(processed.GetEvents(common.SetImportantContractsTx)) > 0 { + syncContracts = true + } + return rollupTxs, syncContracts +} diff --git a/go/host/host.go b/go/host/host.go index 153aea2727..c444100575 100644 --- a/go/host/host.go +++ b/go/host/host.go @@ -99,7 +99,7 @@ func NewHost(config *hostconfig.HostConfig, hostServices *ServicesRegistry, p2p subsService := events.NewLogEventManager(hostServices, logger) l2Repo.SubscribeValidatedBatches(batchListener{newHeads: host.newHeads}) hostServices.RegisterService(hostcommon.P2PName, p2p) - hostServices.RegisterService(hostcommon.L1BlockRepositoryName, l1Repo) + hostServices.RegisterService(hostcommon.L1DataServiceName, l1Repo) maxWaitForL1Receipt := 6 * config.L1BlockTime // wait ~10 blocks to see if tx gets published before retrying retryIntervalForL1Receipt := config.L1BlockTime // retry ~every block l1Publisher := l1.NewL1Publisher( diff --git a/go/host/l1/blockrepository.go b/go/host/l1/blockrepository.go deleted file mode 100644 index fdae951245..0000000000 --- a/go/host/l1/blockrepository.go +++ /dev/null @@ -1,239 +0,0 @@ -package l1 - -import ( - "context" - "errors" - "fmt" - "math/big" - "sync/atomic" - "time" - - "github.com/ten-protocol/go-ten/go/common/subscription" - - "github.com/ten-protocol/go-ten/go/common/host" - - "github.com/ethereum/go-ethereum" - 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" - "github.com/ten-protocol/go-ten/go/common/retry" - "github.com/ten-protocol/go-ten/go/ethadapter" -) - -var ( - // todo (@matt) make this configurable? - _timeoutNoBlocks = 30 * time.Second - one = big.NewInt(1) - ErrNoNextBlock = errors.New("no next block") -) - -// Repository is a host service for subscribing to new blocks and looking up L1 data -type Repository struct { - blockSubscribers *subscription.Manager[host.L1BlockHandler] - // this eth client should only be used by the repository, the repository may "reconnect" it at any time and don't want to interfere with other processes - ethClient ethadapter.EthClient - logger gethlog.Logger - - running atomic.Bool - head gethcommon.Hash - obscuroRelevantContracts []gethcommon.Address -} - -func NewL1Repository(ethClient ethadapter.EthClient, obscuroRelevantContracts []gethcommon.Address, logger gethlog.Logger) *Repository { - return &Repository{ - blockSubscribers: subscription.NewManager[host.L1BlockHandler](), - ethClient: ethClient, - obscuroRelevantContracts: obscuroRelevantContracts, - running: atomic.Bool{}, - logger: logger, - } -} - -func (r *Repository) Start() error { - r.running.Store(true) - - // Repository constantly streams new blocks and forwards them to subscribers - go r.streamLiveBlocks() - return nil -} - -func (r *Repository) Stop() error { - r.running.Store(false) - return nil -} - -func (r *Repository) HealthStatus(context.Context) host.HealthStatus { - // todo (@matt) do proper health status based on last received block or something - errMsg := "" - if !r.running.Load() { - errMsg = "not running" - } - return &host.BasicErrHealthStatus{ErrMsg: errMsg} -} - -// Subscribe will register a new block handler to receive new blocks as they arrive, returns unsubscribe func -func (r *Repository) Subscribe(handler host.L1BlockHandler) func() { - return r.blockSubscribers.Subscribe(handler) -} - -// FetchNextBlock calculates the next canonical block that should be sent to requester after a given hash. -// It returns the block and a bool for whether it is the latest known head -func (r *Repository) FetchNextBlock(prevBlockHash gethcommon.Hash) (*types.Block, bool, error) { - if prevBlockHash == r.head { - // prevBlock is the latest known head - return nil, false, ErrNoNextBlock - } - - if prevBlockHash == (gethcommon.Hash{}) { - // prevBlock is empty, so we are starting from genesis - blk, err := r.ethClient.BlockByNumber(big.NewInt(0)) - if err != nil { - return nil, false, fmt.Errorf("could not find genesis block - %w", err) - } - return blk, false, nil - } - - // the latestCanonAncestor will usually return the prevBlock itself but this step is necessary to walk back if there was a fork - lca, err := r.latestCanonAncestor(prevBlockHash) - if err != nil { - return nil, false, err - } - // and send the canonical block at the height after that - // (which may be a fork, or it may just be the next on the same branch if we are catching-up) - blk, err := r.ethClient.BlockByNumber(increment(lca.Number())) - if err != nil { - if errors.Is(err, ethereum.NotFound) { - return nil, false, ErrNoNextBlock - } - return nil, false, fmt.Errorf("could not find block after latest canon ancestor, height=%s - %w", increment(lca.Number()), err) - } - - return blk, blk.Hash() == r.head, nil -} - -func (r *Repository) latestCanonAncestor(blkHash gethcommon.Hash) (*types.Block, error) { - blk, err := r.ethClient.BlockByHash(blkHash) - if err != nil { - return nil, fmt.Errorf("unable to fetch L1 block with hash=%s - %w", blkHash, err) - } - canonAtSameHeight, err := r.ethClient.BlockByNumber(blk.Number()) - if err != nil { - return nil, fmt.Errorf("unable to fetch L1 block at height=%d - %w", blk.Number(), err) - } - if blk.Hash() != canonAtSameHeight.Hash() { - return r.latestCanonAncestor(blk.ParentHash()) - } - return blk, nil -} - -// FetchObscuroReceipts returns all obscuro-relevant receipts for an L1 block -func (r *Repository) FetchObscuroReceipts(block *common.L1Block) (types.Receipts, error) { - receipts := make([]*types.Receipt, len(block.Transactions())) - if len(block.Transactions()) == 0 { - return receipts, nil - } - - blkHash := block.Hash() - // we want to send receipts for any transactions that produced obscuro-relevant log events - logs, err := r.ethClient.GetLogs(ethereum.FilterQuery{BlockHash: &blkHash, Addresses: r.obscuroRelevantContracts}) - if err != nil { - return nil, fmt.Errorf("unable to fetch logs for L1 block - %w", err) - } - // make a lookup map of the relevant tx hashes which need receipts - relevantTx := make(map[gethcommon.Hash]bool) - for _, l := range logs { - relevantTx[l.TxHash] = true - } - - for idx, transaction := range block.Transactions() { - if !relevantTx[transaction.Hash()] && !r.isObscuroTransaction(transaction) { - // put in a dummy receipt so that the index matches the transaction index - // (the receipts list maintains the indexes of the transactions, it is a sparse list) - receipts[idx] = &types.Receipt{Status: types.ReceiptStatusFailed} - continue - } - receipt, err := r.ethClient.TransactionReceipt(transaction.Hash()) - - if err != nil || receipt == nil { - r.logger.Error("Problem with retrieving the receipt on the host!", log.ErrKey, err, log.CmpKey, log.CrossChainCmp) - continue - } - - r.logger.Trace("Adding receipt", "status", receipt.Status, log.TxKey, transaction.Hash(), - log.BlockHashKey, blkHash, log.CmpKey, log.CrossChainCmp) - - receipts[idx] = receipt - } - - return receipts, nil -} - -// stream blocks from L1 as they arrive and forward them to subscribers, no guarantee of perfect ordering or that there won't be gaps. -// If streaming is interrupted it will carry on from latest, it won't try to replay missed blocks. -func (r *Repository) streamLiveBlocks() { - liveStream, streamSub := r.resetLiveStream() - for r.running.Load() { - select { - case header := <-liveStream: - r.head = header.Hash() - block, err := r.ethClient.BlockByHash(header.Hash()) - if err != nil { - r.logger.Error("Error fetching new block", log.BlockHashKey, header.Hash(), - log.BlockHeightKey, header.Number, log.ErrKey, err) - continue - } - for _, handler := range r.blockSubscribers.Subscribers() { - go handler.HandleBlock(block) - } - case <-time.After(_timeoutNoBlocks): - r.logger.Warn("no new blocks received since timeout", "timeout", _timeoutNoBlocks) - // reset stream to ensure it has not died - liveStream, streamSub = r.resetLiveStream() - } - } - - if streamSub != nil { - streamSub.Unsubscribe() - } -} - -func (r *Repository) resetLiveStream() (chan *types.Header, ethereum.Subscription) { - err := retry.Do(func() error { - if !r.running.Load() { - // break out of the loop if repository has stopped - return retry.FailFast(errors.New("repository is stopped")) - } - err := r.ethClient.ReconnectIfClosed() - if err != nil { - r.logger.Warn("failed to reconnect to L1", log.ErrKey, err) - return err - } - return nil - }, retry.NewBackoffAndRetryForeverStrategy([]time.Duration{100 * time.Millisecond, 1 * time.Second, 5 * time.Second}, 10*time.Second)) - if err != nil { - // this should only happen if repository has been stopped, because we retry reconnecting forever - r.logger.Warn("unable to reconnect to L1", log.ErrKey, err) - return nil, nil - } - return r.ethClient.BlockListener() -} - -func (r *Repository) FetchBlockByHeight(height *big.Int) (*types.Block, error) { - return r.ethClient.BlockByNumber(height) -} - -// isObscuroTransaction will look at the 'to' address of the transaction, we are only interested in management contract and bridge transactions -func (r *Repository) isObscuroTransaction(transaction *types.Transaction) bool { - for _, address := range r.obscuroRelevantContracts { - if transaction.To() != nil && *transaction.To() == address { - return true - } - } - return false -} - -func increment(i *big.Int) *big.Int { - return i.Add(i, one) -} diff --git a/go/host/l1/dataservice.go b/go/host/l1/dataservice.go new file mode 100644 index 0000000000..b0bc8d95cd --- /dev/null +++ b/go/host/l1/dataservice.go @@ -0,0 +1,346 @@ +package l1 + +import ( + "context" + "errors" + "fmt" + "math/big" + "sync/atomic" + "time" + + "github.com/ten-protocol/go-ten/go/enclave/crosschain" + "github.com/ten-protocol/go-ten/go/ethadapter/mgmtcontractlib" + + "github.com/ten-protocol/go-ten/go/common/subscription" + + "github.com/ten-protocol/go-ten/go/common/host" + + "github.com/ethereum/go-ethereum" + 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" + "github.com/ten-protocol/go-ten/go/common/retry" + "github.com/ten-protocol/go-ten/go/ethadapter" +) + +var ( + // todo (@matt) make this configurable? + _timeoutNoBlocks = 30 * time.Second + one = big.NewInt(1) + ErrNoNextBlock = errors.New("no next block") +) + +type ContractType int + +const ( + MgmtContract ContractType = iota + MsgBus +) + +// DataService is a host service for subscribing to new blocks and looking up L1 data +type DataService struct { + blockSubscribers *subscription.Manager[host.L1BlockHandler] + // this eth client should only be used by the repository, the repository may "reconnect" it at any time and don't want to interfere with other processes + ethClient ethadapter.EthClient + logger gethlog.Logger + mgmtContractLib mgmtcontractlib.MgmtContractLib + blobResolver BlobResolver + + running atomic.Bool + head gethcommon.Hash + contractAddresses map[ContractType][]gethcommon.Address +} + +func NewL1DataService( + ethClient ethadapter.EthClient, + logger gethlog.Logger, + mgmtContractLib mgmtcontractlib.MgmtContractLib, + blobResolver BlobResolver, + contractAddresses map[ContractType][]gethcommon.Address, +) *DataService { + return &DataService{ + blockSubscribers: subscription.NewManager[host.L1BlockHandler](), + ethClient: ethClient, + running: atomic.Bool{}, + logger: logger, + mgmtContractLib: mgmtContractLib, + blobResolver: blobResolver, + contractAddresses: contractAddresses, + } +} + +func (r *DataService) Start() error { + r.running.Store(true) + + // Repository constantly streams new blocks and forwards them to subscribers + go r.streamLiveBlocks() + return nil +} + +func (r *DataService) Stop() error { + r.running.Store(false) + return nil +} + +func (r *DataService) HealthStatus(context.Context) host.HealthStatus { + // todo (@matt) do proper health status based on last received block or something + errMsg := "" + if !r.running.Load() { + errMsg = "not running" + } + return &host.BasicErrHealthStatus{ErrMsg: errMsg} +} + +// Subscribe will register a new block handler to receive new blocks as they arrive, returns unsubscribe func +func (r *DataService) Subscribe(handler host.L1BlockHandler) func() { + return r.blockSubscribers.Subscribe(handler) +} + +// FetchNextBlock calculates the next canonical block that should be sent to requester after a given hash. +// It returns the block and a bool for whether it is the latest known head +func (r *DataService) FetchNextBlock(prevBlockHash gethcommon.Hash) (*types.Block, bool, error) { + if prevBlockHash == r.head { + // prevBlock is the latest known head + return nil, false, ErrNoNextBlock + } + + if prevBlockHash == (gethcommon.Hash{}) { + // prevBlock is empty, so we are starting from genesis + blk, err := r.ethClient.BlockByNumber(big.NewInt(0)) + if err != nil { + return nil, false, fmt.Errorf("could not find genesis block - %w", err) + } + return blk, false, nil + } + + // the latestCanonAncestor will usually return the prevBlock itself but this step is necessary to walk back if there was a fork + lca, err := r.latestCanonAncestor(prevBlockHash) + if err != nil { + return nil, false, err + } + // and send the canonical block at the height after that + // (which may be a fork, or it may just be the next on the same branch if we are catching-up) + blk, err := r.ethClient.BlockByNumber(increment(lca.Number())) + if err != nil { + if errors.Is(err, ethereum.NotFound) { + return nil, false, ErrNoNextBlock + } + return nil, false, fmt.Errorf("could not find block after latest canon ancestor, height=%s - %w", increment(lca.Number()), err) + } + + return blk, blk.Hash() == r.head, nil +} + +func (r *DataService) latestCanonAncestor(blkHash gethcommon.Hash) (*types.Block, error) { + blk, err := r.ethClient.BlockByHash(blkHash) + if err != nil { + return nil, fmt.Errorf("unable to fetch L1 block with hash=%s - %w", blkHash, err) + } + canonAtSameHeight, err := r.ethClient.BlockByNumber(blk.Number()) + if err != nil { + return nil, fmt.Errorf("unable to fetch L1 block at height=%d - %w", blk.Number(), err) + } + if blk.Hash() != canonAtSameHeight.Hash() { + return r.latestCanonAncestor(blk.ParentHash()) + } + return blk, nil +} + +// GetTenRelevantTransactions processes logs in their natural order without grouping by transaction hash. +func (r *DataService) GetTenRelevantTransactions(block *common.L1Block) (*common.ProcessedL1Data, error) { + processed := &common.ProcessedL1Data{ + BlockHeader: block.Header(), + Events: []common.L1Event{}, + } + + logs, err := r.fetchMessageBusMgmtContractLogs(block) + if err != nil { + return nil, err + } + + for _, l := range logs { + if len(l.Topics) == 0 { + r.logger.Warn("Log has no topics", "txHash", l.TxHash) + continue + } + + txData, err := r.fetchTxAndReceipt(l.TxHash) + if err != nil { + r.logger.Error("Error creating transaction data", "txHash", l.TxHash, "error", err) + continue + } + + // first topic is always the event signature + switch l.Topics[0] { + case crosschain.CrossChainEventID: + r.processCrossChainLogs(l, txData, processed) + case crosschain.ValueTransferEventID: + r.processValueTransferLogs(l, txData, processed) + case crosschain.SequencerEnclaveGrantedEventID: + r.processSequencerLogs(l, txData, processed, common.SequencerAddedTx) + r.processManagementContractTx(txData, processed) // we need to decode the InitialiseSecretTx + case crosschain.SequencerEnclaveRevokedEventID: + r.processSequencerLogs(l, txData, processed, common.SequencerRevokedTx) + case crosschain.ImportantContractAddressUpdatedID: + r.processManagementContractTx(txData, processed) + case crosschain.RollupAddedID: + r.processManagementContractTx(txData, processed) + case crosschain.NetworkSecretRequestedID: + processed.AddEvent(common.SecretRequestTx, txData) + case crosschain.NetworkSecretRespondedID: + processed.AddEvent(common.SecretResponseTx, txData) + default: + r.logger.Warn("Unknown log topic", "topic", l.Topics[0], "txHash", l.TxHash) + } + } + + return processed, nil +} + +// fetchMessageBusMgmtContractLogs retrieves all logs from management contract and message bus addresses +func (r *DataService) fetchMessageBusMgmtContractLogs(block *common.L1Block) ([]types.Log, error) { + blkHash := block.Hash() + var allAddresses []gethcommon.Address + allAddresses = append(allAddresses, r.contractAddresses[MgmtContract]...) + allAddresses = append(allAddresses, r.contractAddresses[MsgBus]...) + + logs, err := r.ethClient.GetLogs(ethereum.FilterQuery{BlockHash: &blkHash, Addresses: allAddresses}) + if err != nil { + return nil, fmt.Errorf("unable to fetch logs for L1 block - %w", err) + } + return logs, nil +} + +// fetchTxAndReceipt creates a new L1TxData instance for a transaction +func (r *DataService) fetchTxAndReceipt(txHash gethcommon.Hash) (*common.L1TxData, error) { + tx, _, err := r.ethClient.TransactionByHash(txHash) + if err != nil { + return nil, fmt.Errorf("error fetching transaction: %w", err) + } + + receipt, err := r.ethClient.TransactionReceipt(txHash) + if err != nil { + return nil, fmt.Errorf("error fetching receipt: %w", err) + } + + return &common.L1TxData{ + Transaction: tx, + Receipt: receipt, + CrossChainMessages: common.CrossChainMessages{}, + ValueTransfers: common.ValueTransferEvents{}, + }, nil +} + +// processCrossChainLogs handles cross-chain message logs +func (r *DataService) processCrossChainLogs(l types.Log, txData *common.L1TxData, processed *common.ProcessedL1Data) { + if messages, err := crosschain.ConvertLogsToMessages([]types.Log{l}, crosschain.CrossChainEventName, crosschain.MessageBusABI); err == nil { + txData.CrossChainMessages = messages + processed.AddEvent(common.CrossChainMessageTx, txData) + } +} + +// processValueTransferLogs handles value transfer logs +func (r *DataService) processValueTransferLogs(l types.Log, txData *common.L1TxData, processed *common.ProcessedL1Data) { + if transfers, err := crosschain.ConvertLogsToValueTransfers([]types.Log{l}, crosschain.ValueTransferEventName, crosschain.MessageBusABI); err == nil { + txData.ValueTransfers = transfers + processed.AddEvent(common.CrossChainValueTranserTx, txData) + } +} + +// processSequencerLogs handles sequencer logs +func (r *DataService) processSequencerLogs(l types.Log, txData *common.L1TxData, processed *common.ProcessedL1Data, txType common.L1TenEventType) { + if enclaveID, err := getEnclaveIdFromLog(l); err == nil { + txData.SequencerEnclaveID = enclaveID + processed.AddEvent(txType, txData) + } +} + +// processManagementContractTx handles decoded transaction types +func (r *DataService) processManagementContractTx(txData *common.L1TxData, processed *common.ProcessedL1Data) { + b := processed.BlockHeader + if decodedTx := r.mgmtContractLib.DecodeTx(txData.Transaction); decodedTx != nil { + switch t := decodedTx.(type) { + case *common.L1InitializeSecretTx: + processed.AddEvent(common.InitialiseSecretTx, txData) + case *common.L1SetImportantContractsTx: + processed.AddEvent(common.SetImportantContractsTx, txData) + case *common.L1RollupHashes: + if blobs, err := r.blobResolver.FetchBlobs(context.Background(), b, t.BlobHashes); err == nil { + txData.Blobs = blobs + processed.AddEvent(common.RollupTx, txData) + } + default: + // this should never happen since the specific events should always decode into one of these types + r.logger.Error("Unknown tx type", "txHash", txData.Transaction.Hash().Hex()) + } + } +} + +// stream blocks from L1 as they arrive and forward them to subscribers, no guarantee of perfect ordering or that there won't be gaps. +// If streaming is interrupted it will carry on from latest, it won't try to replay missed blocks. +func (r *DataService) streamLiveBlocks() { + liveStream, streamSub := r.resetLiveStream() + for r.running.Load() { + select { + case header := <-liveStream: + r.head = header.Hash() + block, err := r.ethClient.BlockByHash(header.Hash()) + if err != nil { + r.logger.Error("Error fetching new block", log.BlockHashKey, header.Hash(), + log.BlockHeightKey, header.Number, log.ErrKey, err) + continue + } + for _, handler := range r.blockSubscribers.Subscribers() { + go handler.HandleBlock(block) + } + case <-time.After(_timeoutNoBlocks): + r.logger.Warn("no new blocks received since timeout", "timeout", _timeoutNoBlocks) + // reset stream to ensure it has not died + liveStream, streamSub = r.resetLiveStream() + } + } + + if streamSub != nil { + streamSub.Unsubscribe() + } +} + +func (r *DataService) resetLiveStream() (chan *types.Header, ethereum.Subscription) { + err := retry.Do(func() error { + if !r.running.Load() { + // break out of the loop if repository has stopped + return retry.FailFast(errors.New("repository is stopped")) + } + err := r.ethClient.ReconnectIfClosed() + if err != nil { + r.logger.Warn("failed to reconnect to L1", log.ErrKey, err) + return err + } + return nil + }, retry.NewBackoffAndRetryForeverStrategy([]time.Duration{100 * time.Millisecond, 1 * time.Second, 5 * time.Second}, 10*time.Second)) + if err != nil { + // this should only happen if repository has been stopped, because we retry reconnecting forever + r.logger.Warn("unable to reconnect to L1", log.ErrKey, err) + return nil, nil + } + return r.ethClient.BlockListener() +} + +func (r *DataService) FetchBlockByHeight(height *big.Int) (*types.Block, error) { + return r.ethClient.BlockByNumber(height) +} + +// getEnclaveIdFromLog gets the enclave ID from the log topic +func getEnclaveIdFromLog(log types.Log) (gethcommon.Address, error) { + if len(log.Topics) != 1 { + return gethcommon.Address{}, fmt.Errorf("invalid number of topics in log: %d", len(log.Topics)) + } + + return gethcommon.BytesToAddress(log.Topics[0].Bytes()), nil +} + +func increment(i *big.Int) *big.Int { + return i.Add(i, one) +} diff --git a/go/host/l1/publisher.go b/go/host/l1/publisher.go index 5675deacaa..1af8e902b4 100644 --- a/go/host/l1/publisher.go +++ b/go/host/l1/publisher.go @@ -8,10 +8,6 @@ import ( "sync" "time" - "github.com/ethereum/go-ethereum/crypto/kzg4844" - - "github.com/ethereum/go-ethereum" - "github.com/ten-protocol/go-ten/contracts/generated/ManagementContract" "github.com/ten-protocol/go-ten/go/common/errutil" "github.com/ten-protocol/go-ten/go/common/stopcontrol" @@ -44,7 +40,7 @@ type Publisher struct { // lock for the important contract addresses map importantAddressesMutex sync.RWMutex - repository host.L1BlockRepository + repository host.L1DataService logger gethlog.Logger hostStopper *stopcontrol.StopControl @@ -64,7 +60,7 @@ func NewL1Publisher( hostWallet wallet.Wallet, client ethadapter.EthClient, mgmtContract mgmtcontractlib.MgmtContractLib, - repository host.L1BlockRepository, + repository host.L1DataService, blobResolver BlobResolver, hostStopper *stopcontrol.StopControl, logger gethlog.Logger, @@ -167,7 +163,7 @@ func (p *Publisher) InitializeSecret(attestation *common.AttestationReport, encS if err != nil { return errors.Wrap(err, "could not encode attestation") } - l1tx := ðadapter.L1InitializeSecretTx{ + l1tx := &common.L1InitializeSecretTx{ EnclaveID: &attestation.EnclaveID, Attestation: encodedAttestation, InitialSecret: encSecret, @@ -182,7 +178,7 @@ func (p *Publisher) RequestSecret(attestation *common.AttestationReport) (gethco if err != nil { return gethcommon.Hash{}, errors.Wrap(err, "could not encode attestation") } - l1tx := ðadapter.L1RequestSecretTx{ + l1tx := &common.L1RequestSecretTx{ Attestation: encodedAttestation, } // record the L1 head height before we submit the secret request, so we know which block to watch from @@ -208,7 +204,7 @@ func (p *Publisher) RequestSecret(attestation *common.AttestationReport) (gethco } func (p *Publisher) PublishSecretResponse(secretResponse *common.ProducedSecretResponse) error { - l1tx := ðadapter.L1RespondSecretTx{ + l1tx := &common.L1RespondSecretTx{ Secret: secretResponse.Secret, RequesterID: secretResponse.RequesterID, AttesterID: secretResponse.AttesterID, @@ -228,76 +224,16 @@ func (p *Publisher) PublishSecretResponse(secretResponse *common.ProducedSecretR return nil } -// ExtractRelevantTenTransactions will extract any transactions from the block that are relevant to TEN -// todo (#2495) we should monitor for relevant L1 events instead of scanning every transaction in the block -func (p *Publisher) ExtractRelevantTenTransactions(block *types.Block, receipts types.Receipts) ([]*common.TxAndReceiptAndBlobs, []*ethadapter.L1RollupTx, []*ethadapter.L1SetImportantContractsTx) { - // temporarily add this host stopping check to prevent sim test failures until a more robust solution is implemented - for !p.hostStopper.IsStopping() { - txWithReceiptsAndBlobs := make([]*common.TxAndReceiptAndBlobs, 0) - rollupTxs := make([]*ethadapter.L1RollupTx, 0) - contractAddressTxs := make([]*ethadapter.L1SetImportantContractsTx, 0) - - txs := block.Transactions() - for i, rec := range receipts { - if rec.BlockNumber == nil { - continue // Skip non-relevant transactions - } - - decodedTx := p.mgmtContractLib.DecodeTx(txs[i]) - var blobs []*kzg4844.Blob - var err error - - switch typedTx := decodedTx.(type) { - case *ethadapter.L1SetImportantContractsTx: - contractAddressTxs = append(contractAddressTxs, typedTx) - case *ethadapter.L1RollupHashes: - blobs, err = p.blobResolver.FetchBlobs(p.sendingContext, block.Header(), typedTx.BlobHashes) - // temporarily add this host stopping check to prevent sim test failures until a more robust solution is implemented - if err != nil { - if errors.Is(err, ethereum.NotFound) { - p.logger.Crit("Blobs were not found on beacon chain or archive service", "block", block.Hash(), "error", err) - } else { - p.logger.Crit("could not fetch blobs", log.ErrKey, err) - } - continue - } - - encodedRlp, err := ethadapter.DecodeBlobs(blobs) - if err != nil { - p.logger.Crit("could not decode blobs.", log.ErrKey, err) - continue - } - - rlp := ðadapter.L1RollupTx{ - Rollup: encodedRlp, - } - rollupTxs = append(rollupTxs, rlp) - } - - // compile the tx, receipt and blobs into a single struct for submission to the enclave - txWithReceiptsAndBlobs = append(txWithReceiptsAndBlobs, &common.TxAndReceiptAndBlobs{ - Tx: txs[i], - Receipt: rec, - Blobs: blobs, - }) - } - - return txWithReceiptsAndBlobs, rollupTxs, contractAddressTxs - } - return nil, nil, nil -} - -// FindSecretResponseTx will scan the block for any secret response transactions. This is separate from the above method -// as we do not require the receipts for these transactions. -func (p *Publisher) FindSecretResponseTx(block *types.Block) []*ethadapter.L1RespondSecretTx { - secretRespTxs := make([]*ethadapter.L1RespondSecretTx, 0) +// FindSecretResponseTx will attempt to decode the transactions passed in +func (p *Publisher) FindSecretResponseTx(processed []*common.L1TxData) []*common.L1RespondSecretTx { + secretRespTxs := make([]*common.L1RespondSecretTx, 0) - for _, tx := range block.Transactions() { - t := p.mgmtContractLib.DecodeTx(tx) + for _, tx := range processed { + t := p.mgmtContractLib.DecodeTx(tx.Transaction) if t == nil { continue } - if scrtTx, ok := t.(*ethadapter.L1RespondSecretTx); ok { + if scrtTx, ok := t.(*common.L1RespondSecretTx); ok { secretRespTxs = append(secretRespTxs, scrtTx) continue } @@ -314,7 +250,7 @@ func (p *Publisher) PublishRollup(producedRollup *common.ExtRollup) { if err != nil { p.logger.Crit("could not encode rollup.", log.ErrKey, err) } - tx := ðadapter.L1RollupTx{ + tx := &common.L1RollupTx{ Rollup: encRollup, } p.logger.Info("Publishing rollup", "size", len(encRollup)/1024, log.RollupHashKey, producedRollup.Hash()) diff --git a/go/host/rpc/enclaverpc/enclave_client.go b/go/host/rpc/enclaverpc/enclave_client.go index 67fc38dd76..0bb0c6c0bf 100644 --- a/go/host/rpc/enclaverpc/enclave_client.go +++ b/go/host/rpc/enclaverpc/enclave_client.go @@ -212,18 +212,18 @@ func (c *Client) RPCEncryptionKey(ctx context.Context) ([]byte, common.SystemErr return response.RpcPubKey, nil } -func (c *Client) SubmitL1Block(ctx context.Context, blockHeader *types.Header, txsReceiptsAndBlobs []*common.TxAndReceiptAndBlobs) (*common.BlockSubmissionResponse, common.SystemError) { +func (c *Client) SubmitL1Block(ctx context.Context, processed *common.ProcessedL1Data) (*common.BlockSubmissionResponse, common.SystemError) { var buffer bytes.Buffer - if err := blockHeader.EncodeRLP(&buffer); err != nil { + if err := processed.BlockHeader.EncodeRLP(&buffer); err != nil { return nil, fmt.Errorf("could not encode block. Cause: %w", err) } - serializedTxsReceiptsAndBlobs, err := rlp.EncodeToBytes(txsReceiptsAndBlobs) + serializedProcessedData, err := rlp.EncodeToBytes(processed) if err != nil { return nil, fmt.Errorf("could not encode receipts. Cause: %w", err) } - response, err := c.protoClient.SubmitL1Block(ctx, &generated.SubmitBlockRequest{EncodedBlock: buffer.Bytes(), EncodedReceipts: serializedTxsReceiptsAndBlobs}) + response, err := c.protoClient.SubmitL1Block(ctx, &generated.SubmitBlockRequest{EncodedBlock: buffer.Bytes(), EncodedProcessedData: serializedProcessedData}) if err != nil { return nil, fmt.Errorf("could not submit block. Cause: %w", err) } diff --git a/go/host/servicelocator.go b/go/host/servicelocator.go index a5067617c8..3e15656717 100644 --- a/go/host/servicelocator.go +++ b/go/host/servicelocator.go @@ -41,8 +41,8 @@ func (s *ServicesRegistry) P2P() hostcommon.P2P { return s.getService(hostcommon.P2PName).(hostcommon.P2P) } -func (s *ServicesRegistry) L1Repo() hostcommon.L1BlockRepository { - return s.getService(hostcommon.L1BlockRepositoryName).(hostcommon.L1BlockRepository) +func (s *ServicesRegistry) L1Data() hostcommon.L1DataService { + return s.getService(hostcommon.L1DataServiceName).(hostcommon.L1DataService) } func (s *ServicesRegistry) L1Publisher() hostcommon.L1Publisher { diff --git a/integration/ethereummock/erc20_contract_lib.go b/integration/ethereummock/erc20_contract_lib.go index e9b0117c86..cf40f6db00 100644 --- a/integration/ethereummock/erc20_contract_lib.go +++ b/integration/ethereummock/erc20_contract_lib.go @@ -3,29 +3,29 @@ package ethereummock import ( "bytes" - "github.com/ethereum/go-ethereum/common" + gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ten-protocol/go-ten/go/ethadapter" + "github.com/ten-protocol/go-ten/go/common" "github.com/ten-protocol/go-ten/go/ethadapter/erc20contractlib" ) type contractLib struct{} -func (c *contractLib) CreateDepositTx(tx *ethadapter.L1DepositTx) types.TxData { +func (c *contractLib) CreateDepositTx(tx *common.L1DepositTx) types.TxData { return encodeTx(tx, depositTxAddr) } -// Return only deposit transactions to the management contract -func (c *contractLib) DecodeTx(tx *types.Transaction) ethadapter.L1Transaction { +// DecodeTx returns only deposit transactions to the management contract +func (c *contractLib) DecodeTx(tx *types.Transaction) common.L1TenTransaction { if bytes.Equal(tx.To().Bytes(), depositTxAddr.Bytes()) { - depositTx, ok := decodeTx(tx).(*ethadapter.L1DepositTx) + depositTx, ok := decodeTx(tx).(*common.L1DepositTx) if !ok { return nil } // Mock deposits towards the L1 bridge target nil as the management contract address // is not set. - if bytes.Equal(depositTx.To.Bytes(), common.BigToAddress(common.Big0).Bytes()) { + if bytes.Equal(depositTx.To.Bytes(), gethcommon.BigToAddress(gethcommon.Big0).Bytes()) { return depositTx } } diff --git a/integration/ethereummock/mgmt_contract_lib.go b/integration/ethereummock/mgmt_contract_lib.go index 500a40a889..fc32a9b898 100644 --- a/integration/ethereummock/mgmt_contract_lib.go +++ b/integration/ethereummock/mgmt_contract_lib.go @@ -5,6 +5,10 @@ import ( "encoding/gob" "fmt" + "github.com/ten-protocol/go-ten/go/common" + + "github.com/ten-protocol/go-ten/go/host/l1" + "github.com/ten-protocol/go-ten/go/ethadapter" "github.com/ten-protocol/go-ten/integration/datagenerator" @@ -22,13 +26,19 @@ var ( storeSecretTxAddr = datagenerator.RandomAddress() requestSecretTxAddr = datagenerator.RandomAddress() initializeSecretTxAddr = datagenerator.RandomAddress() - // MgmtContractAddresses make all these addresses available for the host to know what receipts will be forwarded to the enclave - MgmtContractAddresses = []gethcommon.Address{ - depositTxAddr, - rollupTxAddr, - storeSecretTxAddr, - requestSecretTxAddr, - initializeSecretTxAddr, + messageBusAddr = datagenerator.RandomAddress() + // ContractAddresses maps contract types to their addresses + ContractAddresses = map[l1.ContractType][]gethcommon.Address{ + l1.MgmtContract: { + depositTxAddr, + rollupTxAddr, + storeSecretTxAddr, + requestSecretTxAddr, + initializeSecretTxAddr, + }, + l1.MsgBus: { + messageBusAddr, + }, } ) @@ -49,7 +59,7 @@ func (m *mockContractLib) GetContractAddr() *gethcommon.Address { return &rollupTxAddr } -func (m *mockContractLib) DecodeTx(tx *types.Transaction) ethadapter.L1Transaction { +func (m *mockContractLib) DecodeTx(tx *types.Transaction) common.L1TenTransaction { // Do not decode erc20 transactions, this is the responsibility // of the erc20 contract lib. if tx.To().Hex() == depositTxAddr.Hex() { @@ -57,14 +67,14 @@ func (m *mockContractLib) DecodeTx(tx *types.Transaction) ethadapter.L1Transacti } if tx.To().Hex() == rollupTxAddr.Hex() { - return ðadapter.L1RollupHashes{ + return &common.L1RollupHashes{ BlobHashes: tx.BlobHashes(), } } return decodeTx(tx) } -func (m *mockContractLib) CreateBlobRollup(t *ethadapter.L1RollupTx) (types.TxData, error) { +func (m *mockContractLib) CreateBlobRollup(t *common.L1RollupTx) (types.TxData, error) { var err error blobs, err := ethadapter.EncodeBlobs(t.Rollup) if err != nil { @@ -77,7 +87,7 @@ func (m *mockContractLib) CreateBlobRollup(t *ethadapter.L1RollupTx) (types.TxDa return nil, fmt.Errorf("failed to make sidecar: %w", err) } - hashesTx := ethadapter.L1RollupHashes{BlobHashes: blobHashes} + hashesTx := common.L1RollupHashes{BlobHashes: blobHashes} var buf bytes.Buffer enc := gob.NewEncoder(&buf) @@ -94,15 +104,15 @@ func (m *mockContractLib) CreateBlobRollup(t *ethadapter.L1RollupTx) (types.TxDa }, nil } -func (m *mockContractLib) CreateRequestSecret(tx *ethadapter.L1RequestSecretTx) types.TxData { +func (m *mockContractLib) CreateRequestSecret(tx *common.L1RequestSecretTx) types.TxData { return encodeTx(tx, requestSecretTxAddr) } -func (m *mockContractLib) CreateRespondSecret(tx *ethadapter.L1RespondSecretTx, _ bool) types.TxData { +func (m *mockContractLib) CreateRespondSecret(tx *common.L1RespondSecretTx, _ bool) types.TxData { return encodeTx(tx, storeSecretTxAddr) } -func (m *mockContractLib) CreateInitializeSecret(tx *ethadapter.L1InitializeSecretTx) types.TxData { +func (m *mockContractLib) CreateInitializeSecret(tx *common.L1InitializeSecretTx) types.TxData { return encodeTx(tx, initializeSecretTxAddr) } @@ -134,7 +144,7 @@ func (m *mockContractLib) DecodeImportantAddressResponse([]byte) (gethcommon.Add return gethcommon.Address{}, nil } -func decodeTx(tx *types.Transaction) ethadapter.L1Transaction { +func decodeTx(tx *types.Transaction) common.L1TenTransaction { if len(tx.Data()) == 0 { panic("Data cannot be 0 in the mock implementation") } @@ -146,16 +156,16 @@ func decodeTx(tx *types.Transaction) ethadapter.L1Transaction { // in the mock implementation we use the To address field to specify the L1 operation (rollup/storesecret/requestsecret) // the mock implementation does not process contracts // so this is a way that we can differentiate different contract calls - var t ethadapter.L1Transaction + var t common.L1TenTransaction switch tx.To().Hex() { case storeSecretTxAddr.Hex(): - t = ðadapter.L1RespondSecretTx{} + t = &common.L1RespondSecretTx{} case depositTxAddr.Hex(): - t = ðadapter.L1DepositTx{} + t = &common.L1DepositTx{} case requestSecretTxAddr.Hex(): - t = ðadapter.L1RequestSecretTx{} + t = &common.L1RequestSecretTx{} case initializeSecretTxAddr.Hex(): - t = ðadapter.L1InitializeSecretTx{} + t = &common.L1InitializeSecretTx{} default: panic("unexpected type") } @@ -168,7 +178,7 @@ func decodeTx(tx *types.Transaction) ethadapter.L1Transaction { return t } -func encodeTx(tx ethadapter.L1Transaction, opType gethcommon.Address) types.TxData { +func encodeTx(tx common.L1TenTransaction, opType gethcommon.Address) types.TxData { var buf bytes.Buffer enc := gob.NewEncoder(&buf) diff --git a/integration/ethereummock/mock_l1_network.go b/integration/ethereummock/mock_l1_network.go index 9829ea92f7..5c35d2fc14 100644 --- a/integration/ethereummock/mock_l1_network.go +++ b/integration/ethereummock/mock_l1_network.go @@ -15,8 +15,6 @@ import ( testcommon "github.com/ten-protocol/go-ten/integration/common" - "github.com/ten-protocol/go-ten/go/ethadapter" - "github.com/ten-protocol/go-ten/go/common" "github.com/ethereum/go-ethereum/core/types" @@ -92,14 +90,14 @@ func printBlock(b *types.Block, m *Node) string { } switch l1Tx := t.(type) { - case *ethadapter.L1RollupTx: + case *common.L1RollupTx: r, err := common.DecodeRollup(l1Tx.Rollup) if err != nil { testlog.Logger().Crit("failed to decode rollup") } txs = append(txs, fmt.Sprintf("r_%d(nonce=%d)", common.ShortHash(r.Hash()), tx.Nonce())) - case *ethadapter.L1DepositTx: + case *common.L1DepositTx: var to uint64 if l1Tx.To != nil { to = common.ShortAddress(*l1Tx.To) diff --git a/integration/ethereummock/node.go b/integration/ethereummock/node.go index e01b412b30..31b483c7e5 100644 --- a/integration/ethereummock/node.go +++ b/integration/ethereummock/node.go @@ -30,6 +30,7 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/core/types" ethclient_ethereum "github.com/ethereum/go-ethereum/ethclient" + "github.com/ten-protocol/go-ten/go/enclave/crosschain" "github.com/ten-protocol/go-ten/go/ethadapter" "github.com/ten-protocol/go-ten/go/ethadapter/erc20contractlib" "github.com/ten-protocol/go-ten/go/ethadapter/mgmtcontractlib" @@ -145,6 +146,52 @@ func (m *Node) TransactionReceipt(_ gethcommon.Hash) (*types.Receipt, error) { }, nil } +func (m *Node) TransactionByHash(hash gethcommon.Hash) (*types.Transaction, bool, error) { + // First check mempool/pending transactions + select { + case tx := <-m.mempoolCh: + if tx.Hash() == hash { + // Put the tx back in the channel + m.mempoolCh <- tx + return tx, false, nil + } + // Put the tx back in the channel + m.mempoolCh <- tx + default: + // Don't block if mempool channel is empty + } + + // Then check if the transaction exists in any block + blk, err := m.BlockResolver.FetchHeadBlock(context.Background()) + if err != nil { + return nil, false, fmt.Errorf("could not retrieve head block. Cause: %w", err) + } + + // Traverse the chain looking for the transaction + for !bytes.Equal(blk.ParentHash().Bytes(), (common.L1BlockHash{}).Bytes()) { + for _, tx := range blk.Transactions() { + if tx.Hash() == hash { + return tx, true, nil + } + } + + blk, err = m.BlockResolver.FetchBlock(context.Background(), blk.ParentHash()) + if err != nil { + return nil, false, fmt.Errorf("could not retrieve parent block. Cause: %w", err) + } + } + + // Check genesis block + for _, tx := range MockGenesisBlock.Transactions() { + if tx.Hash() == hash { + return tx, true, nil + } + } + + // If we get here, the transaction wasn't found + return nil, false, ethereum.NotFound +} + func (m *Node) Nonce(gethcommon.Address) (uint64, error) { return 0, nil } @@ -156,7 +203,7 @@ func (m *Node) getRollupFromBlock(block *types.Block) *common.ExtRollup { continue } switch l1tx := decodedTx.(type) { - case *ethadapter.L1RollupHashes: + case *common.L1RollupHashes: ctx := context.TODO() blobs, _ := m.BlobResolver.FetchBlobs(ctx, block.Header(), l1tx.BlobHashes) r, err := ethadapter.ReconstructRollup(blobs) @@ -271,21 +318,49 @@ func (m *Node) BalanceAt(gethcommon.Address, *big.Int) (*big.Int, error) { panic("not implemented") } -// GetLogs is a mock method - we don't really have logs on the mock transactions, so it returns a basic log for every tx -// so the host recognises them as relevant +// GetLogs is a mock method - we create logs with topics matching the real contract events func (m *Node) GetLogs(fq ethereum.FilterQuery) ([]types.Log, error) { logs := make([]types.Log, 0) if fq.BlockHash == nil { return logs, nil } + blk, err := m.BlockByHash(*fq.BlockHash) if err != nil { return nil, fmt.Errorf("could not retrieve block. Cause: %w", err) } + for _, tx := range blk.Transactions() { + if tx.To() == nil { + continue + } + + // map transaction types to their corresponding event topics + var topic gethcommon.Hash + switch tx.To().Hex() { + case rollupTxAddr.Hex(): + topic = crosschain.RollupAddedID + case messageBusAddr.Hex(): + topic = crosschain.CrossChainEventID + case depositTxAddr.Hex(): + topic = crosschain.ValueTransferEventID + case storeSecretTxAddr.Hex(): + topic = crosschain.NetworkSecretRespondedID + case requestSecretTxAddr.Hex(): + topic = crosschain.NetworkSecretRequestedID + case initializeSecretTxAddr.Hex(): + topic = crosschain.SequencerEnclaveGrantedEventID + default: + continue + } + dummyLog := types.Log{ - BlockHash: blk.Hash(), - TxHash: tx.Hash(), + Address: *tx.To(), + BlockHash: blk.Hash(), + TxHash: tx.Hash(), + Topics: []gethcommon.Hash{topic}, + BlockNumber: blk.NumberU64(), + Index: uint(len(logs)), } logs = append(logs, dummyLog) } diff --git a/integration/simulation/devnetwork/node.go b/integration/simulation/devnetwork/node.go index d3be72c194..11a01adb22 100644 --- a/integration/simulation/devnetwork/node.go +++ b/integration/simulation/devnetwork/node.go @@ -180,9 +180,13 @@ func (n *InMemNodeOperator) createHostContainer() *hostcontainer.HostContainer { } rpcServer := node.NewServer(&rpcConfig, n.logger) mgmtContractLib := mgmtcontractlib.NewMgmtContractLib(&hostConfig.ManagementContractAddress, n.logger) - l1Repo := l1.NewL1Repository(n.l1Client, []gethcommon.Address{hostConfig.ManagementContractAddress, hostConfig.MessageBusAddress}, n.logger) + contractAddresses := map[l1.ContractType][]gethcommon.Address{ + l1.MgmtContract: {hostConfig.ManagementContractAddress}, + l1.MsgBus: {hostConfig.MessageBusAddress}, + } blobResolver := l1.NewBlobResolver(ethadapter.NewL1BeaconClient(ethadapter.NewBeaconHTTPClient(new(http.Client), fmt.Sprintf("127.0.0.1:%d", n.config.L1BeaconPort)))) - return hostcontainer.NewHostContainer(hostConfig, svcLocator, nodeP2p, n.l1Client, l1Repo, enclaveClients, mgmtContractLib, n.l1Wallet, rpcServer, hostLogger, metrics.New(false, 0, n.logger), blobResolver) + l1Data := l1.NewL1DataService(n.l1Client, n.logger, mgmtContractLib, blobResolver, contractAddresses) + return hostcontainer.NewHostContainer(hostConfig, svcLocator, nodeP2p, n.l1Client, l1Data, enclaveClients, mgmtContractLib, n.l1Wallet, rpcServer, hostLogger, metrics.New(false, 0, n.logger), blobResolver) } func (n *InMemNodeOperator) createEnclaveContainer(idx int) *enclavecontainer.EnclaveContainer { diff --git a/integration/simulation/network/network_utils.go b/integration/simulation/network/network_utils.go index 72dab7bdf7..2c528cec62 100644 --- a/integration/simulation/network/network_utils.go +++ b/integration/simulation/network/network_utils.go @@ -112,8 +112,8 @@ func createInMemTenNode( // create an in memory TEN node hostLogger := testlog.Logger().New(log.NodeIDKey, id, log.CmpKey, log.HostCmp) metricsService := metrics.New(hostConfig.MetricsEnabled, hostConfig.MetricsHTTPPort, hostLogger) - l1Repo := l1.NewL1Repository(ethClient, ethereummock.MgmtContractAddresses, hostLogger) - currentContainer := hostcontainer.NewHostContainer(hostConfig, host.NewServicesRegistry(hostLogger), mockP2P, ethClient, l1Repo, enclaveClients, mgmtContractLib, ethWallet, nil, hostLogger, metricsService, blobResolver) + l1Data := l1.NewL1DataService(ethClient, hostLogger, mgmtContractLib, blobResolver, ethereummock.ContractAddresses) + currentContainer := hostcontainer.NewHostContainer(hostConfig, host.NewServicesRegistry(hostLogger), mockP2P, ethClient, l1Data, enclaveClients, mgmtContractLib, ethWallet, nil, hostLogger, metricsService, blobResolver) return currentContainer } diff --git a/integration/simulation/output_stats.go b/integration/simulation/output_stats.go index 27f652cec2..441388f89e 100644 --- a/integration/simulation/output_stats.go +++ b/integration/simulation/output_stats.go @@ -97,7 +97,7 @@ func (o *OutputStats) incrementStats(block *types.Block, _ ethadapter.EthClient) } switch l1Tx := t.(type) { - case *ethadapter.L1RollupTx: + case *common.L1RollupTx: _, err := common.DecodeRollup(l1Tx.Rollup) if err != nil { testlog.Logger().Crit("could not decode rollup.", log.ErrKey, err) @@ -109,7 +109,7 @@ func (o *OutputStats) incrementStats(block *types.Block, _ ethadapter.EthClient) // } //} - case *ethadapter.L1DepositTx: + case *common.L1DepositTx: o.canonicalERC20DepositCount++ } } diff --git a/integration/simulation/simulation.go b/integration/simulation/simulation.go index bd1982aeaf..4ce3f4c32e 100644 --- a/integration/simulation/simulation.go +++ b/integration/simulation/simulation.go @@ -21,7 +21,6 @@ import ( "github.com/ten-protocol/go-ten/go/common/errutil" "github.com/ten-protocol/go-ten/go/common/log" "github.com/ten-protocol/go-ten/go/common/retry" - "github.com/ten-protocol/go-ten/go/ethadapter" "github.com/ten-protocol/go-ten/go/wallet" "github.com/ten-protocol/go-ten/integration/common/testlog" "github.com/ten-protocol/go-ten/integration/erc20contract" @@ -139,7 +138,7 @@ func (s *Simulation) waitForTenGenesisOnL1() { if t == nil { continue } - if _, ok := t.(*ethadapter.L1RollupHashes); ok { + if _, ok := t.(*common.L1RollupHashes); ok { // exit at the first TEN rollup we see return } @@ -324,15 +323,19 @@ func (s *Simulation) deployTenZen() { time.Sleep(2 * time.Second) } - for { + // Wait for balance with retry + err = retry.Do(func() error { balance, err := rpcClient.BalanceAt(context.Background(), nil) if err != nil { - panic(fmt.Errorf("failed to get balance: %w", err)) + return fmt.Errorf("failed to get balance: %w", err) } - if balance.Cmp(big.NewInt(0)) > 0 { - break + if balance.Cmp(big.NewInt(0)) <= 0 { + return fmt.Errorf("waiting for positive balance") } - time.Sleep(2 * time.Second) + return nil + }, retry.NewTimeoutStrategy(1*time.Minute, 2*time.Second)) + if err != nil { + panic(fmt.Errorf("failed to get positive balance after timeout: %w", err)) } owner := s.Params.Wallets.L2FaucetWallet @@ -404,7 +407,7 @@ func (s *Simulation) deployTenERC20s() { rpc := s.RPCHandles.TenWalletClient(owner.Address(), 1) err = rpc.SendTransaction(s.ctx, signedTx) if err != nil { - panic(err) + panic(fmt.Sprintf("ERC20 deployment transaction unsuccessful. Cause: %s", err)) } err = testcommon.AwaitReceipt(s.ctx, rpc, signedTx.Hash(), s.Params.ReceiptTimeout) @@ -425,7 +428,7 @@ func (s *Simulation) prefundL1Accounts() { receiver := w.Address() tokenOwner := s.Params.Wallets.Tokens[testcommon.HOC].L1Owner ownerAddr := tokenOwner.Address() - txData := ðadapter.L1DepositTx{ + txData := &common.L1DepositTx{ Amount: initialBalance, To: &receiver, TokenContract: s.Params.Wallets.Tokens[testcommon.HOC].L1ContractAddress, diff --git a/integration/simulation/simulation_full_network_test.go b/integration/simulation/simulation_full_network_test.go index a25cf0d3d6..2323bf2bbc 100644 --- a/integration/simulation/simulation_full_network_test.go +++ b/integration/simulation/simulation_full_network_test.go @@ -29,7 +29,7 @@ func TestFullNetworkMonteCarloSimulation(t *testing.T) { L1EfficiencyThreshold: 0.2, Wallets: wallets, StartPort: integration.TestPorts.TestFullNetworkMonteCarloSimulationPort, - ReceiptTimeout: 20 * time.Second, + ReceiptTimeout: 45 * time.Second, StoppingDelay: 15 * time.Second, NodeWithInboundP2PDisabled: 2, L1BeaconPort: integration.TestPorts.TestFullNetworkMonteCarloSimulationPort + integration.DefaultPrysmGatewayPortOffset, diff --git a/integration/simulation/transaction_injector_tracker.go b/integration/simulation/transaction_injector_tracker.go index e6b678fc65..a89fd9fd40 100644 --- a/integration/simulation/transaction_injector_tracker.go +++ b/integration/simulation/transaction_injector_tracker.go @@ -4,7 +4,6 @@ import ( "sync" "github.com/ethereum/go-ethereum/core/types" - "github.com/ten-protocol/go-ten/go/ethadapter" "github.com/ten-protocol/go-ten/go/wallet" "github.com/ten-protocol/go-ten/go/common" @@ -13,7 +12,7 @@ import ( type txInjectorTracker struct { gasTransactionsLock sync.RWMutex l1TransactionsLock sync.RWMutex - L1Transactions []ethadapter.L1Transaction + L1Transactions []common.L1TenTransaction l2TransactionsLock sync.RWMutex TransferL2Transactions []*common.L2Tx NativeValueTransferL2Transactions []*common.L2Tx @@ -29,7 +28,7 @@ type GasBridgingRecord struct { func newCounter() *txInjectorTracker { return &txInjectorTracker{ l1TransactionsLock: sync.RWMutex{}, - L1Transactions: []ethadapter.L1Transaction{}, + L1Transactions: []common.L1TenTransaction{}, l2TransactionsLock: sync.RWMutex{}, TransferL2Transactions: []*common.L2Tx{}, WithdrawalL2Transactions: []*common.L2Tx{}, @@ -48,7 +47,7 @@ func (m *txInjectorTracker) trackGasBridgingTx(tx *types.Transaction, receiverWa } // trackL1Tx adds an L1Tx to the internal list -func (m *txInjectorTracker) trackL1Tx(tx ethadapter.L1Transaction) { +func (m *txInjectorTracker) trackL1Tx(tx common.L1TenTransaction) { m.l1TransactionsLock.Lock() defer m.l1TransactionsLock.Unlock() m.L1Transactions = append(m.L1Transactions, tx) @@ -73,7 +72,7 @@ func (m *txInjectorTracker) trackNativeValueTransferL2Tx(tx *common.L2Tx) { } // GetL1Transactions returns all generated L1 L2Txs -func (m *txInjectorTracker) GetL1Transactions() []ethadapter.L1Transaction { +func (m *txInjectorTracker) GetL1Transactions() []common.L1TenTransaction { return m.L1Transactions } diff --git a/integration/simulation/validate_chain.go b/integration/simulation/validate_chain.go index 1fded15ca0..8976972105 100644 --- a/integration/simulation/validate_chain.go +++ b/integration/simulation/validate_chain.go @@ -280,12 +280,12 @@ func ExtractDataFromEthereumChain( } switch l1tx := t.(type) { - case *ethadapter.L1DepositTx: + case *common.L1DepositTx: // todo (@stefan) - remove this hack once the old integrated bridge is removed. deposits = append(deposits, tx.Hash()) totalDeposited.Add(totalDeposited, l1tx.Amount) successfulDeposits++ - case *ethadapter.L1RollupHashes: + case *common.L1RollupHashes: r, err := getRollupFromBlobHashes(s.ctx, s.Params.BlobResolver, block, l1tx.BlobHashes) if err != nil { testlog.Logger().Crit("could not decode rollup. ", log.ErrKey, err) @@ -453,7 +453,7 @@ func checkBlockchainOfTenNode(t *testing.T, rpcHandles *network.RPCHandles, minT injectorDepositedAmt := big.NewInt(0) for _, tx := range s.TxInjector.TxTracker.GetL1Transactions() { - if depTx, ok := tx.(*ethadapter.L1DepositTx); ok { + if depTx, ok := tx.(*common.L1DepositTx); ok { injectorDepositedAmt.Add(injectorDepositedAmt, depTx.Amount) } } diff --git a/integration/smartcontract/debug_mgmt_contract_lib.go b/integration/smartcontract/debug_mgmt_contract_lib.go index cf7d29b7ec..3cf78c6816 100644 --- a/integration/smartcontract/debug_mgmt_contract_lib.go +++ b/integration/smartcontract/debug_mgmt_contract_lib.go @@ -41,7 +41,7 @@ func (d *debugMgmtContractLib) AwaitedIssueRollup(rollup common.ExtRollup, clien if err != nil { return err } - txData, err := d.CreateBlobRollup(ðadapter.L1RollupTx{Rollup: encodedRollup}) + txData, err := d.CreateBlobRollup(&common.L1RollupTx{Rollup: encodedRollup}) if err != nil { return fmt.Errorf("failed to create blob rollup: %w", err) } diff --git a/integration/smartcontract/smartcontracts_test.go b/integration/smartcontract/smartcontracts_test.go index 8914d96357..132cce164c 100644 --- a/integration/smartcontract/smartcontracts_test.go +++ b/integration/smartcontract/smartcontracts_test.go @@ -1,6 +1,8 @@ package smartcontract import ( + "crypto/ecdsa" + "fmt" "testing" "time" @@ -155,7 +157,7 @@ func nonAttestedNodesCannotCreateRollup(t *testing.T, mgmtContractLib *debugMgmt if err != nil { t.Error(err) } - txData, err := mgmtContractLib.CreateBlobRollup(ðadapter.L1RollupTx{Rollup: encodedRollup}) + txData, err := mgmtContractLib.CreateBlobRollup(&common.L1RollupTx{Rollup: encodedRollup}) if err != nil { t.Error(err) } @@ -170,7 +172,7 @@ func nonAttestedNodesCannotCreateRollup(t *testing.T, mgmtContractLib *debugMgmt func secretCannotBeInitializedTwice(t *testing.T, mgmtContractLib *debugMgmtContractLib, w *debugWallet, client ethadapter.EthClient) { aggregatorID := datagenerator.RandomAddress() txData := mgmtContractLib.CreateInitializeSecret( - ðadapter.L1InitializeSecretTx{ + &common.L1InitializeSecretTx{ EnclaveID: &aggregatorID, }, ) @@ -196,7 +198,7 @@ func secretCannotBeInitializedTwice(t *testing.T, mgmtContractLib *debugMgmtCont // do the same again aggregatorID = datagenerator.RandomAddress() txData = mgmtContractLib.CreateInitializeSecret( - ðadapter.L1InitializeSecretTx{ + &common.L1InitializeSecretTx{ EnclaveID: &aggregatorID, }, ) @@ -225,7 +227,7 @@ func attestedNodesCreateRollup(t *testing.T, mgmtContractLib *debugMgmtContractL // the aggregator starts the network txData := mgmtContractLib.CreateInitializeSecret( - ðadapter.L1InitializeSecretTx{ + &common.L1InitializeSecretTx{ EnclaveID: &enclaveID, }, ) @@ -256,7 +258,7 @@ func nonAttestedNodesCannotAttest(t *testing.T, mgmtContractLib *debugMgmtContra // aggregator A starts the network secret txData := mgmtContractLib.CreateInitializeSecret( - ðadapter.L1InitializeSecretTx{ + &common.L1InitializeSecretTx{ EnclaveID: &aggAID, }, ) @@ -277,7 +279,7 @@ func nonAttestedNodesCannotAttest(t *testing.T, mgmtContractLib *debugMgmtContra aggBID := crypto.PubkeyToAddress(aggBPrivateKey.PublicKey) txData = mgmtContractLib.CreateRequestSecret( - ðadapter.L1RequestSecretTx{ + &common.L1RequestSecretTx{ Attestation: datagenerator.RandomBytes(10), }, ) @@ -300,11 +302,11 @@ func nonAttestedNodesCannotAttest(t *testing.T, mgmtContractLib *debugMgmtContra fakeSecret := []byte{123} txData = mgmtContractLib.CreateRespondSecret( - (ðadapter.L1RespondSecretTx{ - AttesterID: aggCID, - RequesterID: aggBID, + Sign(&common.L1RespondSecretTx{ Secret: fakeSecret, - }).Sign(aggCPrivateKey), + RequesterID: aggBID, + AttesterID: aggCID, + }, aggCPrivateKey), true, ) @@ -315,11 +317,11 @@ func nonAttestedNodesCannotAttest(t *testing.T, mgmtContractLib *debugMgmtContra // agg c responds to the secret AGAIN, but trying to mimick aggregator A txData = mgmtContractLib.CreateRespondSecret( - (ðadapter.L1RespondSecretTx{ + Sign(&common.L1RespondSecretTx{ Secret: fakeSecret, RequesterID: aggBID, AttesterID: aggAID, - }).Sign(aggCPrivateKey), + }, aggCPrivateKey), true, ) @@ -341,7 +343,7 @@ func newlyAttestedNodesCanAttest(t *testing.T, mgmtContractLib *debugMgmtContrac // the aggregator starts the network txData := mgmtContractLib.CreateInitializeSecret( - ðadapter.L1InitializeSecretTx{ + &common.L1InitializeSecretTx{ EnclaveID: &aggAID, InitialSecret: secretBytes, }, @@ -370,7 +372,7 @@ func newlyAttestedNodesCanAttest(t *testing.T, mgmtContractLib *debugMgmtContrac aggBID := crypto.PubkeyToAddress(aggBPrivateKey.PublicKey) txData = mgmtContractLib.CreateRequestSecret( - ðadapter.L1RequestSecretTx{ + &common.L1RequestSecretTx{ Attestation: datagenerator.RandomBytes(10), }, ) @@ -390,7 +392,7 @@ func newlyAttestedNodesCanAttest(t *testing.T, mgmtContractLib *debugMgmtContrac aggCID := crypto.PubkeyToAddress(aggCPrivateKey.PublicKey) txData = mgmtContractLib.CreateRequestSecret( - ðadapter.L1RequestSecretTx{ + &common.L1RequestSecretTx{ Attestation: datagenerator.RandomBytes(10), }, ) @@ -405,11 +407,11 @@ func newlyAttestedNodesCanAttest(t *testing.T, mgmtContractLib *debugMgmtContrac // Agg A responds to Agg C request txData = mgmtContractLib.CreateRespondSecret( - (ðadapter.L1RespondSecretTx{ + Sign(&common.L1RespondSecretTx{ Secret: secretBytes, RequesterID: aggCID, AttesterID: aggAID, - }).Sign(aggAPrivateKey), + }, aggAPrivateKey), true, ) _, receipt, err = w.AwaitedSignAndSendTransaction(client, txData) @@ -432,11 +434,11 @@ func newlyAttestedNodesCanAttest(t *testing.T, mgmtContractLib *debugMgmtContrac // agg C attests agg B txData = mgmtContractLib.CreateRespondSecret( - (ðadapter.L1RespondSecretTx{ + Sign(&common.L1RespondSecretTx{ Secret: secretBytes, RequesterID: aggBID, AttesterID: aggCID, - }).Sign(aggCPrivateKey), + }, aggCPrivateKey), true, ) _, receipt, err = w.AwaitedSignAndSendTransaction(client, txData) @@ -456,3 +458,28 @@ func newlyAttestedNodesCanAttest(t *testing.T, mgmtContractLib *debugMgmtContrac t.Error("expected agg to be attested") } } + +// Sign signs the payload with a given private key +func Sign(scretTx *common.L1RespondSecretTx, privateKey *ecdsa.PrivateKey) *common.L1RespondSecretTx { + var data []byte + data = append(data, scretTx.AttesterID.Bytes()...) + data = append(data, scretTx.RequesterID.Bytes()...) + data = append(data, string(scretTx.Secret)...) + + ethereumMessageHash := func(data []byte) []byte { + prefix := fmt.Sprintf("\x19Ethereum Signed Message:\n%d", len(data)) + return crypto.Keccak256([]byte(prefix), data) + } + + hashedData := ethereumMessageHash(data) + // sign the hash + signedHash, err := crypto.Sign(hashedData, privateKey) + if err != nil { + return nil + } + + // set recovery id to 27; prevent malleable signatures + signedHash[64] += 27 + scretTx.AttesterSig = signedHash + return scretTx +}