diff --git a/bindings/bin/rollup_deployed.hex b/bindings/bin/rollup_deployed.hex index aab843afb..68a52ca9c 100644 --- a/bindings/bin/rollup_deployed.hex +++ b/bindings/bin/rollup_deployed.hex @@ -1 +1 @@ -0x608060405260043610610353575f3560e01c8063728cdbca116101bd578063b8d0a1b0116100f2578063d8dc99d211610092578063dff7827e1161006d578063dff7827e14610ac4578063e3fff1dd14610ad9578063f2fde38b14610af8578063fb1e8b0414610b17575f80fd5b8063d8dc99d214610a71578063ddd8a3dc14610a86578063de8b303514610aa5575f80fd5b8063cd4edc69116100cd578063cd4edc6914610a0b578063ce5db8d614610a1e578063cf9a674514610a33578063d279c19114610a52575f80fd5b8063b8d0a1b0146109ae578063bedb86fb146109cd578063c5553892146109ec575f80fd5b8063a479265d1161015d578063b31a77d311610138578063b31a77d31461093c578063b348442514610951578063b35dac4e14610970578063b3e0a5091461098f575f80fd5b8063a479265d146108dd578063a4f209b0146108f2578063abc8d68d14610911575f80fd5b80638f1d3776116101985780638f1d3776146107af578063910129d41461085f57806397fc007c14610890578063a415d8dc146108af575f80fd5b8063728cdbca1461075a57806388b1ea09146107795780638da5cb5b14610792575f80fd5b80632a213ba1116102935780635c975abb11610233578063612672901161020e57806361267290146106dd57806368589dfa146106fc5780636c578c1d14610727578063715018a614610746575f80fd5b80635c975abb1461061a5780635ef7a94a146106315780635f77cf1d14610691575f80fd5b80633e001b661161026e5780633e001b66146105b4578063428868b5146105c95780634e8f1d67146105dc57806357e0af6c146105fb575f80fd5b80632a213ba1146105335780632b7ac3f31461055e5780633b70c18a14610595575f80fd5b806313361101116102fe5780631e8825be116102d95780631e8825be1461049f57806321e2f9e0146104be5780632362f03e146104dd5780632571098d14610508575f80fd5b8063133611011461043b57806318463fb01461045a57806318af3b2b1461046f575f80fd5b806310d445831161032e57806310d44583146103e5578063116a1f4214610404578063121dcd5014610426575f80fd5b806304d772151461035e578063059def61146103a15780630ceb6780146103c4575f80fd5b3661035a57005b5f80fd5b348015610369575f80fd5b5061038c610378366004614d1c565b60a36020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156103ac575f80fd5b506103b6609d5481565b604051908152602001610398565b3480156103cf575f80fd5b506103e36103de366004614d4e565b610b2c565b005b3480156103f0575f80fd5b506103e36103ff366004614dac565b610bfe565b34801561040f575f80fd5b5061038c61041e366004614d1c565b609d54101590565b348015610431575f80fd5b506103b6609e5481565b348015610446575f80fd5b506103e3610455366004614df4565b610f3a565b348015610465575f80fd5b506103b660a75481565b34801561047a575f80fd5b5061038c610489366004614d1c565b5f90815260a26020526040902060010154421090565b3480156104aa575f80fd5b506103e36104b9366004614e59565b611434565b3480156104c9575f80fd5b5061038c6104d8366004614d1c565b61181f565b3480156104e8575f80fd5b506103b66104f7366004614d1c565b60a16020525f908152604090205481565b348015610513575f80fd5b506103b6610522366004614d1c565b60a06020525f908152604090205481565b34801561053e575f80fd5b506103b661054d366004614d1c565b60ad6020525f908152604090205481565b348015610569575f80fd5b50609c5461057d906001600160a01b031681565b6040516001600160a01b039091168152602001610398565b3480156105a0575f80fd5b50609b5461057d906001600160a01b031681565b3480156105bf575f80fd5b506103b660aa5481565b6103e36105d7366004614e59565b61184d565b3480156105e7575f80fd5b506103e36105f6366004614eb9565b611c00565b348015610606575f80fd5b506103e3610615366004614d1c565b611fd4565b348015610625575f80fd5b5060655460ff1661038c565b34801561063c575f80fd5b5061067161064b366004614d1c565b60a26020525f908152604090208054600182015460028301546003909301549192909184565b604080519485526020850193909352918301526060820152608001610398565b34801561069c575f80fd5b506106c47f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff9091168152602001610398565b3480156106e8575f80fd5b506103e36106f7366004614d1c565b61207f565b348015610707575f80fd5b506103b6610716366004614d1c565b60ab6020525f908152604090205481565b348015610732575f80fd5b506103e3610741366004614d4e565b61225a565b348015610751575f80fd5b506103e3612317565b348015610765575f80fd5b506103e3610774366004614f6a565b61232a565b348015610784575f80fd5b5060a65461038c9060ff1681565b34801561079d575f80fd5b506033546001600160a01b031661057d565b3480156107ba575f80fd5b5061081b6107c9366004614d1c565b60a46020525f9081526040902080546001820154600283015460039093015467ffffffffffffffff831693680100000000000000009093046001600160a01b0316929060ff8082169161010090041686565b6040805167ffffffffffffffff90971687526001600160a01b03909516602087015293850192909252606084015215156080830152151560a082015260c001610398565b34801561086a575f80fd5b5061038c610879366004614d1c565b5f90815260a4602052604090206003015460ff1690565b34801561089b575f80fd5b506103e36108aa366004614d4e565b612633565b3480156108ba575f80fd5b5061038c6108c9366004614d4e565b609f6020525f908152604090205460ff1681565b3480156108e8575f80fd5b506103b660995481565b3480156108fd575f80fd5b506103e361090c366004614d1c565b612716565b34801561091c575f80fd5b506103b661092b366004614d4e565b60a56020525f908152604090205481565b348015610947575f80fd5b506103b660a85481565b34801561095c575f80fd5b506103e361096b366004614fc5565b6127c6565b34801561097b575f80fd5b506103e361098a366004614d4e565b612aca565b34801561099a575f80fd5b506103e36109a9366004614df4565b612b23565b3480156109b9575f80fd5b506103e36109c8366004614fc5565b612e80565b3480156109d8575f80fd5b506103e36109e7366004615039565b612f09565b3480156109f7575f80fd5b506103e3610a06366004614d1c565b613047565b6103e3610a1936600461506b565b6130ea565b348015610a29575f80fd5b506103b660985481565b348015610a3e575f80fd5b506103e3610a4d366004614d1c565b61367c565b348015610a5d575f80fd5b506103e3610a6c366004614d4e565b6137eb565b348015610a7c575f80fd5b506103b660ac5481565b348015610a91575f80fd5b5060975461057d906001600160a01b031681565b348015610ab0575f80fd5b5061038c610abf366004614d1c565b6138aa565b348015610acf575f80fd5b506103b6609a5481565b348015610ae4575f80fd5b506103e3610af3366004614d1c565b6138f4565b348015610b03575f80fd5b506103e3610b12366004614d4e565b613997565b348015610b22575f80fd5b506103b660a95481565b610b34613a24565b6001600160a01b0381165f908152609f602052604090205460ff1615610ba15760405162461bcd60e51b815260206004820152601f60248201527f6163636f756e7420697320616c72656164792061206368616c6c656e6765720060448201526064015b60405180910390fd5b6001600160a01b0381165f818152609f6020908152604091829020805460ff1916600190811790915591519182527f7feb653c7b1f0d23daeed494225b3f28851cdc8973fcc653866d9b6e205fc00991015b60405180910390a250565b610c06613a24565b5f8111610c555760405162461bcd60e51b815260206004820152601560248201527f636f756e74206d757374206265206e6f6e7a65726f00000000000000000000006044820152606401610b98565b5f80610c618585613a7e565b915091505f610c74836001015160c01c90565b5f81815260a160205260409020549091508214610cd35760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b5f60a181610ce187856150c0565b81526020019081526020015f205414610d615760405162461bcd60e51b8152602060048201526024808201527f726576657274696e67206d7573742073746172742066726f6d2074686520656e60448201527f64696e67000000000000000000000000000000000000000000000000000000006064820152608401610b98565b609d548111610dd85760405162461bcd60e51b815260206004820152602160248201527f63616e206f6e6c792072657665727420756e46696e616c697a6564206261746360448201527f68000000000000000000000000000000000000000000000000000000000000006064820152608401610b98565b610de36001826150d3565b609e555b8315610f3257604051829082907ecae2739091badfd91c373f0a16cede691e0cd25bb80cff77dd5caeb4710146905f90a35f81815260a16020526040812055610e2f816138aa565b15610e8a575f81815260a460209081526040808320600181015490546801000000000000000090046001600160a01b0316845260a59092528220805491929091610e7a9084906150c0565b909155505060a6805460ff191690555b5f81815260a46020526040812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181018290556002810191909155600301805461ffff1916905560a85415801590610eea575060a85481145b15610ef4575f60a8555b6001015f81815260a160205260409020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90940193915081610de7575b505050505050565b60a85415610f8a5760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b610f92613b17565b5f80610f9e8484613a7e565b915091505f610fb1836001015160c01c90565b5f81815260a1602052604090205490915082146110105760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b6110198161181f565b6110655760405162461bcd60e51b815260206004820152600f60248201527f6261746368206e6f7420657869737400000000000000000000000000000000006044820152606401610b98565b61106e816138aa565b156110bb5760405162461bcd60e51b815260206004820152601260248201527f626174636820696e206368616c6c656e676500000000000000000000000000006044820152606401610b98565b5f81815260a4602052604090206003015460ff161561111c5760405162461bcd60e51b815260206004820152601660248201527f62617463682073686f756c6420626520726576657274000000000000000000006044820152606401610b98565b5f81815260a2602052604090206001015442101561117c5760405162461bcd60e51b815260206004820152601960248201527f626174636820696e206368616c6c656e67652077696e646f77000000000000006044820152606401610b98565b605983015160a05f61118f6001856150d3565b81526020019081526020015f2054146111ea5760405162461bcd60e51b815260206004820152601d60248201527f696e636f72726563742070726576696f757320737461746520726f6f740000006044820152606401610b98565b5f81815260a06020526040902054156112455760405162461bcd60e51b815260206004820152601660248201527f626174636820616c7265616479207665726966696564000000000000000000006044820152606401610b98565b80609d54600101146112995760405162461bcd60e51b815260206004820152601560248201527f696e636f727265637420626174636820696e64657800000000000000000000006044820152606401610b98565b609d819055600160a35f6112ae866099015190565b815260208101919091526040015f20805460ff191691151591909117905560798301515f82815260a060205260409020556112fd6112f0846011015160c01c90565b600985015160c01c613b6a565b60a25f61130b6001846150d3565b815260208101919091526040015f908120818155600180820183905560028201839055600390910182905560ab919061134490846150d3565b81526020019081526020015f205f905560ad5f60018361136491906150d3565b81526020019081526020015f205f905560a45f60018361138491906150d3565b815260208082019290925260409081015f90812080547fffffffff000000000000000000000000000000000000000000000000000000001681556001810182905560028101829055600301805461ffff1916905583815260a1909252902054817f26ba82f907317eedc97d0cbef23de76a43dd6edb563bdb6e9407645b950a7a2d611410866079015190565b60998701516040805192835260208301919091520160405180910390a35050505050565b6097546001600160a01b03166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156114a0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114c491906150e6565b6115105760405162461bcd60e51b815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610b98565b60a854156115605760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b611568613b17565b5f49156115b75760405162461bcd60e51b815260206004820152601f60248201527f636f6d6d69745374617465206d757374206e6f7420636172727920626c6f62006044820152606401610b98565b5f6115cd6115c86020850185615101565b613a7e565b5090505f6115df826001015160c01c90565b6115ea9060016150c0565b5f81815260ad602052604090205490915061166d5760405162461bcd60e51b815260206004820152602260248201527f6e6f2073746f72656420626c6f62206861736820666f7220746869732062617460448201527f63680000000000000000000000000000000000000000000000000000000000006064820152608401610b98565b60ac54609b54604080517fb59b1a7800000000000000000000000000000000000000000000000000000000815290514293926001600160a01b03169163b59b1a789160048083019260209291908290030181865afa1580156116d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116f59190615162565b6116ff91906150c0565b1015611767575f6117166080860160608701615179565b61ffff16116117675760405162461bcd60e51b815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610b98565b6097545f906001600160a01b031663d096c3c6336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156117d5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117f99190615162565b905061181885858360ad5f8781526020019081526020015f2054613c27565b5050505050565b5f81815260a260205260408120541580159061184757505f82815260a1602052604090205415155b92915050565b6097546001600160a01b03166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156118b9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118dd91906150e6565b6119295760405162461bcd60e51b815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610b98565b60a854156119795760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b611981613b17565b5f6119926115c86020850185615101565b5090505f6119a4826001015160c01c90565b6119af9060016150c0565b5f81815260ad602052604090205490915015611a335760405162461bcd60e51b815260206004820152602860248201527f636f6d6d69744261746368207265717569726573206e6f2073746f726564206260448201527f6c6f6220686173680000000000000000000000000000000000000000000000006064820152608401610b98565b60ac54609b54604080517fb59b1a7800000000000000000000000000000000000000000000000000000000815290514293926001600160a01b03169163b59b1a789160048083019260209291908290030181865afa158015611a97573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611abb9190615162565b611ac591906150c0565b1015611b2d575f611adc6080860160608701615179565b61ffff1611611b2d5760405162461bcd60e51b815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610b98565b6097545f906001600160a01b031663d096c3c6336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611b9b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bbf9190615162565b90505f804915611bd0575f49611bf2565b7f010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c4440145b9050610f3286868484613c27565b60a85415611c505760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b611c58613b17565b60ac54609e545f90815260a2602052604081205490914291611c7a91906150c0565b1090505f4260ac54609b5f9054906101000a90046001600160a01b03166001600160a01b031663b59b1a786040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cd2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cf69190615162565b611d0091906150c0565b10905081158015611d0e5750805b15611d75575f611d2460808a0160608b01615179565b61ffff1611611d755760405162461bcd60e51b815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610b98565b8180611d7e5750805b611dca5760405162461bcd60e51b815260206004820152600e60248201527f696e76616c69642074696d696e670000000000000000000000000000000000006044820152606401610b98565b5f611ddb6115c860208b018b615101565b5090505f611ded826001015160c01c90565b611df89060016150c0565b5f81815260ad60205260408120549192509015611e98575f4915611e845760405162461bcd60e51b815260206004820152602f60248201527f6d757374206e6f7420636172727920626c6f62207768656e207573696e67207360448201527f746f72656420626c6f62206861736800000000000000000000000000000000006064820152608401610b98565b505f81815260ad6020526040902054611ecb565b5f4915611ea6575f49611ec8565b7f010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c4440145b90505b611ed78b8b5f84613c27565b5f80611ee38b8b613a7e565b915091505f611ef6836001015160c01c90565b905080609e5414611f495760405162461bcd60e51b815260206004820152601660248201527f696e636f727265637420626174636820686561646572000000000000000000006044820152606401610b98565b5f81815260a160205260409020548214611fa55760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b5f81815260a26020526040902042600190910155611fc4838b8b6142a2565b5050505050505050505050505050565b611fdc613a24565b5f81118015611fed57506099548114155b6120395760405162461bcd60e51b815260206004820152601860248201527f696e76616c6964206e65772070726f6f662077696e646f7700000000000000006044820152606401610b98565b609980549082905560408051828152602081018490527f1e3a2094feb4b696dd3d7caea38ad2f41dbdcac3fa3943c7a693aff8a64b0a6191015b60405180910390a15050565b5f54600290610100900460ff1615801561209f57505f5460ff8083169116105b6121115760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610b98565b5f805461ffff191660ff83161761010017905561212f5f5460ff1690565b60ff166002146121815760405162461bcd60e51b815260206004820152601660248201527f6d757374206861766520696e697469616c697a656421000000000000000000006044820152606401610b98565b816121f45760405162461bcd60e51b815260206004820152602760248201527f63616e206e6f742073657420737461746520726f6f742077697468206279746560448201527f73333228302921000000000000000000000000000000000000000000000000006064820152608401610b98565b609e545f90815260ab602052604090205461221d57609e545f90815260ab602052604090208290555b5f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602001612073565b612262613a24565b6001600160a01b0381165f908152609f602052604090205460ff166122c95760405162461bcd60e51b815260206004820152601b60248201527f6163636f756e74206973206e6f742061206368616c6c656e67657200000000006044820152606401610b98565b6001600160a01b0381165f818152609f60209081526040808320805460ff19169055519182527f7feb653c7b1f0d23daeed494225b3f28851cdc8973fcc653866d9b6e205fc0099101610bf3565b61231f613a24565b6123285f614455565b565b5f54610100900460ff161580801561234857505f54600160ff909116105b806123615750303b15801561236157505f5460ff166001145b6123d35760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610b98565b5f805460ff1916600117905580156123f4575f805461ff0019166101001790555b6001600160a01b038616158061241157506001600160a01b038516155b15612448576040517fecc6fdf000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03871661249e5760405162461bcd60e51b815260206004820152601b60248201527f696e76616c6964206c31207374616b696e6720636f6e747261637400000000006044820152606401610b98565b6124a66144be565b6124ae614542565b609780546001600160a01b03808a167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255609b8054898416908316179055609c805492881692909116821790556098859055609984905560a98390556040515f907f728af3d16a5760405e27a082c98ab272e9f0a1d02f0085d41532a26093aedd96908290a3604080515f8152602081018690527fa577f4223f91f74e2dad65bbb8c30807587ae95d0d34288057bb3ec0d398a437910160405180910390a1604080515f8152602081018590527f1e3a2094feb4b696dd3d7caea38ad2f41dbdcac3fa3943c7a693aff8a64b0a61910160405180910390a1604080515f8152602081018490527ffb81bce17f015797e11949d3c332e2bf9453faf68f728447426803138f2b0223910160405180910390a1801561262a575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b61263b613a24565b6001600160a01b038116158015906126615750609c546001600160a01b03828116911614155b6126ad5760405162461bcd60e51b815260206004820152601460248201527f696e76616c6964206e65772076657269666965720000000000000000000000006044820152606401610b98565b609c80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f728af3d16a5760405e27a082c98ab272e9f0a1d02f0085d41532a26093aedd96905f90a35050565b61271e613a24565b5f8111801561272e575060648111155b801561273c575060a9548114155b6127885760405162461bcd60e51b815260206004820152601f60248201527f696e76616c69642070726f6f66207265776172642070657263656e74616765006044820152606401610b98565b60a980549082905560408051828152602081018490527ffb81bce17f015797e11949d3c332e2bf9453faf68f728447426803138f2b02239101612073565b60a854156128165760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b61281e613b17565b6097546001600160a01b03166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561288a573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128ae91906150e6565b6128fa5760405162461bcd60e51b815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610b98565b5f806129068686613a7e565b915091505f612919836001015160c01c90565b5f81815260a1602052604090205490915082146129785760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b612981816138aa565b6129cd5760405162461bcd60e51b815260206004820152601260248201527f626174636820696e206368616c6c656e676500000000000000000000000000006044820152606401610b98565b5f81815260a46020526040902060038101805461ff00191661010017905560a6805460ff191690556099546002909101544291612a09916150c0565b11612a7f575f81815260a4602090815260408083206003908101805460ff1916600117905560a2835292819020909201548251808401909352600783527f54696d656f75740000000000000000000000000000000000000000000000000091830191909152612a7a918391906145c6565b61262a565b612a8a8386866142a2565b61262a81336040518060400160405280600d81526020017f50726f6f66207375636365737300000000000000000000000000000000000000815250614722565b612ad2613a24565b60aa80545f909155612ae482826147ee565b604080516001600160a01b0384168152602081018390527fb1b2058a6969e2d25e47bcaebe8ae21c29a23b2752429315b75e2f4f285f3d879101612073565b612b2b613a24565b5f805260a06020527fb84a74ec6ef4d0e83b6006dfaa014ab4026f9f3b97d186e604d29998a4e808ea5415612ba25760405162461bcd60e51b815260206004820152601660248201527f67656e6573697320626174636820696d706f72746564000000000000000000006044820152606401610b98565b5f80612bae8484613a7e565b915091505f612bc1836001015160c01c90565b90508015612c115760405162461bcd60e51b815260206004820152601360248201527f696e76616c696420626174636820696e646578000000000000000000000000006044820152606401610b98565b5f612c1d846079015190565b905080612c6c5760405162461bcd60e51b815260206004820152600f60248201527f7a65726f20737461746520726f6f7400000000000000000000000000000000006044820152606401610b98565b600984015160c01c15612cc15760405162461bcd60e51b815260206004820152601d60248201527f6c31206d65737361676520706f707065642073686f756c6420626520300000006044820152606401610b98565b5f612ccd856019015190565b03612d1a5760405162461bcd60e51b815260206004820152600e60248201527f7a65726f206461746120686173680000000000000000000000000000000000006044820152606401610b98565b7f010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014612d46856039015190565b14612d935760405162461bcd60e51b815260206004820152601660248201527f696e76616c69642076657273696f6e65642068617368000000000000000000006044820152606401610b98565b5f82815260a1602090815260408083208690558051608081018252428082528184019081528183018581526060830186815288875260a28652848720935184559151600184015551600283015551600390910155603987015160ad83528184205560ab825280832084905560a0909152808220839055609e849055609d84905551849184917f2c32d4ae151744d0bf0b9464a3e897a1d17ed2f1af71f7c9a75f12ce0d28238f9190a3604080518281525f6020820152849184917f26ba82f907317eedc97d0cbef23de76a43dd6edb563bdb6e9407645b950a7a2d910160405180910390a3505050505050565b5f80612e8c8686613a7e565b915091505f612e9f836001015160c01c90565b5f81815260a160205260409020549091508214612efe5760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b61262a8386866142a2565b612f11613a24565b801561301557612f1f614899565b60a65460ff1615612fd45760a7545f90815260a460209081526040808320600181015490546801000000000000000090046001600160a01b0316845260a59092528220805491929091612f739084906150c0565b909155505060a7545f90815260a46020526040812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181018290556002810191909155600301805461ffff1916905560a6805460ff191690555b7f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258335b6040516001600160a01b03909116815260200160405180910390a150565b61301d6148f3565b7f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33612ff7565b50565b61304f613a24565b5f81118015613060575060ac548114155b6130ac5760405162461bcd60e51b815260206004820152601f60248201527f696e76616c6964206e657720726f6c6c75702064656c617920706572696f64006044820152606401610b98565b60ac80549082905560408051828152602081018490527f624e47dc9fb8f8cfeaf4ead4710277cc1757136cfa885e465514cf6d510f0ad19101612073565b335f908152609f602052604090205460ff166131485760405162461bcd60e51b815260206004820152601760248201527f6f6e6c79206368616c6c656e67657220616c6c6f7765640000000000000000006044820152606401610b98565b60a854156131985760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b6131a0613b17565b60a65460ff16156131f35760405162461bcd60e51b815260206004820152601460248201527f616c726561647920696e206368616c6c656e67650000000000000000000000006044820152606401610b98565b8167ffffffffffffffff16609d541061324e5760405162461bcd60e51b815260206004820152601760248201527f626174636820616c72656164792066696e616c697a65640000000000000000006044820152606401610b98565b67ffffffffffffffff82165f90815260a1602052604090205481146132b55760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b6132c88267ffffffffffffffff1661181f565b6133145760405162461bcd60e51b815260206004820152600f60248201527f6261746368206e6f7420657869737400000000000000000000000000000000006044820152606401610b98565b67ffffffffffffffff82165f90815260a460205260409020546801000000000000000090046001600160a01b03161561338f5760405162461bcd60e51b815260206004820152601860248201527f626174636820616c7265616479206368616c6c656e67656400000000000000006044820152606401610b98565b67ffffffffffffffff82165f90815260a26020526040902060010154421061341f5760405162461bcd60e51b815260206004820152603360248201527f63616e6e6f74206368616c6c656e6765206261746368206f757473696465207460448201527f6865206368616c6c656e67652077696e646f77000000000000000000000000006064820152608401610b98565b60975f9054906101000a90046001600160a01b03166001600160a01b0316630d13fd7b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561346f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134939190615162565b3410156134e25760405162461bcd60e51b815260206004820152601260248201527f696e73756666696369656e742076616c756500000000000000000000000000006044820152606401610b98565b67ffffffffffffffff82811660a78190556040805160c0810182528281523360208083018281523484860190815242606086019081525f6080870181815260a0880182815299825260a4909552969096209451855492516001600160a01b031668010000000000000000027fffffffff000000000000000000000000000000000000000000000000000000009093169816979097171783559451600183015591516002820155925160039093018054925115156101000261ff00199415159490941661ffff19909316929092179290921790556001600160a01b03168267ffffffffffffffff167f3a6ea19df25b49e7624e313ce7c1ab23984238e93727260db56a81735b1b9976346040516135fa91815260200190565b60405180910390a35f609d54600161361291906150c0565b90505b609e54811161366a578267ffffffffffffffff168114613658576099545f82815260a26020526040812060010180549091906136529084906150c0565b90915550505b806136628161519a565b915050613615565b505060a6805460ff1916600117905550565b5f54600390610100900460ff1615801561369c57505f5460ff8083169116105b61370e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610b98565b5f805461ffff191660ff8316176101001781558290036137705760405162461bcd60e51b815260206004820152601b60248201527f696e76616c696420726f6c6c75702064656c617920706572696f6400000000006044820152606401610b98565b60ac829055604080515f8152602081018490527f624e47dc9fb8f8cfeaf4ead4710277cc1757136cfa885e465514cf6d510f0ad1910160405180910390a15f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602001612073565b335f90815260a560205260408120549081900361384a5760405162461bcd60e51b815260206004820152601c60248201527f696e76616c69642062617463684368616c6c656e6765526577617264000000006044820152606401610b98565b335f90815260a5602052604081205561386382826147ee565b816001600160a01b03167f9c25fa83f414ed363c8d39c98fb3e17567b3431cede71eb062c49d2a63ce247a8260405161389e91815260200190565b60405180910390a25050565b5f81815260a460205260408120546801000000000000000090046001600160a01b0316158015906118475750505f90815260a46020526040902060030154610100900460ff161590565b6138fc613a24565b5f8111801561390d57506098548114155b6139595760405162461bcd60e51b815260206004820152601b60248201527f696e76616c6964206e65772066696e616c697a6520706572696f6400000000006044820152606401610b98565b609880549082905560408051828152602081018490527fa577f4223f91f74e2dad65bbb8c30807587ae95d0d34288057bb3ec0d398a4379101612073565b61399f613a24565b6001600160a01b038116613a1b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610b98565b61304481614455565b6033546001600160a01b031633146123285760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b98565b5f805f613a8b858561492c565b90505f8160ff165f03613aac57613aa2868661499c565b9094509050613b09565b8160ff16600103613ac157613aa28686614a05565b60405162461bcd60e51b815260206004820152601960248201527f556e737570706f727465642062617463682076657273696f6e000000000000006044820152606401610b98565b808420925050509250929050565b60655460ff16156123285760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610b98565b805f03613b75575050565b8082035f5b82811015613c2157610100818403811115613b9457508083035b609b546040517f3c7f528300000000000000000000000000000000000000000000000000000000815260048101859052602481018390526001600160a01b0390911690633c7f5283906044015f604051808303815f87803b158015613bf7575f80fd5b505af1158015613c09573d5f803e3d5ffd5b50505050610100830192505061010081019050613b7a565b50505050565b613c3460208501856151d1565b60ff161580613c525750613c4b60208501856151d1565b60ff166001145b613c9e5760405162461bcd60e51b815260206004820152600f60248201527f696e76616c69642076657273696f6e00000000000000000000000000000000006044820152606401610b98565b6080840135613cef5760405162461bcd60e51b815260206004820152601b60248201527f70726576696f757320737461746520726f6f74206973207a65726f00000000006044820152606401610b98565b60a0840135613d405760405162461bcd60e51b815260206004820152601660248201527f6e657720737461746520726f6f74206973207a65726f000000000000000000006044820152606401610b98565b5f80613d526115c86020880188615101565b915091505f613d65836001015160c01c90565b90505f60a181613d768460016150c0565b81526020019081526020015f205414613dd15760405162461bcd60e51b815260206004820152601760248201527f626174636820616c726561647920636f6d6d69747465640000000000000000006044820152606401610b98565b609e548114613e225760405162461bcd60e51b815260206004820152601560248201527f696e636f727265637420626174636820696e64657800000000000000000000006044820152606401610b98565b5f81815260a160205260409020548214613e7e5760405162461bcd60e51b815260206004820152601b60248201527f696e636f727265637420706172656e74206261746368206861736800000000006044820152606401610b98565b5f81815260ab6020526040902054608088013514613ede5760405162461bcd60e51b815260206004820152601d60248201527f696e636f72726563742070726576696f757320737461746520726f6f740000006044820152606401610b98565b5f613eed846011015160c01c90565b90505f613f19613f0360608b0160408c016151f1565b613f1360808c0160608d01615179565b84614a58565b9050613f2b60808a0160608b01615179565b6001939093019261ffff1691909101908560f9613f4b60208c018c6151d1565b60ff16600103613f5a57506101015b604080518281019091529650613f7f87613f7760208e018e6151d1565b60ff16614a9c565b60c085901b6001880152613fad87613f9d60808e0160608f01615179565b61ffff1660c01b60099190910152565b60c084811b6011890152601988018490526039880183905260808c0135605989015260a08c013560798901528b0135609988015261401187613ff260208d018d615101565b60405161400092919061520a565b604051809103902060b99190910152565b60d98701869052600161402760208d018d6151d1565b60ff1610614059576140598761404360608e0160408f016151f1565b67ffffffffffffffff1660c01b60f99190910152565b8087205f86815260a1602090815260408083209390935560ab815282822060a08f0135905560ad905290812083905560a65460ff16156140c25760a7545f90815260a4602052604090206002015460995442916140b5916150c0565b6140bf91906150d3565b90505b604051806080016040528042815260200182609854426140e291906150c0565b6140ec91906150c0565b81526020018d604001602081019061410491906151f1565b67ffffffffffffffff16815260209081018c90525f88815260a2825260409081902083518155838301516001820155908301516002820155606090920151600390920191909155609e8790556097546001600160a01b031692506374fe27b791508b359061417e90614178908e018e615101565b5f614aa3565b5f61418c60408f018f615101565b6040518663ffffffff1660e01b81526004016141ac959493929190615260565b602060405180830381865afa1580156141c7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906141eb91906150e6565b61425d5760405162461bcd60e51b815260206004820152602160248201527f746865207369676e617475726520766572696669636174696f6e206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610b98565b5f84815260a16020526040808220549051909186917f2c32d4ae151744d0bf0b9464a3e897a1d17ed2f1af71f7c9a75f12ce0d28238f9190a350505050505050505050565b806142ef5760405162461bcd60e51b815260206004820152601360248201527f496e76616c69642062617463682070726f6f66000000000000000000000000006044820152606401610b98565b5f6142fe846001015160c01c90565b90505f61430c856039015190565b90505f7f000000000000000000000000000000000000000000000000000000000000000061433b876059015190565b6079880151609989015160b98a015160198b015160405160c09690961b7fffffffffffffffff000000000000000000000000000000000000000000000000166020870152602886019490945260488501929092526068840152608883015260a882015260c8810183905260e801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120609c549091506001600160a01b0316632c09a8486143fd885160f81c90565b858888866040518663ffffffff1660e01b81526004016144219594939291906152d3565b5f6040518083038186803b158015614437575f80fd5b505afa158015614449573d5f803e3d5ffd5b50505050505050505050565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f54610100900460ff1661453a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b98565b612328614af7565b5f54610100900460ff166145be5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b98565b612328614b7f565b60a88390555f83815260a460205260408082205460975491517f45bc4d1000000000000000000000000000000000000000000000000000000000815260048101869052680100000000000000009091046001600160a01b03908116939216906345bc4d10906024016020604051808303815f875af115801561464a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061466e9190615162565b5f86815260a4602052604090206001015490915061468d9082906150c0565b5f86815260a460209081526040808320546801000000000000000090046001600160a01b0316835260a5909152812080549091906146cc9084906150c0565b90915550506040516146df908490615304565b604051908190038120906001600160a01b0384169087907fe70d3820e244d5f71d1a6395db24f3460e8dca966edc1fd3625b6292880a877a905f90a45050505050565b5f83815260a4602052604081206001015460a9549091906064906147469084615330565b6147509190615347565b905061475c81836150d3565b60aa5f82825461476c91906150c0565b90915550506001600160a01b0384165f90815260a56020526040812080548392906147989084906150c0565b90915550506040516147ab908490615304565b604051908190038120906001600160a01b0386169087907fe70d3820e244d5f71d1a6395db24f3460e8dca966edc1fd3625b6292880a877a905f90a45050505050565b8015614895575f826001600160a01b0316826040515f6040518083038185875af1925050503d805f811461483d576040519150601f19603f3d011682016040523d82523d5f602084013e614842565b606091505b50509050806148935760405162461bcd60e51b815260206004820152601b60248201527f526f6c6c75703a20455448207472616e73666572206661696c656400000000006044820152606401610b98565b505b5050565b6148a1613b17565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586148d63390565b6040516001600160a01b03909116815260200160405180910390a1565b6148fb614c04565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa336148d6565b5f8161497a5760405162461bcd60e51b815260206004820152601260248201527f456d7074792062617463682068656164657200000000000000000000000000006044820152606401610b98565b82825f81811061498c5761498c61537f565b919091013560f81c949350505050565b5f8160f98110156149ef5760405162461bcd60e51b815260206004820152601d60248201527f626174636820686561646572206c656e67746820746f6f20736d616c6c0000006044820152606401610b98565b6040519150808483378082016040529250929050565b5f8161010181146149ef5760405162461bcd60e51b815260206004820181905260248201527f626174636820686561646572206c656e67746820697320696e636f72726563746044820152606401610b98565b6040805160c085901b815260f084901b6008820152600a60208502820181019092525f918101614a8d8161ffff871686614c56565b82900390912095945050505050565b8082535050565b60605f80808080614ab6888a018a615499565b9550955095509550955050818710614ad4579450614af09350505050565b838710614ae8578295505050505050614af0565b509293505050505b9392505050565b5f54610100900460ff16614b735760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b98565b6065805460ff19169055565b5f54610100900460ff16614bfb5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b98565b61232833614455565b60655460ff166123285760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610b98565b5f825f03614c65575082614af0565b609b546001600160a01b03165f5b84811015614d12576040517fae453cd5000000000000000000000000000000000000000000000000000000008152600481018590525f906001600160a01b0384169063ae453cd590602401602060405180830381865afa158015614cd9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614cfd9190615162565b87525060209095019460019384019301614c73565b5093949350505050565b5f60208284031215614d2c575f80fd5b5035919050565b80356001600160a01b0381168114614d49575f80fd5b919050565b5f60208284031215614d5e575f80fd5b614af082614d33565b5f8083601f840112614d77575f80fd5b50813567ffffffffffffffff811115614d8e575f80fd5b602083019150836020828501011115614da5575f80fd5b9250929050565b5f805f60408486031215614dbe575f80fd5b833567ffffffffffffffff811115614dd4575f80fd5b614de086828701614d67565b909790965060209590950135949350505050565b5f8060208385031215614e05575f80fd5b823567ffffffffffffffff811115614e1b575f80fd5b614e2785828601614d67565b90969095509350505050565b5f60e08284031215614e43575f80fd5b50919050565b5f60608284031215614e43575f80fd5b5f8060408385031215614e6a575f80fd5b823567ffffffffffffffff80821115614e81575f80fd5b614e8d86838701614e33565b93506020850135915080821115614ea2575f80fd5b50614eaf85828601614e49565b9150509250929050565b5f805f805f8060808789031215614ece575f80fd5b863567ffffffffffffffff80821115614ee5575f80fd5b614ef18a838b01614e33565b97506020890135915080821115614f06575f80fd5b614f128a838b01614e49565b96506040890135915080821115614f27575f80fd5b614f338a838b01614d67565b90965094506060890135915080821115614f4b575f80fd5b50614f5889828a01614d67565b979a9699509497509295939492505050565b5f805f805f8060c08789031215614f7f575f80fd5b614f8887614d33565b9550614f9660208801614d33565b9450614fa460408801614d33565b9350606087013592506080870135915060a087013590509295509295509295565b5f805f8060408587031215614fd8575f80fd5b843567ffffffffffffffff80821115614fef575f80fd5b614ffb88838901614d67565b90965094506020870135915080821115615013575f80fd5b5061502087828801614d67565b95989497509550505050565b8015158114613044575f80fd5b5f60208284031215615049575f80fd5b8135614af08161502c565b803567ffffffffffffffff81168114614d49575f80fd5b5f806040838503121561507c575f80fd5b61508583615054565b946020939093013593505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8082018082111561184757611847615093565b8181038181111561184757611847615093565b5f602082840312156150f6575f80fd5b8151614af08161502c565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615134575f80fd5b83018035915067ffffffffffffffff82111561514e575f80fd5b602001915036819003821315614da5575f80fd5b5f60208284031215615172575f80fd5b5051919050565b5f60208284031215615189575f80fd5b813561ffff81168114614af0575f80fd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036151ca576151ca615093565b5060010190565b5f602082840312156151e1575f80fd5b813560ff81168114614af0575f80fd5b5f60208284031215615201575f80fd5b614af082615054565b818382375f9101908152919050565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f6080820187835260206080602085015281885180845260a08601915060208a0193505f5b818110156152aa5784516001600160a01b031683529383019391830191600101615285565b505087604086015284810360608601526152c5818789615219565b9a9950505050505050505050565b858152846020820152608060408201525f6152f2608083018587615219565b90508260608301529695505050505050565b5f82515f5b818110156153235760208186018101518583015201615309565b505f920191825250919050565b808202811582820484141761184757611847615093565b5f8261537a577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f8301126153e8575f80fd5b8135602067ffffffffffffffff80831115615405576154056153ac565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f83011681018181108482111715615448576154486153ac565b6040529384526020818701810194908101925087851115615467575f80fd5b6020870191505b8482101561548e5761547f82614d33565b8352918301919083019061546e565b979650505050505050565b5f805f805f8060c087890312156154ae575f80fd5b86359550602087013567ffffffffffffffff808211156154cc575f80fd5b6154d88a838b016153d9565b96506040890135955060608901359150808211156154f4575f80fd5b6155008a838b016153d9565b94506080890135935060a089013591508082111561551c575f80fd5b5061552989828a016153d9565b915050929550929550929556fea164736f6c6343000818000a +0x608060405260043610610353575f3560e01c8063728cdbca116101bd578063b8d0a1b0116100f2578063d8dc99d211610092578063dff7827e1161006d578063dff7827e14610ac4578063e3fff1dd14610ad9578063f2fde38b14610af8578063fb1e8b0414610b17575f80fd5b8063d8dc99d214610a71578063ddd8a3dc14610a86578063de8b303514610aa5575f80fd5b8063cd4edc69116100cd578063cd4edc6914610a0b578063ce5db8d614610a1e578063cf9a674514610a33578063d279c19114610a52575f80fd5b8063b8d0a1b0146109ae578063bedb86fb146109cd578063c5553892146109ec575f80fd5b8063a479265d1161015d578063b31a77d311610138578063b31a77d31461093c578063b348442514610951578063b35dac4e14610970578063b3e0a5091461098f575f80fd5b8063a479265d146108dd578063a4f209b0146108f2578063abc8d68d14610911575f80fd5b80638f1d3776116101985780638f1d3776146107af578063910129d41461085f57806397fc007c14610890578063a415d8dc146108af575f80fd5b8063728cdbca1461075a57806388b1ea09146107795780638da5cb5b14610792575f80fd5b80632a213ba1116102935780635c975abb11610233578063612672901161020e57806361267290146106dd57806368589dfa146106fc5780636c578c1d14610727578063715018a614610746575f80fd5b80635c975abb1461061a5780635ef7a94a146106315780635f77cf1d14610691575f80fd5b80633e001b661161026e5780633e001b66146105b4578063428868b5146105c95780634e8f1d67146105dc57806357e0af6c146105fb575f80fd5b80632a213ba1146105335780632b7ac3f31461055e5780633b70c18a14610595575f80fd5b806313361101116102fe5780631e8825be116102d95780631e8825be1461049f57806321e2f9e0146104be5780632362f03e146104dd5780632571098d14610508575f80fd5b8063133611011461043b57806318463fb01461045a57806318af3b2b1461046f575f80fd5b806310d445831161032e57806310d44583146103e5578063116a1f4214610404578063121dcd5014610426575f80fd5b806304d772151461035e578063059def61146103a15780630ceb6780146103c4575f80fd5b3661035a57005b5f80fd5b348015610369575f80fd5b5061038c610378366004614e13565b60a36020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156103ac575f80fd5b506103b6609d5481565b604051908152602001610398565b3480156103cf575f80fd5b506103e36103de366004614e40565b610b2c565b005b3480156103f0575f80fd5b506103e36103ff366004614e9e565b610bfe565b34801561040f575f80fd5b5061038c61041e366004614e13565b609d54101590565b348015610431575f80fd5b506103b6609e5481565b348015610446575f80fd5b506103e3610455366004614ee6565b610f3a565b348015610465575f80fd5b506103b660a75481565b34801561047a575f80fd5b5061038c610489366004614e13565b5f90815260a26020526040902060010154421090565b3480156104aa575f80fd5b506103e36104b9366004614f45565b611434565b3480156104c9575f80fd5b5061038c6104d8366004614e13565b61181f565b3480156104e8575f80fd5b506103b66104f7366004614e13565b60a16020525f908152604090205481565b348015610513575f80fd5b506103b6610522366004614e13565b60a06020525f908152604090205481565b34801561053e575f80fd5b506103b661054d366004614e13565b60ad6020525f908152604090205481565b348015610569575f80fd5b50609c5461057d906001600160a01b031681565b6040516001600160a01b039091168152602001610398565b3480156105a0575f80fd5b50609b5461057d906001600160a01b031681565b3480156105bf575f80fd5b506103b660aa5481565b6103e36105d7366004614f45565b61184d565b3480156105e7575f80fd5b506103e36105f6366004614fa5565b611be8565b348015610606575f80fd5b506103e3610615366004614e13565b611f9c565b348015610625575f80fd5b5060655460ff1661038c565b34801561063c575f80fd5b5061067161064b366004614e13565b60a26020525f908152604090208054600182015460028301546003909301549192909184565b604080519485526020850193909352918301526060820152608001610398565b34801561069c575f80fd5b506106c47f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff9091168152602001610398565b3480156106e8575f80fd5b506103e36106f7366004614e13565b612047565b348015610707575f80fd5b506103b6610716366004614e13565b60ab6020525f908152604090205481565b348015610732575f80fd5b506103e3610741366004614e40565b612222565b348015610751575f80fd5b506103e36122df565b348015610765575f80fd5b506103e3610774366004615056565b6122f2565b348015610784575f80fd5b5060a65461038c9060ff1681565b34801561079d575f80fd5b506033546001600160a01b031661057d565b3480156107ba575f80fd5b5061081b6107c9366004614e13565b60a46020525f9081526040902080546001820154600283015460039093015467ffffffffffffffff831693680100000000000000009093046001600160a01b0316929060ff8082169161010090041686565b6040805167ffffffffffffffff90971687526001600160a01b03909516602087015293850192909252606084015215156080830152151560a082015260c001610398565b34801561086a575f80fd5b5061038c610879366004614e13565b5f90815260a4602052604090206003015460ff1690565b34801561089b575f80fd5b506103e36108aa366004614e40565b6125fb565b3480156108ba575f80fd5b5061038c6108c9366004614e40565b609f6020525f908152604090205460ff1681565b3480156108e8575f80fd5b506103b660995481565b3480156108fd575f80fd5b506103e361090c366004614e13565b6126de565b34801561091c575f80fd5b506103b661092b366004614e40565b60a56020525f908152604090205481565b348015610947575f80fd5b506103b660a85481565b34801561095c575f80fd5b506103e361096b3660046150b1565b61278e565b34801561097b575f80fd5b506103e361098a366004614e40565b612a92565b34801561099a575f80fd5b506103e36109a9366004614ee6565b612aeb565b3480156109b9575f80fd5b506103e36109c83660046150b1565b612e48565b3480156109d8575f80fd5b506103e36109e7366004615125565b612ed1565b3480156109f7575f80fd5b506103e3610a06366004614e13565b61300f565b6103e3610a19366004615157565b6130b2565b348015610a29575f80fd5b506103b660985481565b348015610a3e575f80fd5b506103e3610a4d366004614e13565b613644565b348015610a5d575f80fd5b506103e3610a6c366004614e40565b6137b3565b348015610a7c575f80fd5b506103b660ac5481565b348015610a91575f80fd5b5060975461057d906001600160a01b031681565b348015610ab0575f80fd5b5061038c610abf366004614e13565b613872565b348015610acf575f80fd5b506103b6609a5481565b348015610ae4575f80fd5b506103e3610af3366004614e13565b6138bc565b348015610b03575f80fd5b506103e3610b12366004614e40565b61395f565b348015610b22575f80fd5b506103b660a95481565b610b346139ec565b6001600160a01b0381165f908152609f602052604090205460ff1615610ba15760405162461bcd60e51b815260206004820152601f60248201527f6163636f756e7420697320616c72656164792061206368616c6c656e6765720060448201526064015b60405180910390fd5b6001600160a01b0381165f818152609f6020908152604091829020805460ff1916600190811790915591519182527f7feb653c7b1f0d23daeed494225b3f28851cdc8973fcc653866d9b6e205fc00991015b60405180910390a250565b610c066139ec565b5f8111610c555760405162461bcd60e51b815260206004820152601560248201527f636f756e74206d757374206265206e6f6e7a65726f00000000000000000000006044820152606401610b98565b5f80610c618585613a46565b915091505f610c74836001015160c01c90565b5f81815260a160205260409020549091508214610cd35760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b5f60a181610ce187856151ac565b81526020019081526020015f205414610d615760405162461bcd60e51b8152602060048201526024808201527f726576657274696e67206d7573742073746172742066726f6d2074686520656e60448201527f64696e67000000000000000000000000000000000000000000000000000000006064820152608401610b98565b609d548111610dd85760405162461bcd60e51b815260206004820152602160248201527f63616e206f6e6c792072657665727420756e46696e616c697a6564206261746360448201527f68000000000000000000000000000000000000000000000000000000000000006064820152608401610b98565b610de36001826151bf565b609e555b8315610f3257604051829082907ecae2739091badfd91c373f0a16cede691e0cd25bb80cff77dd5caeb4710146905f90a35f81815260a16020526040812055610e2f81613872565b15610e8a575f81815260a460209081526040808320600181015490546801000000000000000090046001600160a01b0316845260a59092528220805491929091610e7a9084906151ac565b909155505060a6805460ff191690555b5f81815260a46020526040812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181018290556002810191909155600301805461ffff1916905560a85415801590610eea575060a85481145b15610ef4575f60a8555b6001015f81815260a160205260409020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90940193915081610de7575b505050505050565b60a85415610f8a5760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b610f92613aee565b5f80610f9e8484613a46565b915091505f610fb1836001015160c01c90565b5f81815260a1602052604090205490915082146110105760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b6110198161181f565b6110655760405162461bcd60e51b815260206004820152600f60248201527f6261746368206e6f7420657869737400000000000000000000000000000000006044820152606401610b98565b61106e81613872565b156110bb5760405162461bcd60e51b815260206004820152601260248201527f626174636820696e206368616c6c656e676500000000000000000000000000006044820152606401610b98565b5f81815260a4602052604090206003015460ff161561111c5760405162461bcd60e51b815260206004820152601660248201527f62617463682073686f756c6420626520726576657274000000000000000000006044820152606401610b98565b5f81815260a2602052604090206001015442101561117c5760405162461bcd60e51b815260206004820152601960248201527f626174636820696e206368616c6c656e67652077696e646f77000000000000006044820152606401610b98565b605983015160a05f61118f6001856151bf565b81526020019081526020015f2054146111ea5760405162461bcd60e51b815260206004820152601d60248201527f696e636f72726563742070726576696f757320737461746520726f6f740000006044820152606401610b98565b5f81815260a06020526040902054156112455760405162461bcd60e51b815260206004820152601660248201527f626174636820616c7265616479207665726966696564000000000000000000006044820152606401610b98565b80609d54600101146112995760405162461bcd60e51b815260206004820152601560248201527f696e636f727265637420626174636820696e64657800000000000000000000006044820152606401610b98565b609d819055600160a35f6112ae866099015190565b815260208101919091526040015f20805460ff191691151591909117905560798301515f82815260a060205260409020556112fd6112f0846011015160c01c90565b600985015160c01c613b41565b60a25f61130b6001846151bf565b815260208101919091526040015f908120818155600180820183905560028201839055600390910182905560ab919061134490846151bf565b81526020019081526020015f205f905560ad5f60018361136491906151bf565b81526020019081526020015f205f905560a45f60018361138491906151bf565b815260208082019290925260409081015f90812080547fffffffff000000000000000000000000000000000000000000000000000000001681556001810182905560028101829055600301805461ffff1916905583815260a1909252902054817f26ba82f907317eedc97d0cbef23de76a43dd6edb563bdb6e9407645b950a7a2d611410866079015190565b60998701516040805192835260208301919091520160405180910390a35050505050565b6097546001600160a01b03166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156114a0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114c491906151d2565b6115105760405162461bcd60e51b815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610b98565b60a854156115605760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b611568613aee565b5f49156115b75760405162461bcd60e51b815260206004820152601f60248201527f636f6d6d69745374617465206d757374206e6f7420636172727920626c6f62006044820152606401610b98565b5f6115cd6115c860208501856151ed565b613a46565b5090505f6115df826001015160c01c90565b6115ea9060016151ac565b5f81815260ad602052604090205490915061166d5760405162461bcd60e51b815260206004820152602260248201527f6e6f2073746f72656420626c6f62206861736820666f7220746869732062617460448201527f63680000000000000000000000000000000000000000000000000000000000006064820152608401610b98565b60ac54609b54604080517fb59b1a7800000000000000000000000000000000000000000000000000000000815290514293926001600160a01b03169163b59b1a789160048083019260209291908290030181865afa1580156116d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116f5919061524e565b6116ff91906151ac565b1015611767575f6117166080860160608701615265565b61ffff16116117675760405162461bcd60e51b815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610b98565b6097545f906001600160a01b031663d096c3c6336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156117d5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117f9919061524e565b905061181885858360ad5f8781526020019081526020015f2054613bfe565b5050505050565b5f81815260a260205260408120541580159061184757505f82815260a1602052604090205415155b92915050565b6097546001600160a01b03166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156118b9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118dd91906151d2565b6119295760405162461bcd60e51b815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610b98565b60a854156119795760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b611981613aee565b5f6119926115c860208501856151ed565b5090505f6119a4826001015160c01c90565b6119af9060016151ac565b5f81815260ad602052604090205490915015611a335760405162461bcd60e51b815260206004820152602860248201527f636f6d6d69744261746368207265717569726573206e6f2073746f726564206260448201527f6c6f6220686173680000000000000000000000000000000000000000000000006064820152608401610b98565b60ac54609b54604080517fb59b1a7800000000000000000000000000000000000000000000000000000000815290514293926001600160a01b03169163b59b1a789160048083019260209291908290030181865afa158015611a97573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611abb919061524e565b611ac591906151ac565b1015611b2d575f611adc6080860160608701615265565b61ffff1611611b2d5760405162461bcd60e51b815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610b98565b6097545f906001600160a01b031663d096c3c6336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611b9b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bbf919061524e565b90505f611bda611bd26020880188615286565b60ff1661425e565b9050610f3286868484613bfe565b60a85415611c385760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b611c40613aee565b60ac54609e545f90815260a2602052604081205490914291611c6291906151ac565b1090505f4260ac54609b5f9054906101000a90046001600160a01b03166001600160a01b031663b59b1a786040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cba573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cde919061524e565b611ce891906151ac565b10905081158015611cf65750805b15611d5d575f611d0c60808a0160608b01615265565b61ffff1611611d5d5760405162461bcd60e51b815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610b98565b8180611d665750805b611db25760405162461bcd60e51b815260206004820152600e60248201527f696e76616c69642074696d696e670000000000000000000000000000000000006044820152606401610b98565b5f611dc36115c860208b018b6151ed565b5090505f611dd5826001015160c01c90565b611de09060016151ac565b5f81815260ad60205260408120549192509015611e80575f4915611e6c5760405162461bcd60e51b815260206004820152602f60248201527f6d757374206e6f7420636172727920626c6f62207768656e207573696e67207360448201527f746f72656420626c6f62206861736800000000000000000000000000000000006064820152608401610b98565b505f81815260ad6020526040902054611e93565b611e90611bd260208d018d615286565b90505b611e9f8b8b5f84613bfe565b5f80611eab8b8b613a46565b915091505f611ebe836001015160c01c90565b905080609e5414611f115760405162461bcd60e51b815260206004820152601660248201527f696e636f727265637420626174636820686561646572000000000000000000006044820152606401610b98565b5f81815260a160205260409020548214611f6d5760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b5f81815260a26020526040902042600190910155611f8c838b8b614399565b5050505050505050505050505050565b611fa46139ec565b5f81118015611fb557506099548114155b6120015760405162461bcd60e51b815260206004820152601860248201527f696e76616c6964206e65772070726f6f662077696e646f7700000000000000006044820152606401610b98565b609980549082905560408051828152602081018490527f1e3a2094feb4b696dd3d7caea38ad2f41dbdcac3fa3943c7a693aff8a64b0a6191015b60405180910390a15050565b5f54600290610100900460ff1615801561206757505f5460ff8083169116105b6120d95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610b98565b5f805461ffff191660ff8316176101001790556120f75f5460ff1690565b60ff166002146121495760405162461bcd60e51b815260206004820152601660248201527f6d757374206861766520696e697469616c697a656421000000000000000000006044820152606401610b98565b816121bc5760405162461bcd60e51b815260206004820152602760248201527f63616e206e6f742073657420737461746520726f6f742077697468206279746560448201527f73333228302921000000000000000000000000000000000000000000000000006064820152608401610b98565b609e545f90815260ab60205260409020546121e557609e545f90815260ab602052604090208290555b5f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200161203b565b61222a6139ec565b6001600160a01b0381165f908152609f602052604090205460ff166122915760405162461bcd60e51b815260206004820152601b60248201527f6163636f756e74206973206e6f742061206368616c6c656e67657200000000006044820152606401610b98565b6001600160a01b0381165f818152609f60209081526040808320805460ff19169055519182527f7feb653c7b1f0d23daeed494225b3f28851cdc8973fcc653866d9b6e205fc0099101610bf3565b6122e76139ec565b6122f05f61454c565b565b5f54610100900460ff161580801561231057505f54600160ff909116105b806123295750303b15801561232957505f5460ff166001145b61239b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610b98565b5f805460ff1916600117905580156123bc575f805461ff0019166101001790555b6001600160a01b03861615806123d957506001600160a01b038516155b15612410576040517fecc6fdf000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0387166124665760405162461bcd60e51b815260206004820152601b60248201527f696e76616c6964206c31207374616b696e6720636f6e747261637400000000006044820152606401610b98565b61246e6145b5565b612476614639565b609780546001600160a01b03808a167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255609b8054898416908316179055609c805492881692909116821790556098859055609984905560a98390556040515f907f728af3d16a5760405e27a082c98ab272e9f0a1d02f0085d41532a26093aedd96908290a3604080515f8152602081018690527fa577f4223f91f74e2dad65bbb8c30807587ae95d0d34288057bb3ec0d398a437910160405180910390a1604080515f8152602081018590527f1e3a2094feb4b696dd3d7caea38ad2f41dbdcac3fa3943c7a693aff8a64b0a61910160405180910390a1604080515f8152602081018490527ffb81bce17f015797e11949d3c332e2bf9453faf68f728447426803138f2b0223910160405180910390a180156125f2575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b6126036139ec565b6001600160a01b038116158015906126295750609c546001600160a01b03828116911614155b6126755760405162461bcd60e51b815260206004820152601460248201527f696e76616c6964206e65772076657269666965720000000000000000000000006044820152606401610b98565b609c80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f728af3d16a5760405e27a082c98ab272e9f0a1d02f0085d41532a26093aedd96905f90a35050565b6126e66139ec565b5f811180156126f6575060648111155b8015612704575060a9548114155b6127505760405162461bcd60e51b815260206004820152601f60248201527f696e76616c69642070726f6f66207265776172642070657263656e74616765006044820152606401610b98565b60a980549082905560408051828152602081018490527ffb81bce17f015797e11949d3c332e2bf9453faf68f728447426803138f2b0223910161203b565b60a854156127de5760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b6127e6613aee565b6097546001600160a01b03166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015612852573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061287691906151d2565b6128c25760405162461bcd60e51b815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610b98565b5f806128ce8686613a46565b915091505f6128e1836001015160c01c90565b5f81815260a1602052604090205490915082146129405760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b61294981613872565b6129955760405162461bcd60e51b815260206004820152601260248201527f626174636820696e206368616c6c656e676500000000000000000000000000006044820152606401610b98565b5f81815260a46020526040902060038101805461ff00191661010017905560a6805460ff1916905560995460029091015442916129d1916151ac565b11612a47575f81815260a4602090815260408083206003908101805460ff1916600117905560a2835292819020909201548251808401909352600783527f54696d656f75740000000000000000000000000000000000000000000000000091830191909152612a42918391906146bd565b6125f2565b612a52838686614399565b6125f281336040518060400160405280600d81526020017f50726f6f66207375636365737300000000000000000000000000000000000000815250614819565b612a9a6139ec565b60aa80545f909155612aac82826148e5565b604080516001600160a01b0384168152602081018390527fb1b2058a6969e2d25e47bcaebe8ae21c29a23b2752429315b75e2f4f285f3d87910161203b565b612af36139ec565b5f805260a06020527fb84a74ec6ef4d0e83b6006dfaa014ab4026f9f3b97d186e604d29998a4e808ea5415612b6a5760405162461bcd60e51b815260206004820152601660248201527f67656e6573697320626174636820696d706f72746564000000000000000000006044820152606401610b98565b5f80612b768484613a46565b915091505f612b89836001015160c01c90565b90508015612bd95760405162461bcd60e51b815260206004820152601360248201527f696e76616c696420626174636820696e646578000000000000000000000000006044820152606401610b98565b5f612be5846079015190565b905080612c345760405162461bcd60e51b815260206004820152600f60248201527f7a65726f20737461746520726f6f7400000000000000000000000000000000006044820152606401610b98565b600984015160c01c15612c895760405162461bcd60e51b815260206004820152601d60248201527f6c31206d65737361676520706f707065642073686f756c6420626520300000006044820152606401610b98565b5f612c95856019015190565b03612ce25760405162461bcd60e51b815260206004820152600e60248201527f7a65726f206461746120686173680000000000000000000000000000000000006044820152606401610b98565b7f010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014612d0e856039015190565b14612d5b5760405162461bcd60e51b815260206004820152601660248201527f696e76616c69642076657273696f6e65642068617368000000000000000000006044820152606401610b98565b5f82815260a1602090815260408083208690558051608081018252428082528184019081528183018581526060830186815288875260a28652848720935184559151600184015551600283015551600390910155603987015160ad83528184205560ab825280832084905560a0909152808220839055609e849055609d84905551849184917f2c32d4ae151744d0bf0b9464a3e897a1d17ed2f1af71f7c9a75f12ce0d28238f9190a3604080518281525f6020820152849184917f26ba82f907317eedc97d0cbef23de76a43dd6edb563bdb6e9407645b950a7a2d910160405180910390a3505050505050565b5f80612e548686613a46565b915091505f612e67836001015160c01c90565b5f81815260a160205260409020549091508214612ec65760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b6125f2838686614399565b612ed96139ec565b8015612fdd57612ee7614990565b60a65460ff1615612f9c5760a7545f90815260a460209081526040808320600181015490546801000000000000000090046001600160a01b0316845260a59092528220805491929091612f3b9084906151ac565b909155505060a7545f90815260a46020526040812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181018290556002810191909155600301805461ffff1916905560a6805460ff191690555b7f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258335b6040516001600160a01b03909116815260200160405180910390a150565b612fe56149ea565b7f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33612fbf565b50565b6130176139ec565b5f81118015613028575060ac548114155b6130745760405162461bcd60e51b815260206004820152601f60248201527f696e76616c6964206e657720726f6c6c75702064656c617920706572696f64006044820152606401610b98565b60ac80549082905560408051828152602081018490527f624e47dc9fb8f8cfeaf4ead4710277cc1757136cfa885e465514cf6d510f0ad1910161203b565b335f908152609f602052604090205460ff166131105760405162461bcd60e51b815260206004820152601760248201527f6f6e6c79206368616c6c656e67657220616c6c6f7765640000000000000000006044820152606401610b98565b60a854156131605760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b613168613aee565b60a65460ff16156131bb5760405162461bcd60e51b815260206004820152601460248201527f616c726561647920696e206368616c6c656e67650000000000000000000000006044820152606401610b98565b8167ffffffffffffffff16609d54106132165760405162461bcd60e51b815260206004820152601760248201527f626174636820616c72656164792066696e616c697a65640000000000000000006044820152606401610b98565b67ffffffffffffffff82165f90815260a16020526040902054811461327d5760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b6132908267ffffffffffffffff1661181f565b6132dc5760405162461bcd60e51b815260206004820152600f60248201527f6261746368206e6f7420657869737400000000000000000000000000000000006044820152606401610b98565b67ffffffffffffffff82165f90815260a460205260409020546801000000000000000090046001600160a01b0316156133575760405162461bcd60e51b815260206004820152601860248201527f626174636820616c7265616479206368616c6c656e67656400000000000000006044820152606401610b98565b67ffffffffffffffff82165f90815260a2602052604090206001015442106133e75760405162461bcd60e51b815260206004820152603360248201527f63616e6e6f74206368616c6c656e6765206261746368206f757473696465207460448201527f6865206368616c6c656e67652077696e646f77000000000000000000000000006064820152608401610b98565b60975f9054906101000a90046001600160a01b03166001600160a01b0316630d13fd7b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613437573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061345b919061524e565b3410156134aa5760405162461bcd60e51b815260206004820152601260248201527f696e73756666696369656e742076616c756500000000000000000000000000006044820152606401610b98565b67ffffffffffffffff82811660a78190556040805160c0810182528281523360208083018281523484860190815242606086019081525f6080870181815260a0880182815299825260a4909552969096209451855492516001600160a01b031668010000000000000000027fffffffff000000000000000000000000000000000000000000000000000000009093169816979097171783559451600183015591516002820155925160039093018054925115156101000261ff00199415159490941661ffff19909316929092179290921790556001600160a01b03168267ffffffffffffffff167f3a6ea19df25b49e7624e313ce7c1ab23984238e93727260db56a81735b1b9976346040516135c291815260200190565b60405180910390a35f609d5460016135da91906151ac565b90505b609e548111613632578267ffffffffffffffff168114613620576099545f82815260a260205260408120600101805490919061361a9084906151ac565b90915550505b8061362a816152a6565b9150506135dd565b505060a6805460ff1916600117905550565b5f54600390610100900460ff1615801561366457505f5460ff8083169116105b6136d65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610b98565b5f805461ffff191660ff8316176101001781558290036137385760405162461bcd60e51b815260206004820152601b60248201527f696e76616c696420726f6c6c75702064656c617920706572696f6400000000006044820152606401610b98565b60ac829055604080515f8152602081018490527f624e47dc9fb8f8cfeaf4ead4710277cc1757136cfa885e465514cf6d510f0ad1910160405180910390a15f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200161203b565b335f90815260a56020526040812054908190036138125760405162461bcd60e51b815260206004820152601c60248201527f696e76616c69642062617463684368616c6c656e6765526577617264000000006044820152606401610b98565b335f90815260a5602052604081205561382b82826148e5565b816001600160a01b03167f9c25fa83f414ed363c8d39c98fb3e17567b3431cede71eb062c49d2a63ce247a8260405161386691815260200190565b60405180910390a25050565b5f81815260a460205260408120546801000000000000000090046001600160a01b0316158015906118475750505f90815260a46020526040902060030154610100900460ff161590565b6138c46139ec565b5f811180156138d557506098548114155b6139215760405162461bcd60e51b815260206004820152601b60248201527f696e76616c6964206e65772066696e616c697a6520706572696f6400000000006044820152606401610b98565b609880549082905560408051828152602081018490527fa577f4223f91f74e2dad65bbb8c30807587ae95d0d34288057bb3ec0d398a437910161203b565b6139676139ec565b6001600160a01b0381166139e35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610b98565b61300c8161454c565b6033546001600160a01b031633146122f05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b98565b5f805f613a538585614a23565b90505f8160ff165f03613a7457613a6a8686614a93565b9094509050613ae0565b8160ff1660011480613a8957508160ff166002145b15613a9857613a6a8686614afc565b60405162461bcd60e51b815260206004820152601960248201527f556e737570706f727465642062617463682076657273696f6e000000000000006044820152606401610b98565b808420925050509250929050565b60655460ff16156122f05760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610b98565b805f03613b4c575050565b8082035f5b82811015613bf857610100818403811115613b6b57508083035b609b546040517f3c7f528300000000000000000000000000000000000000000000000000000000815260048101859052602481018390526001600160a01b0390911690633c7f5283906044015f604051808303815f87803b158015613bce575f80fd5b505af1158015613be0573d5f803e3d5ffd5b50505050610100830192505061010081019050613b51565b50505050565b6002613c0d6020860186615286565b60ff161115613c5e5760405162461bcd60e51b815260206004820152600f60248201527f696e76616c69642076657273696f6e00000000000000000000000000000000006044820152606401610b98565b6080840135613caf5760405162461bcd60e51b815260206004820152601b60248201527f70726576696f757320737461746520726f6f74206973207a65726f00000000006044820152606401610b98565b60a0840135613d005760405162461bcd60e51b815260206004820152601660248201527f6e657720737461746520726f6f74206973207a65726f000000000000000000006044820152606401610b98565b5f80613d126115c860208801886151ed565b915091505f613d25836001015160c01c90565b90505f60a181613d368460016151ac565b81526020019081526020015f205414613d915760405162461bcd60e51b815260206004820152601760248201527f626174636820616c726561647920636f6d6d69747465640000000000000000006044820152606401610b98565b609e548114613de25760405162461bcd60e51b815260206004820152601560248201527f696e636f727265637420626174636820696e64657800000000000000000000006044820152606401610b98565b5f81815260a160205260409020548214613e3e5760405162461bcd60e51b815260206004820152601b60248201527f696e636f727265637420706172656e74206261746368206861736800000000006044820152606401610b98565b5f81815260ab6020526040902054608088013514613e9e5760405162461bcd60e51b815260206004820152601d60248201527f696e636f72726563742070726576696f757320737461746520726f6f740000006044820152606401610b98565b5f613ead846011015160c01c90565b90505f613ed9613ec360608b0160408c016152dd565b613ed360808c0160608d01615265565b84614b4f565b9050613eeb60808a0160608b01615265565b60019384019361ffff91909116929092019160f990613f0d60208c018c615286565b60ff1610613f1a57506101015b604080518281019091529550613f3f86613f3760208d018d615286565b60ff16614b93565b60c084901b6001870152613f6d86613f5d60808d0160608e01615265565b61ffff1660c01b60099190910152565b60c083811b6011880152601987018390526039870188905260808b0135605988015260a08b013560798801528a01356099870152613fd186613fb260208c018c6151ed565b604051613fc09291906152f6565b604051809103902060b99190910152565b60d986018590526001613fe760208c018c615286565b60ff1610614019576140198661400360608d0160408e016152dd565b67ffffffffffffffff1660c01b60f99190910152565b8086205f85815260a1602090815260408083209390935560ab815282822060a08e0135905560ad905290812088905560a65460ff16156140825760a7545f90815260a460205260409020600201546099544291614075916151ac565b61407f91906151bf565b90505b604051806080016040528042815260200182609854426140a291906151ac565b6140ac91906151ac565b81526020016140c160608e0160408f016152dd565b67ffffffffffffffff16815260209081018b90525f87815260a2825260409081902083518155838301516001820155908301516002820155606090920151600390920191909155609e8690556097546001600160a01b031692506374fe27b791508a359061413b90614135908d018d6151ed565b5f614b9a565b5f61414960408e018e6151ed565b6040518663ffffffff1660e01b815260040161416995949392919061534c565b602060405180830381865afa158015614184573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906141a891906151d2565b61421a5760405162461bcd60e51b815260206004820152602160248201527f746865207369676e617475726520766572696669636174696f6e206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610b98565b5f83815260a16020526040808220549051909185917f2c32d4ae151744d0bf0b9464a3e897a1d17ed2f1af71f7c9a75f12ce0d28238f9190a3505050505050505050565b5f816002036142ed575f6040515f5b80498061427a5750614289565b6020820283015260010161426d565b6020810280832092016040529092509050806142e75760405162461bcd60e51b815260206004820152601b60248201527f5632207265717569726573206174206c65617374203120626c6f6200000000006044820152606401610b98565b50919050565b600149156143635760405162461bcd60e51b815260206004820152602560248201527f6c6567616379206261746368657320737570706f72742065786163746c79203160448201527f20626c6f620000000000000000000000000000000000000000000000000000006064820152608401610b98565b5f4915614371575f49611847565b507f010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c4440145b919050565b806143e65760405162461bcd60e51b815260206004820152601360248201527f496e76616c69642062617463682070726f6f66000000000000000000000000006044820152606401610b98565b5f6143f5846001015160c01c90565b90505f614403856039015190565b90505f7f0000000000000000000000000000000000000000000000000000000000000000614432876059015190565b6079880151609989015160b98a015160198b015160405160c09690961b7fffffffffffffffff000000000000000000000000000000000000000000000000166020870152602886019490945260488501929092526068840152608883015260a882015260c8810183905260e801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120609c549091506001600160a01b0316632c09a8486144f4885160f81c90565b858888866040518663ffffffff1660e01b81526004016145189594939291906153bf565b5f6040518083038186803b15801561452e575f80fd5b505afa158015614540573d5f803e3d5ffd5b50505050505050505050565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f54610100900460ff166146315760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b98565b6122f0614bee565b5f54610100900460ff166146b55760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b98565b6122f0614c76565b60a88390555f83815260a460205260408082205460975491517f45bc4d1000000000000000000000000000000000000000000000000000000000815260048101869052680100000000000000009091046001600160a01b03908116939216906345bc4d10906024016020604051808303815f875af1158015614741573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614765919061524e565b5f86815260a460205260409020600101549091506147849082906151ac565b5f86815260a460209081526040808320546801000000000000000090046001600160a01b0316835260a5909152812080549091906147c39084906151ac565b90915550506040516147d69084906153f0565b604051908190038120906001600160a01b0384169087907fe70d3820e244d5f71d1a6395db24f3460e8dca966edc1fd3625b6292880a877a905f90a45050505050565b5f83815260a4602052604081206001015460a95490919060649061483d908461541c565b6148479190615433565b905061485381836151bf565b60aa5f82825461486391906151ac565b90915550506001600160a01b0384165f90815260a560205260408120805483929061488f9084906151ac565b90915550506040516148a29084906153f0565b604051908190038120906001600160a01b0386169087907fe70d3820e244d5f71d1a6395db24f3460e8dca966edc1fd3625b6292880a877a905f90a45050505050565b801561498c575f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114614934576040519150601f19603f3d011682016040523d82523d5f602084013e614939565b606091505b505090508061498a5760405162461bcd60e51b815260206004820152601b60248201527f526f6c6c75703a20455448207472616e73666572206661696c656400000000006044820152606401610b98565b505b5050565b614998613aee565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586149cd3390565b6040516001600160a01b03909116815260200160405180910390a1565b6149f2614cfb565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa336149cd565b5f81614a715760405162461bcd60e51b815260206004820152601260248201527f456d7074792062617463682068656164657200000000000000000000000000006044820152606401610b98565b82825f818110614a8357614a8361546b565b919091013560f81c949350505050565b5f8160f9811015614ae65760405162461bcd60e51b815260206004820152601d60248201527f626174636820686561646572206c656e67746820746f6f20736d616c6c0000006044820152606401610b98565b6040519150808483378082016040529250929050565b5f816101018114614ae65760405162461bcd60e51b815260206004820181905260248201527f626174636820686561646572206c656e67746820697320696e636f72726563746044820152606401610b98565b6040805160c085901b815260f084901b6008820152600a60208502820181019092525f918101614b848161ffff871686614d4d565b82900390912095945050505050565b8082535050565b60605f80808080614bad888a018a615585565b9550955095509550955050818710614bcb579450614be79350505050565b838710614bdf578295505050505050614be7565b509293505050505b9392505050565b5f54610100900460ff16614c6a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b98565b6065805460ff19169055565b5f54610100900460ff16614cf25760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b98565b6122f03361454c565b60655460ff166122f05760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610b98565b5f825f03614d5c575082614be7565b609b546001600160a01b03165f5b84811015614e09576040517fae453cd5000000000000000000000000000000000000000000000000000000008152600481018590525f906001600160a01b0384169063ae453cd590602401602060405180830381865afa158015614dd0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614df4919061524e565b87525060209095019460019384019301614d6a565b5093949350505050565b5f60208284031215614e23575f80fd5b5035919050565b80356001600160a01b0381168114614394575f80fd5b5f60208284031215614e50575f80fd5b614be782614e2a565b5f8083601f840112614e69575f80fd5b50813567ffffffffffffffff811115614e80575f80fd5b602083019150836020828501011115614e97575f80fd5b9250929050565b5f805f60408486031215614eb0575f80fd5b833567ffffffffffffffff811115614ec6575f80fd5b614ed286828701614e59565b909790965060209590950135949350505050565b5f8060208385031215614ef7575f80fd5b823567ffffffffffffffff811115614f0d575f80fd5b614f1985828601614e59565b90969095509350505050565b5f60e082840312156142e7575f80fd5b5f606082840312156142e7575f80fd5b5f8060408385031215614f56575f80fd5b823567ffffffffffffffff80821115614f6d575f80fd5b614f7986838701614f25565b93506020850135915080821115614f8e575f80fd5b50614f9b85828601614f35565b9150509250929050565b5f805f805f8060808789031215614fba575f80fd5b863567ffffffffffffffff80821115614fd1575f80fd5b614fdd8a838b01614f25565b97506020890135915080821115614ff2575f80fd5b614ffe8a838b01614f35565b96506040890135915080821115615013575f80fd5b61501f8a838b01614e59565b90965094506060890135915080821115615037575f80fd5b5061504489828a01614e59565b979a9699509497509295939492505050565b5f805f805f8060c0878903121561506b575f80fd5b61507487614e2a565b955061508260208801614e2a565b945061509060408801614e2a565b9350606087013592506080870135915060a087013590509295509295509295565b5f805f80604085870312156150c4575f80fd5b843567ffffffffffffffff808211156150db575f80fd5b6150e788838901614e59565b909650945060208701359150808211156150ff575f80fd5b5061510c87828801614e59565b95989497509550505050565b801515811461300c575f80fd5b5f60208284031215615135575f80fd5b8135614be781615118565b803567ffffffffffffffff81168114614394575f80fd5b5f8060408385031215615168575f80fd5b61517183615140565b946020939093013593505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b808201808211156118475761184761517f565b818103818111156118475761184761517f565b5f602082840312156151e2575f80fd5b8151614be781615118565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615220575f80fd5b83018035915067ffffffffffffffff82111561523a575f80fd5b602001915036819003821315614e97575f80fd5b5f6020828403121561525e575f80fd5b5051919050565b5f60208284031215615275575f80fd5b813561ffff81168114614be7575f80fd5b5f60208284031215615296575f80fd5b813560ff81168114614be7575f80fd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036152d6576152d661517f565b5060010190565b5f602082840312156152ed575f80fd5b614be782615140565b818382375f9101908152919050565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f6080820187835260206080602085015281885180845260a08601915060208a0193505f5b818110156153965784516001600160a01b031683529383019391830191600101615371565b505087604086015284810360608601526153b1818789615305565b9a9950505050505050505050565b858152846020820152608060408201525f6153de608083018587615305565b90508260608301529695505050505050565b5f82515f5b8181101561540f57602081860181015185830152016153f5565b505f920191825250919050565b80820281158282048414176118475761184761517f565b5f82615466577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f8301126154d4575f80fd5b8135602067ffffffffffffffff808311156154f1576154f1615498565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110848211171561553457615534615498565b6040529384526020818701810194908101925087851115615553575f80fd5b6020870191505b8482101561557a5761556b82614e2a565b8352918301919083019061555a565b979650505050505050565b5f805f805f8060c0878903121561559a575f80fd5b86359550602087013567ffffffffffffffff808211156155b8575f80fd5b6155c48a838b016154c5565b96506040890135955060608901359150808211156155e0575f80fd5b6155ec8a838b016154c5565b94506080890135935060a0890135915080821115615608575f80fd5b5061561589828a016154c5565b915050929550929550929556fea164736f6c6343000818000a diff --git a/bindings/bin/zkevmverifierv1_deployed.hex b/bindings/bin/zkevmverifierv1_deployed.hex index 7c168f402..14d355469 100644 --- a/bindings/bin/zkevmverifierv1_deployed.hex +++ b/bindings/bin/zkevmverifierv1_deployed.hex @@ -1 +1 @@ -0x608060405234801561000f575f80fd5b5060043610610085575f3560e01c80637e4f7a8a116100585780637e4f7a8a146100f2578063a48fd34b14610115578063c8bd017614610128578063ffa1ad741461013b575f80fd5b806309665ee7146100895780632a510436146100a457806341493c60146100ca5780636b61d8e7146100df575b5f80fd5b6100915f5481565b6040519081526020015b60405180910390f35b7fd4e8ecd2357dd882209800acd6abb443d231cf287d77ba62b732ce937c8b56e7610091565b6100dd6100d8366004612d64565b61017a565b005b6100916100ed366004612dd8565b610388565b610105610100366004612e17565b610404565b604051901515815260200161009b565b6100dd610123366004612ea9565b612c23565b6100dd610136366004612f10565b612c90565b604080518082018252600681527f76352e302e3000000000000000000000000000000000000000000000000000006020820152905161009b9190612fb9565b5f6101886004828486612fd2565b61019191612ff9565b90507fd4e8ecd2357dd882209800acd6abb443d231cf287d77ba62b732ce937c8b56e77fd4e8ecd2000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461025f576040517f988066a10000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000080841660048301528216602482015260440160405180910390fd5b5f61026a8787610388565b6040805160028082526060820183529293505f929091602083019080368337019050509050885f1c815f815181106102a4576102a4613041565b602002602001018181525050815f1c816001815181106102c6576102c6613041565b60209081029190910101525f30637e4f7a8a6102e5886004818c612fd2565b856040518463ffffffff1660e01b8152600401610304939291906130b5565b602060405180830381865afa15801561031f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610343919061310c565b90508061037c576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050505050565b5f7f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f1b600284846040516103be92919061312b565b602060405180830381855afa1580156103d9573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906103fc919061313a565b169392505050565b5f6040516102408101610416846108a6565b61042085856108b9565b61042986610908565b6104328761091e565b5f61043e86868a610ab8565b905061044981610dee565b90506104558189610e54565b90506104618189610ee2565b5060608201517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000006104b884630100000085612bb8565b086101c0840152506104cb818587610f4d565b6104d682868a6112c2565b91507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018183086101a08401525061050d9050611667565b610516866127ac565b61051f866126fd565b61052886612324565b61053186611e50565b61053a86611bb6565b610543866117b8565b61020001519050612c1b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f77726f6e67206e756d626572206f66207075626c696320696e707574730000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6572726f72206d6f6420657870000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6572726f72206563206f7065726174696f6e00000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f696e707574732061726520626967676572207468616e207200000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f77726f6e672070726f6f662073697a65000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f6f70656e696e677320626967676572207468616e2072000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f6572726f722070616972696e67000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6572726f722076657269667900000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6572726f722072616e646f6d2067656e206b7a670000000000000000000000006044820152606481fd5b600281146108b6576108b661054f565b50565b5f5b81811015610903577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000833511156108f4576108f461066c565b602092909201916001016108bb565b505050565b61036081811461091a5761091a6106cb565b5050565b61018081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000813511156109545761095461072a565b506101a081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000008135111561098b5761098b61072a565b506101c081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000813511156109c2576109c261072a565b506101e081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000813511156109f9576109f961072a565b5061020081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610a3057610a3061072a565b5061026081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610a6757610a6761072a565b5061030081015f5b6001811015610903577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000082351115610aa957610aa961072a565b60209190910190600101610a6f565b5f60405161024081016467616d6d6181527f239ed22af3191cfccd323949e417667defbcb082d9f31527488e523372ea9e7a60208201527f213da3cb623029a98e0186dc8c1a3a31ee249ab93bfb68abc1103900890eccb960408201527f01fd59b61f15d097ad7701c4dc12b8739eadc1d54664773c3ed5d8104c296c2a60608201527e22ee53909feab41bb47f0e6ddb802bb6096fd2027d89c22d94b4e56e227cd060808201527f14992dea1a6515e3f8a2250e30cb9e3bad58ff44bbfdd1390bc8d0a8f2bddd0f60a08201527f1e82777c7079b474d31f9fedafca8f2d108de5c58a2df629a8af49cd424c8c2960c08201527f060081d04d187d301d4223990acab3c887713358f1705af7f53e07aca0f709dd60e08201527f16911506ad1ccf9b39db250ce7752278c8115127c4f85080c2bd153946b4a5be6101008201527f279df33b57d698efd752579ee90674a7241ecdb21c6cb35cdf8ef7c1af73160a6101208201527f202fa12c1e82de2f49dc4c5bc771b94c8495544bb0055c4c381744cc3d1d332d6101408201527f040315f3fd753e8cca89f353d096fb94fcdf9cd41973954a3dd4ec58cba79d5f6101608201527f18e0b4a84e9429c05d0fd0d304acd0f3cfa93437356c112199d4d7c0162a1c9e6101808201527f2e14e072ab351d1b3838323f75ecf9b6c08043c230423d515febd04e29336b776101a08201527f1553e1a7b6e18ba105733244604cd37d82371c3a7b0503fa4aff460870170bcf6101c08201527f0c203d7594efa49bd977084de30db24ce843e501791176c21b5beda79ceaf1366101e08201527f0c4bddeb52250b0114282b00285f224b812fc581f2b55e5c3a49472069f901f36102008201527f2fb4fbb4677318edec4b80fc8fa22ffcce4a51d5f3771e575e726e790a9f9cbe6102208201527f28518b11376dc02418849d45b1f3b0e00d3f74502d713b002b9d7293a1018d79610240820152610260810160208602808883379081019060c0808784375061030501905060208282601b820160025afa905080610db857610db86107e8565b5080519250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182066040820152509392505050565b5f60405161024060405101636265746181528360208201526020816024601c840160025afa80610e2057610e206107e8565b5080519250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018206602082015250919050565b5f60405161024060405101606564616c7068618252602082018681526020810190506103208601600160400280828437928301929190910190506040610220870182375060208282601b850160025afa905080610eb357610eb36107e8565b50517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181069091529392505050565b60405161024060405101637a657461815283602082015260c0808401604083013760208160e4601c840160025afa80610f1d57610f1d6107e8565b50517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019006606091909101525050565b5f60405160608101516101c0820151915085610f6b81878585610fe6565b5f92505f91505b85821015610fdc577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001853582510992507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018385086020958601959094506001929092019101610f72565b5050509392505050565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e427ce32d4886b01bfe313ba1dba6db8b2045d128178a7164500e0a6c1183096001855f5b868110156110d4577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103860882527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b840992506020919091019060010161102f565b506110e0818789611198565b5060019050855f5b8681101561118e577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001868551090982526020820191507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b840992506001016110e8565b5050505050505050565b600183525f805b838110156111ed5781850151828401517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181830990506020840193508084880152505060018101905061119f565b50602081038201915080840193505061122e6020840160027f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001038551612bb8565b5f5b838110156112bb5760208503945082517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018651840984527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018184097fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090940193925050600101611230565b5050505050565b5f60405160608101516101c0820151915061032084015f806112ea896020850135853561146e565b91506112fd8962a653508a018787611333565b90507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018082840987089998505050505050505050565b5f61135f85857f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b612bb8565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001817f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103840894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e427ce32d4886b01bfe313ba1dba6db8b2045d128178a7164500e0a6c1182099050611418867f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff87612bb8565b94507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018482099695505050505050565b5f83525f602084015280604084015250806060830152505f6080820153603060818201535f60828201536042608382015360536084820153604260858201536032608682015360326087820153602d608882015360506089820153606c608a820153606f608b820153606e608c820153606b608d820153600b608e8201535f602082608f8460025afa80611504576115046107e8565b8251600160208501536042602185015360536022850153604260238501536032602485015360326025850153602d602685015360506027850153606c6028850153606f6029850153606e602a850153606b602b850153600b602c850153602084602d8660025afa91508161157a5761157a6107e8565b8351186020840152600260408401536042604184015360536042840153604260438401536032604484015360326045840153602d604684015360506047840153606c6048840153606f6049840153606e604a840153606b604b840153600b604c84015360208301602081602d8360025afa915050806115fb576115fb6107e8565b507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017001000000000000000000000000000000008351099050602082015160801c7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018183089392505050565b604051610240604051016101c08201517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001036060850151086116ed837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff83612bb8565b90507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e427ce32d4886b01bfe313ba1dba6db8b2045d128178a7164500e0a6c11820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018282098451935091507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001905082820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018282099050806080840152505050565b60405161024081016101608201518152610180820151602082015261028083013560408201526102a08301356060820152610220830135608082015261024083013560a08201526102c083013560c08201526102e083013560e082015260608201516101008201526101e08201516101208201526020816101408360025afa8061184457611844610847565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182510690508160408101925061028085013581526102a0850135602082015261189483836102c0880184612b1f565b61016084016118a98484610220890184612b1f565b61014085016118bd84610260890183612b66565b7f1fa4be93b5e7f7e674d5059b63554fab99638b304ed8310e9fa44c281ac9b03b85527f1a01ae7fac6228e39d3cb5a5e71fd31160f3241e79a5f48ffb3737e6c389b7216020860152805160408087019182529095908160608160075afa91508161192a5761192a6107e8565b60208101915081517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703825261196286828586612a16565b50508360408501945061197f8560608801516102808a0184612aad565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b60608801510995507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000186850993506119ff85856102c08a0184612b1f565b611a0b85828485612a16565b50602082810180517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd470381528251865291810151908501527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260408501527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60608501527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60808501527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60a0850152905160c0840152805160e08401527f22f1acbb03c4508760c2430af35865e7cdf9f3eb1224504fdcc3708ddb954a486101008401527f2a344fad01c2ed0ed73142ae1752429eaea515c6f3f6b941103cc21c2308e1cb6101208401527f159f15b842ba9c8449aa3268f981010d4c7142e5193473d80b464e964845c3f86101408401527f0efd30ac7b6f8d0d3ccbc2207587c2acbad1532dc0293f0d034cf8258cd428b3610160840152925061090390508160405160205f6101808460085afa80611ba857611ba8610789565b505f51610200919091015250565b6040516102406040510160208101604082016101e084015180610160860160e08701518152610100870151610180880152610120870151610140880152611c0186835f8b0184612b1f565b611c14826101808a016101408a01612b66565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018383099150611c49868360408b0184612b1f565b611c5c826101a08a016101408a01612b66565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018383099150611c91868360808b0184612b1f565b611ca4826101c08a016101408a01612b66565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183830991507f239ed22af3191cfccd323949e417667defbcb082d9f31527488e523372ea9e7a86527f213da3cb623029a98e0186dc8c1a3a31ee249ab93bfb68abc1103900890eccb98552611d1c84838884612ad8565b611d2f826101e08a016101408a01612b66565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183830991507f01fd59b61f15d097ad7701c4dc12b8739eadc1d54664773c3ed5d8104c296c2a86527e22ee53909feab41bb47f0e6ddb802bb6096fd2027d89c22d94b4e56e227cd08552611da684838884612ad8565b611db9826102008a016101408a01612b66565b61030088017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184840992507f2fb4fbb4677318edec4b80fc8fa22ffcce4a51d5f3771e575e726e790a9f9cbe87527f28518b11376dc02418849d45b1f3b0e00d3f74502d713b002b9d7293a1018d798652611e3685848985612ad8565b611e4583826101408b01612b66565b505050505050505050565b6040516467616d6d616102408201908152606082015161026083015260e08201516102808301526101008201516102a083015260c0836102c08401377f239ed22af3191cfccd323949e417667defbcb082d9f31527488e523372ea9e7a6101408201527f213da3cb623029a98e0186dc8c1a3a31ee249ab93bfb68abc1103900890eccb96101608201527f01fd59b61f15d097ad7701c4dc12b8739eadc1d54664773c3ed5d8104c296c2a610180808301919091527e22ee53909feab41bb47f0e6ddb802bb6096fd2027d89c22d94b4e56e227cd06101a0808401919091527f2fb4fbb4677318edec4b80fc8fa22ffcce4a51d5f3771e575e726e790a9f9cbe6101c0808501919091527f28518b11376dc02418849d45b1f3b0e00d3f74502d713b002b9d7293a1018d796101e0808601919091526101208601516102008087019190915293870135610220860152918601356102408501528501356102608401528401356102808301528301356102a08201526102c081016103008401602081833750610260840135602091820152601b906102e5906101e085018285850160025afa9250505080612005576120056107e8565b506101e00180517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019006905250565b604051610240604051017f060081d04d187d301d4223990acab3c887713358f1705af7f53e07aca0f709dd81527f16911506ad1ccf9b39db250ce7752278c8115127c4f85080c2bd153946b4a5be602082015261209e604082016101808501358360e08601612a82565b7f279df33b57d698efd752579ee90674a7241ecdb21c6cb35cdf8ef7c1af73160a81527f202fa12c1e82de2f49dc4c5bc771b94c8495544bb0055c4c381744cc3d1d332d60208201526120fe604082016101a08501358360e08601612ad8565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0840135610180850135097f040315f3fd753e8cca89f353d096fb94fcdf9cd41973954a3dd4ec58cba79d5f82527f18e0b4a84e9429c05d0fd0d304acd0f3cfa93437356c112199d4d7c0162a1c9e602083015261218760408301828460e08701612ad8565b507f2e14e072ab351d1b3838323f75ecf9b6c08043c230423d515febd04e29336b7781527f1553e1a7b6e18ba105733244604cd37d82371c3a7b0503fa4aff460870170bcf60208201526121e8604082016101c08501358360e08601612ad8565b7f0c203d7594efa49bd977084de30db24ce843e501791176c21b5beda79ceaf13681527f0c4bddeb52250b0114282b00285f224b812fc581f2b55e5c3a49472069f901f36020820152612243604082018260e0850180612a16565b610300830161032084015f5b600181101561228f5781358452602082013560208501526122796040850184358660e08901612ad8565b602092909201916040919091019060010161224f565b5050507f14992dea1a6515e3f8a2250e30cb9e3bad58ff44bbfdd1390bc8d0a8f2bddd0f81527f1e82777c7079b474d31f9fedafca8f2d108de5c58a2df629a8af49cd424c8c2960208201526122ed60408201858360e08601612ad8565b6102208301358152610240830135602082015261231260408201868360e08601612ad8565b6112bb8160a0840160e0850180612a16565b6040516020810151604082015160608301515f8401517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184610260880135097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101e088013586097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610180890135820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000161020089013587097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a08a0135820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000186820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018284097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600580097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001878a0998507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101808c01358a0894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000188860894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160058a0993507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a08c0135850893507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000188850893507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001818a099250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101c08b0135830891507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000187830891507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183850997507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018289097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001908103985085890997507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160808a01518908975061037c88828c612034565b60405160026301000000016102406040510161271e81836060860151612bb8565b91506127338183610140870160a08701612aad565b61274681610100860160a0860180612a4c565b612755818360a0860180612a82565b6127678160c0860160a0860180612a4c565b61277e816101c085015160a0860160a08701612a82565b505060c00180517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703905250565b6040515f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160208301516101e08501350990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040830151820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610180840135820890505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160208401516102008601350990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040840151820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0850135820890505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160408501516101c08701350890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182840992507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018184099250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000015f840151830991507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610260850135830991507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0840151830860808401519092507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000190810391508183087f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001036101209390930192909252505050565b8151845260208201516020850152825160408501526020830151606085015260408160808660065afa806112bb576112bb61060d565b8151845260208201516020850152823560408501526020830135606085015260408160808660065afa806112bb576112bb61060d565b815184526020820151602085015282604085015260408160608660075afa806112bb576112bb61060d565b813584526020820135602085015282604085015260408160608660075afa806112bb576112bb61060d565b815184526020820151602085015282604085015260408460608660075afa815160408601526020820151606086015260408260808760065afa16806112bb576112bb61060d565b813584526020820135602085015282604085015260408460608660075afa815160408601526020820151606086015260408260808760065afa16806112bb576112bb61060d565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001838335097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181835108825250505050565b602083526020808401526020604084015280606084015250806080830152507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160a08201525f60208260c08460055afa80612c1557612c156105ae565b50505190565b949350505050565b5f546040517f41493c6000000000000000000000000000000000000000000000000000000000815230916341493c6091612c689190869086908a908a90600401613151565b5f6040518083038186803b158015612c7e575f80fd5b505afa15801561118e573d5f803e3d5ffd5b3073ffffffffffffffffffffffffffffffffffffffff1663a48fd34b848484604051602001612cc191815260200190565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401612cee93929190613189565b5f6040518083038186803b158015612d04575f80fd5b505afa158015612d16573d5f803e3d5ffd5b50505050505050565b5f8083601f840112612d2f575f80fd5b50813567ffffffffffffffff811115612d46575f80fd5b602083019150836020828501011115612d5d575f80fd5b9250929050565b5f805f805f60608688031215612d78575f80fd5b85359450602086013567ffffffffffffffff80821115612d96575f80fd5b612da289838a01612d1f565b90965094506040880135915080821115612dba575f80fd5b50612dc788828901612d1f565b969995985093965092949392505050565b5f8060208385031215612de9575f80fd5b823567ffffffffffffffff811115612dff575f80fd5b612e0b85828601612d1f565b90969095509350505050565b5f805f8060408587031215612e2a575f80fd5b843567ffffffffffffffff80821115612e41575f80fd5b612e4d88838901612d1f565b90965094506020870135915080821115612e65575f80fd5b818701915087601f830112612e78575f80fd5b813581811115612e86575f80fd5b8860208260051b8501011115612e9a575f80fd5b95989497505060200194505050565b5f805f8060408587031215612ebc575f80fd5b843567ffffffffffffffff80821115612ed3575f80fd5b612edf88838901612d1f565b90965094506020870135915080821115612ef7575f80fd5b50612f0487828801612d1f565b95989497509550505050565b5f805f60408486031215612f22575f80fd5b833567ffffffffffffffff811115612f38575f80fd5b612f4486828701612d1f565b909790965060209590950135949350505050565b5f81518084525f5b81811015612f7c57602081850181015186830182015201612f60565b505f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f612fcb6020830184612f58565b9392505050565b5f8085851115612fe0575f80fd5b83861115612fec575f80fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156130395780818660040360031b1b83161692505b505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b604081525f6130c860408301858761306e565b8281036020848101919091528451808352858201928201905f5b818110156130fe578451835293830193918301916001016130e2565b509098975050505050505050565b5f6020828403121561311c575f80fd5b81518015158114612fcb575f80fd5b818382375f9101908152919050565b5f6020828403121561314a575f80fd5b5051919050565b858152606060208201525f61316a60608301868861306e565b828103604084015261317d81858761306e565b98975050505050505050565b604081525f61319c60408301858761306e565b82810360208401526131ae8185612f58565b969550505050505056fea164736f6c6343000818000a +0x608060405234801561000f575f80fd5b506004361061009f575f3560e01c80637cad4e1311610072578063a48fd34b11610058578063a48fd34b14610154578063c8bd017614610167578063ffa1ad741461017a575f80fd5b80637cad4e131461010c5780637e4f7a8a14610131575f80fd5b806309665ee7146100a35780632a510436146100be57806341493c60146100e45780636b61d8e7146100f9575b5f80fd5b6100ab5f5481565b6040519081526020015b60405180910390f35b7f5a093a2fcb46394f5cadfe55c44d4d572fad9cec7aeb38026b0278322ef07fac6100ab565b6100f76100f2366004612f15565b6101b9565b005b6100ab610107366004612f89565b610527565b7e2f850ee998974d6cc00e50cd0814b098c05bfade466d28573240d057f253526100ab565b61014461013f366004612fc8565b6105a5565b60405190151581526020016100b5565b6100f761016236600461305a565b612dd4565b6100f76101753660046130c1565b612e41565b604080518082018252600681527f76362e312e300000000000000000000000000000000000000000000000000000602082015290516100b5919061316a565b5f6101c76004828486613183565b6101d0916131aa565b90507f5a093a2fcb46394f5cadfe55c44d4d572fad9cec7aeb38026b0278322ef07fac7f5a093a2f000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461029e576040517f988066a10000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000080841660048301528216602482015260440160405180910390fd5b7e2f850ee998974d6cc00e50cd0814b098c05bfade466d28573240d057f253525f6102c98888610527565b90505f6102da60246004888a613183565b6102e3916131f2565b90505f6102f460446024898b613183565b6102fd916131f2565b90505f61030e606460448a8c613183565b610317916131f2565b60408051600580825260c082019092529192505f91906020820160a0803683370190505090508c5f1c815f815181106103525761035261322e565b602002602001018181525050845f1c816001815181106103745761037461322e565b60200260200101818152505083816002815181106103945761039461322e565b60200260200101818152505082816003815181106103b4576103b461322e565b60200260200101818152505081816004815181106103d4576103d461322e565b60209081029190910101528315610417576040517f1fcf917700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b858314610450576040517fd58aec5800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f3073ffffffffffffffffffffffffffffffffffffffff16637e4f7a8a8c8c606490809261048093929190613183565b856040518463ffffffff1660e01b815260040161049f939291906132a2565b602060405180830381865afa1580156104ba573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104de91906132f9565b905080610517576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050505050565b5f7f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f1b6002848460405161055d929190613318565b602060405180830381855afa158015610578573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061059b9190613327565b1690505b92915050565b5f60405161024081016105b784610a47565b6105c18585610a5a565b6105ca86610aa9565b6105d387610abf565b5f6105df86868a610c59565b90506105ea81610f90565b90506105f68189610ff6565b90506106028189611084565b5060608201517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000061065984630200000085612d69565b086101c08401525061066c8185876110ef565b61067782868a611464565b91507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018183086101a0840152506106ae905061180a565b6106b78661295d565b6106c0866128ae565b6106c9866124c9565b6106d286611ff4565b6106db86611d59565b6106e48661195b565b61020001519050612dcc565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f77726f6e67206e756d626572206f66207075626c696320696e707574730000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6572726f72206d6f6420657870000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6572726f72206563206f7065726174696f6e00000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f696e707574732061726520626967676572207468616e207200000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f77726f6e672070726f6f662073697a65000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f6f70656e696e677320626967676572207468616e2072000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f6572726f722070616972696e67000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6572726f722076657269667900000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6572726f722072616e646f6d2067656e206b7a670000000000000000000000006044820152606481fd5b60058114610a5757610a576106f0565b50565b5f5b81811015610aa4577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000083351115610a9557610a9561080d565b60209290920191600101610a5c565b505050565b610360818114610abb57610abb61086c565b5050565b61018081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610af557610af56108cb565b506101a081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610b2c57610b2c6108cb565b506101c081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610b6357610b636108cb565b506101e081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610b9a57610b9a6108cb565b5061020081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610bd157610bd16108cb565b5061026081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610c0857610c086108cb565b5061030081015f5b6001811015610aa4577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000082351115610c4a57610c4a6108cb565b60209190910190600101610c10565b5f60405161024081016467616d6d6181527f2dc54336c06a06f4cf81d186d61710b54b7cc8a885d62068fa20ef5affcc9b2960208201527f0de6d6ca530719fcbbc72fb363fcfe8e678cc8e1ff97ae510902c38704c155d360408201527f016d52b549f5a97e0d20ffd0a98365c9a7d93e3877552678c0ee5a5584413e0160608201527f0969091657a75b12b7eea04d595cba1e87304cb4dd5cfdc78530707d1309732460808201527f1090a057ba86e7a26bf16afd35cb54435f66d95cfe43f55c5ef02db7209e931c60a08201527f2bf5be16a8b5a734fb51960de6ad22594c7bab0936545a91bfdc56a896deba2260c08201527f14ff07d809a066622eeec2671abfea3c61f1cbb4ed507e1decc4bd943a856e8160e08201527f1d6b52dd76d02b4dcd2708bee7f60d4a9ba11305894ec5374da8eb13d120914e6101008201527f2188d80f62696638d9914aebd8f9c50232936e7a3945a8967b010105b1bef2e16101208201527f25bbd1a7a916c59eb45e823e61d067f014a5d7721b0826ee6029c823f078bf056101408201527f048f55df25aea5672048ff344d6ae33323302e49ba4d8f7f3d3d57e1342a5c2c6101608201527f2438994c3232ec28ebbf2010fdcb6b7426ba5da25ae499d2e091a53c8fd7dfec6101808201527f18ee8d5a878f07a6729ecf3d71944fd4a15f2e903a77ee2303b6ab61f9c5509f6101a08201527f02f4278497f8821e95247cda1733795c328ff1505f8ca4535c35d921641583796101c08201527f07c21121e364b3cabb19d7f3cc18ee406b0f3ded1ac8f779508e692e24aff89d6101e08201527f2158407e9af4cedca94a99a2e2ec6718311d1f86b39f89f466c4835badb09ffb6102008201527f2f0a1d1b0bc53914c138f532c5f5eb08aa154bec4694e77a3a1152aea194ca826102208201527f2fe78306d51211fa7d2ecf1c3ccec2d626525525bae105ed19cff3b218ffd6ec610240820152610260810160208602808883379081019060c0808784375061030501905060208282601b820160025afa905080610f5a57610f5a610989565b5080519250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182066040820152509392505050565b5f60405161024060405101636265746181528360208201526020816024601c840160025afa80610fc257610fc2610989565b5080519250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018206602082015250919050565b5f60405161024060405101606564616c7068618252602082018681526020810190506103208601600160400280828437928301929190910190506040610220870182375060208282601b850160025afa90508061105557611055610989565b50517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181069091529392505050565b60405161024060405101637a657461815283602082015260c0808401604083013760208160e4601c840160025afa806110bf576110bf610989565b50517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019006606091909101525050565b5f60405160608101516101c082015191508561110d81878585611188565b5f92505f91505b8582101561117e577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001853582510992507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018385086020958601959094506001929092019101611114565b5050509392505050565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e5aaf0a66b91f8030da595e7d1c6787b9b45fc54c546729acf1ff05360983096001855f5b86811015611276577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103860882527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f2a734ebb326341efa19b0361d9130cd47b26b7488dc6d26eeccd4f3eb878331a84099250602091909101906001016111d1565b5061128281878961133a565b5060019050855f5b86811015611330577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001868551090982526020820191507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f2a734ebb326341efa19b0361d9130cd47b26b7488dc6d26eeccd4f3eb878331a8409925060010161128a565b5050505050505050565b600183525f805b8381101561138f5781850151828401517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001818309905060208401935080848801525050600181019050611341565b5060208103820191508084019350506113d06020840160027f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001038551612d69565b5f5b8381101561145d5760208503945082517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018651840984527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018184097fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909401939250506001016113d2565b5050505050565b5f60405160608101516101c0820151915061032084015f8061148c8960208501358535611611565b91506114a0896301821df98a0187876114d6565b90507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018082840987089998505050505050505050565b5f61150285857f2a734ebb326341efa19b0361d9130cd47b26b7488dc6d26eeccd4f3eb878331a612d69565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001817f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103840894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e5aaf0a66b91f8030da595e7d1c6787b9b45fc54c546729acf1ff053609820990506115bb867f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff87612d69565b94507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018482099695505050505050565b5f83525f602084015280604084015250806060830152505f6080820153603060818201535f60828201536042608382015360536084820153604260858201536032608682015360326087820153602d608882015360506089820153606c608a820153606f608b820153606e608c820153606b608d820153600b608e8201535f602082608f8460025afa806116a7576116a7610989565b8251600160208501536042602185015360536022850153604260238501536032602485015360326025850153602d602685015360506027850153606c6028850153606f6029850153606e602a850153606b602b850153600b602c850153602084602d8660025afa91508161171d5761171d610989565b8351186020840152600260408401536042604184015360536042840153604260438401536032604484015360326045840153602d604684015360506047840153606c6048840153606f6049840153606e604a840153606b604b840153600b604c84015360208301602081602d8360025afa9150508061179e5761179e610989565b507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017001000000000000000000000000000000008351099050602082015160801c7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018183089392505050565b604051610240604051016101c08201517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103606085015108611890837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff83612d69565b90507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e5aaf0a66b91f8030da595e7d1c6787b9b45fc54c546729acf1ff053609820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018282098451935091507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001905082820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018282099050806080840152505050565b60405161024081016101608201518152610180820151602082015261028083013560408201526102a08301356060820152610220830135608082015261024083013560a08201526102c083013560c08201526102e083013560e082015260608201516101008201526101e08201516101208201526020816101408360025afa806119e7576119e76109e8565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182510690508160408101925061028085013581526102a08501356020820152611a3783836102c0880184612cd0565b6101608401611a4c8484610220890184612cd0565b6101408501611a6084610260890183612d17565b7f1fa4be93b5e7f7e674d5059b63554fab99638b304ed8310e9fa44c281ac9b03b85527f1a01ae7fac6228e39d3cb5a5e71fd31160f3241e79a5f48ffb3737e6c389b7216020860152805160408087019182529095908160608160075afa915081611acd57611acd610989565b60208101915081517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47038252611b0586828586612bc7565b505083604085019450611b228560608801516102808a0184612c5e565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f2a734ebb326341efa19b0361d9130cd47b26b7488dc6d26eeccd4f3eb878331a60608801510995507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018685099350611ba285856102c08a0184612cd0565b611bae85828485612bc7565b50602082810180517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd470381528251865291810151908501527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260408501527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60608501527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60808501527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60a0850152905160c0840152805160e08401527f22f1acbb03c4508760c2430af35865e7cdf9f3eb1224504fdcc3708ddb954a486101008401527f2a344fad01c2ed0ed73142ae1752429eaea515c6f3f6b941103cc21c2308e1cb6101208401527f159f15b842ba9c8449aa3268f981010d4c7142e5193473d80b464e964845c3f86101408401527f0efd30ac7b6f8d0d3ccbc2207587c2acbad1532dc0293f0d034cf8258cd428b36101608401529250610aa490508160405160205f6101808460085afa80611d4b57611d4b61092a565b505f51610200919091015250565b6040516102406040510160208101604082016101e084015180610160860160e08701518152610100870151610180880152610120870151610140880152611da486835f8b0184612cd0565b611db7826101808a016101408a01612d17565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018383099150611dec868360408b0184612cd0565b611dff826101a08a016101408a01612d17565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018383099150611e34868360808b0184612cd0565b611e47826101c08a016101408a01612d17565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183830991507f2dc54336c06a06f4cf81d186d61710b54b7cc8a885d62068fa20ef5affcc9b2986527f0de6d6ca530719fcbbc72fb363fcfe8e678cc8e1ff97ae510902c38704c155d38552611ebf84838884612c89565b611ed2826101e08a016101408a01612d17565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183830991507f016d52b549f5a97e0d20ffd0a98365c9a7d93e3877552678c0ee5a5584413e0186527f0969091657a75b12b7eea04d595cba1e87304cb4dd5cfdc78530707d130973248552611f4a84838884612c89565b611f5d826102008a016101408a01612d17565b61030088017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184840992507f2f0a1d1b0bc53914c138f532c5f5eb08aa154bec4694e77a3a1152aea194ca8287527f2fe78306d51211fa7d2ecf1c3ccec2d626525525bae105ed19cff3b218ffd6ec8652611fda85848985612c89565b611fe983826101408b01612d17565b505050505050505050565b6040516467616d6d616102408201908152606082015161026083015260e08201516102808301526101008201516102a083015260c0836102c08401377f2dc54336c06a06f4cf81d186d61710b54b7cc8a885d62068fa20ef5affcc9b296101408201527f0de6d6ca530719fcbbc72fb363fcfe8e678cc8e1ff97ae510902c38704c155d36101608201527f016d52b549f5a97e0d20ffd0a98365c9a7d93e3877552678c0ee5a5584413e01610180808301919091527f0969091657a75b12b7eea04d595cba1e87304cb4dd5cfdc78530707d130973246101a0808401919091527f2f0a1d1b0bc53914c138f532c5f5eb08aa154bec4694e77a3a1152aea194ca826101c0808501919091527f2fe78306d51211fa7d2ecf1c3ccec2d626525525bae105ed19cff3b218ffd6ec6101e0808601919091526101208601516102008087019190915293870135610220860152918601356102408501528501356102608401528401356102808301528301356102a08201526102c081016103008401602081833750610260840135602091820152601b906102e5906101e085018285850160025afa92505050806121aa576121aa610989565b506101e00180517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019006905250565b604051610240604051017f14ff07d809a066622eeec2671abfea3c61f1cbb4ed507e1decc4bd943a856e8181527f1d6b52dd76d02b4dcd2708bee7f60d4a9ba11305894ec5374da8eb13d120914e6020820152612243604082016101808501358360e08601612c33565b7f2188d80f62696638d9914aebd8f9c50232936e7a3945a8967b010105b1bef2e181527f25bbd1a7a916c59eb45e823e61d067f014a5d7721b0826ee6029c823f078bf0560208201526122a3604082016101a08501358360e08601612c89565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0840135610180850135097f048f55df25aea5672048ff344d6ae33323302e49ba4d8f7f3d3d57e1342a5c2c82527f2438994c3232ec28ebbf2010fdcb6b7426ba5da25ae499d2e091a53c8fd7dfec602083015261232c60408301828460e08701612c89565b507f18ee8d5a878f07a6729ecf3d71944fd4a15f2e903a77ee2303b6ab61f9c5509f81527f02f4278497f8821e95247cda1733795c328ff1505f8ca4535c35d92164158379602082015261238d604082016101c08501358360e08601612c89565b7f07c21121e364b3cabb19d7f3cc18ee406b0f3ded1ac8f779508e692e24aff89d81527f2158407e9af4cedca94a99a2e2ec6718311d1f86b39f89f466c4835badb09ffb60208201526123e8604082018260e0850180612bc7565b610300830161032084015f5b600181101561243457813584526020820135602085015261241e6040850184358660e08901612c89565b60209290920191604091909101906001016123f4565b5050507f1090a057ba86e7a26bf16afd35cb54435f66d95cfe43f55c5ef02db7209e931c81527f2bf5be16a8b5a734fb51960de6ad22594c7bab0936545a91bfdc56a896deba22602082015261249260408201858360e08601612c89565b610220830135815261024083013560208201526124b760408201868360e08601612c89565b61145d8160a0840160e0850180612bc7565b6040516020810151604082015160608301515f8401517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184610260880135097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101e088013586097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610180890135820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000161020089013587097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a08a0135820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000186820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018284097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600580097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001878a0998507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101808c01358a0894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000188860894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160058a0993507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a08c0135850893507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000188850893507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001818a099250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101c08b0135830891507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000187830891507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183850997507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018289097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001908103985085890997507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160808a0151890897506128a288828c6121d9565b50505050505050505050565b6040516002630200000001610240604051016128cf81836060860151612d69565b91506128e48183610140870160a08701612c5e565b6128f781610100860160a0860180612bfd565b612906818360a0860180612c33565b6129188160c0860160a0860180612bfd565b61292f816101c085015160a0860160a08701612c33565b505060c00180517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703905250565b6040515f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160208301516101e08501350990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040830151820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610180840135820890505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160208401516102008601350990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040840151820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0850135820890505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160408501516101c08701350890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182840992507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018184099250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000015f840151830991507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610260850135830991507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0840151830860808401519092507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000190810391508183087f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001036101209390930192909252505050565b8151845260208201516020850152825160408501526020830151606085015260408160808660065afa8061145d5761145d6107ae565b8151845260208201516020850152823560408501526020830135606085015260408160808660065afa8061145d5761145d6107ae565b815184526020820151602085015282604085015260408160608660075afa8061145d5761145d6107ae565b813584526020820135602085015282604085015260408160608660075afa8061145d5761145d6107ae565b815184526020820151602085015282604085015260408460608660075afa815160408601526020820151606086015260408260808760065afa168061145d5761145d6107ae565b813584526020820135602085015282604085015260408460608660075afa815160408601526020820151606086015260408260808760065afa168061145d5761145d6107ae565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001838335097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181835108825250505050565b602083526020808401526020604084015280606084015250806080830152507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160a08201525f60208260c08460055afa80612dc657612dc661074f565b50505190565b949350505050565b5f546040517f41493c6000000000000000000000000000000000000000000000000000000000815230916341493c6091612e199190869086908a908a9060040161333e565b5f6040518083038186803b158015612e2f575f80fd5b505afa158015611330573d5f803e3d5ffd5b3073ffffffffffffffffffffffffffffffffffffffff1663a48fd34b848484604051602001612e7291815260200190565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401612e9f93929190613376565b5f6040518083038186803b158015612eb5575f80fd5b505afa158015612ec7573d5f803e3d5ffd5b50505050505050565b5f8083601f840112612ee0575f80fd5b50813567ffffffffffffffff811115612ef7575f80fd5b602083019150836020828501011115612f0e575f80fd5b9250929050565b5f805f805f60608688031215612f29575f80fd5b85359450602086013567ffffffffffffffff80821115612f47575f80fd5b612f5389838a01612ed0565b90965094506040880135915080821115612f6b575f80fd5b50612f7888828901612ed0565b969995985093965092949392505050565b5f8060208385031215612f9a575f80fd5b823567ffffffffffffffff811115612fb0575f80fd5b612fbc85828601612ed0565b90969095509350505050565b5f805f8060408587031215612fdb575f80fd5b843567ffffffffffffffff80821115612ff2575f80fd5b612ffe88838901612ed0565b90965094506020870135915080821115613016575f80fd5b818701915087601f830112613029575f80fd5b813581811115613037575f80fd5b8860208260051b850101111561304b575f80fd5b95989497505060200194505050565b5f805f806040858703121561306d575f80fd5b843567ffffffffffffffff80821115613084575f80fd5b61309088838901612ed0565b909650945060208701359150808211156130a8575f80fd5b506130b587828801612ed0565b95989497509550505050565b5f805f604084860312156130d3575f80fd5b833567ffffffffffffffff8111156130e9575f80fd5b6130f586828701612ed0565b909790965060209590950135949350505050565b5f81518084525f5b8181101561312d57602081850181015186830182015201613111565b505f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f61317c6020830184613109565b9392505050565b5f8085851115613191575f80fd5b8386111561319d575f80fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156131ea5780818660040360031b1b83161692505b505092915050565b8035602083101561059f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b604081525f6132b560408301858761325b565b8281036020848101919091528451808352858201928201905f5b818110156132eb578451835293830193918301916001016132cf565b509098975050505050505050565b5f60208284031215613309575f80fd5b8151801515811461317c575f80fd5b818382375f9101908152919050565b5f60208284031215613337575f80fd5b5051919050565b858152606060208201525f61335760608301868861325b565b828103604084015261336a81858761325b565b98975050505050505050565b604081525f61338960408301858761325b565b828103602084015261339b8185613109565b969550505050505056fea164736f6c6343000818000a diff --git a/bindings/bindings/rollup.go b/bindings/bindings/rollup.go index 9466d2be0..a3e5d0a88 100644 --- a/bindings/bindings/rollup.go +++ b/bindings/bindings/rollup.go @@ -50,7 +50,7 @@ type IRollupBatchSignatureInput struct { // RollupMetaData contains all meta data concerning the Rollup contract. var RollupMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_chainID\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ErrZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"batchIndex\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"winner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"string\",\"name\":\"res\",\"type\":\"string\"}],\"name\":\"ChallengeRes\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ChallengeRewardClaim\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"batchIndex\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"challengeDeposit\",\"type\":\"uint256\"}],\"name\":\"ChallengeState\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"batchIndex\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"batchHash\",\"type\":\"bytes32\"}],\"name\":\"CommitBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"batchIndex\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"batchHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"withdrawRoot\",\"type\":\"bytes32\"}],\"name\":\"FinalizeBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ProveRemainingClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"batchIndex\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"batchHash\",\"type\":\"bytes32\"}],\"name\":\"RevertBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"status\",\"type\":\"bool\"}],\"name\":\"UpdateChallenger\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldPeriod\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newPeriod\",\"type\":\"uint256\"}],\"name\":\"UpdateFinalizationPeriodSeconds\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldPercent\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newPercent\",\"type\":\"uint256\"}],\"name\":\"UpdateProofRewardPercent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldWindow\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newWindow\",\"type\":\"uint256\"}],\"name\":\"UpdateProofWindow\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldPeriod\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newPeriod\",\"type\":\"uint256\"}],\"name\":\"UpdateRollupDelayPeriod\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldVerifier\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newVerifier\",\"type\":\"address\"}],\"name\":\"UpdateVerifier\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"LAYER_2_CHAIN_ID\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"__maxNumTxInChunk\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"addChallenger\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"batchIndex\",\"type\":\"uint256\"}],\"name\":\"batchBlobVersionedHashes\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blobVersionedHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"batchChallengeReward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"batchChallenged\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"batchIndex\",\"type\":\"uint256\"}],\"name\":\"batchChallengedSuccess\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"batchIndex\",\"type\":\"uint256\"}],\"name\":\"batchDataStore\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"originTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"finalizeTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signedSequencersBitmap\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"batchIndex\",\"type\":\"uint256\"}],\"name\":\"batchExist\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"batchIndex\",\"type\":\"uint256\"}],\"name\":\"batchInChallenge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"batchIndex\",\"type\":\"uint256\"}],\"name\":\"batchInsideChallengeWindow\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"batchIndex\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"_batchHash\",\"type\":\"bytes32\"}],\"name\":\"challengeState\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"batchIndex\",\"type\":\"uint256\"}],\"name\":\"challenges\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"batchIndex\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"challenger\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"challengeDeposit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"challengeSuccess\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"finished\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"claimProveRemaining\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"}],\"name\":\"claimReward\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"parentBatchHeader\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"lastBlockNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint16\",\"name\":\"numL1Messages\",\"type\":\"uint16\"},{\"internalType\":\"bytes32\",\"name\":\"prevStateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"postStateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"withdrawalRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structIRollup.BatchDataInput\",\"name\":\"batchDataInput\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"signedSequencersBitmap\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"sequencerSets\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structIRollup.BatchSignatureInput\",\"name\":\"batchSignatureInput\",\"type\":\"tuple\"}],\"name\":\"commitBatch\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"parentBatchHeader\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"lastBlockNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint16\",\"name\":\"numL1Messages\",\"type\":\"uint16\"},{\"internalType\":\"bytes32\",\"name\":\"prevStateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"postStateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"withdrawalRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structIRollup.BatchDataInput\",\"name\":\"batchDataInput\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"signedSequencersBitmap\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"sequencerSets\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structIRollup.BatchSignatureInput\",\"name\":\"batchSignatureInput\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_batchHeader\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_batchProof\",\"type\":\"bytes\"}],\"name\":\"commitBatchWithProof\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"parentBatchHeader\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"lastBlockNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint16\",\"name\":\"numL1Messages\",\"type\":\"uint16\"},{\"internalType\":\"bytes32\",\"name\":\"prevStateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"postStateRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"withdrawalRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structIRollup.BatchDataInput\",\"name\":\"batchDataInput\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"signedSequencersBitmap\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"sequencerSets\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structIRollup.BatchSignatureInput\",\"name\":\"batchSignatureInput\",\"type\":\"tuple\"}],\"name\":\"commitState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"batchIndex\",\"type\":\"uint256\"}],\"name\":\"committedBatches\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"batchHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"batchIndex\",\"type\":\"uint256\"}],\"name\":\"committedStateRoots\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"finalizationPeriodSeconds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_batchHeader\",\"type\":\"bytes\"}],\"name\":\"finalizeBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"batchIndex\",\"type\":\"uint256\"}],\"name\":\"finalizedStateRoots\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"stateRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_batchHeader\",\"type\":\"bytes\"}],\"name\":\"importGenesisBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"inChallenge\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_l1StakingContract\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_messageQueue\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_verifier\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_finalizationPeriodSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_proofWindow\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_proofRewardPercent\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_prevStateRoot\",\"type\":\"bytes32\"}],\"name\":\"initialize2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_rollupDelayPeriod\",\"type\":\"uint256\"}],\"name\":\"initialize3\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_batchIndex\",\"type\":\"uint256\"}],\"name\":\"isBatchFinalized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"challengerAddress\",\"type\":\"address\"}],\"name\":\"isChallenger\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isChallenger\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1StakingContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastCommittedBatchIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastFinalizedBatchIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"messageQueue\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"paused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proofRewardPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proofWindow\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_batchHeader\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_batchProof\",\"type\":\"bytes\"}],\"name\":\"proveCommittedBatchState\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proveRemaining\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_batchHeader\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"_batchProof\",\"type\":\"bytes\"}],\"name\":\"proveState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"removeChallenger\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_batchHeader\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_count\",\"type\":\"uint256\"}],\"name\":\"revertBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revertReqIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rollupDelayPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_status\",\"type\":\"bool\"}],\"name\":\"setPause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_newPeriod\",\"type\":\"uint256\"}],\"name\":\"updateFinalizePeriodSeconds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_newWindow\",\"type\":\"uint256\"}],\"name\":\"updateProofWindow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_newProofRewardPercent\",\"type\":\"uint256\"}],\"name\":\"updateRewardPercentage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_newPeriod\",\"type\":\"uint256\"}],\"name\":\"updateRollupDelayPeriod\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newVerifier\",\"type\":\"address\"}],\"name\":\"updateVerifier\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"verifier\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"withdrawalRoot\",\"type\":\"bytes32\"}],\"name\":\"withdrawalRoots\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"exist\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x60a060405234801562000010575f80fd5b50604051620056a1380380620056a183398101604081905262000033916200010f565b6001600160401b0381166080526200004a62000051565b506200013e565b5f54610100900460ff1615620000bd5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116146200010d575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b5f6020828403121562000120575f80fd5b81516001600160401b038116811462000137575f80fd5b9392505050565b6080516155436200015e5f395f81816106a2015261431101526155435ff3fe608060405260043610610353575f3560e01c8063728cdbca116101bd578063b8d0a1b0116100f2578063d8dc99d211610092578063dff7827e1161006d578063dff7827e14610ac4578063e3fff1dd14610ad9578063f2fde38b14610af8578063fb1e8b0414610b17575f80fd5b8063d8dc99d214610a71578063ddd8a3dc14610a86578063de8b303514610aa5575f80fd5b8063cd4edc69116100cd578063cd4edc6914610a0b578063ce5db8d614610a1e578063cf9a674514610a33578063d279c19114610a52575f80fd5b8063b8d0a1b0146109ae578063bedb86fb146109cd578063c5553892146109ec575f80fd5b8063a479265d1161015d578063b31a77d311610138578063b31a77d31461093c578063b348442514610951578063b35dac4e14610970578063b3e0a5091461098f575f80fd5b8063a479265d146108dd578063a4f209b0146108f2578063abc8d68d14610911575f80fd5b80638f1d3776116101985780638f1d3776146107af578063910129d41461085f57806397fc007c14610890578063a415d8dc146108af575f80fd5b8063728cdbca1461075a57806388b1ea09146107795780638da5cb5b14610792575f80fd5b80632a213ba1116102935780635c975abb11610233578063612672901161020e57806361267290146106dd57806368589dfa146106fc5780636c578c1d14610727578063715018a614610746575f80fd5b80635c975abb1461061a5780635ef7a94a146106315780635f77cf1d14610691575f80fd5b80633e001b661161026e5780633e001b66146105b4578063428868b5146105c95780634e8f1d67146105dc57806357e0af6c146105fb575f80fd5b80632a213ba1146105335780632b7ac3f31461055e5780633b70c18a14610595575f80fd5b806313361101116102fe5780631e8825be116102d95780631e8825be1461049f57806321e2f9e0146104be5780632362f03e146104dd5780632571098d14610508575f80fd5b8063133611011461043b57806318463fb01461045a57806318af3b2b1461046f575f80fd5b806310d445831161032e57806310d44583146103e5578063116a1f4214610404578063121dcd5014610426575f80fd5b806304d772151461035e578063059def61146103a15780630ceb6780146103c4575f80fd5b3661035a57005b5f80fd5b348015610369575f80fd5b5061038c610378366004614d1c565b60a36020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156103ac575f80fd5b506103b6609d5481565b604051908152602001610398565b3480156103cf575f80fd5b506103e36103de366004614d4e565b610b2c565b005b3480156103f0575f80fd5b506103e36103ff366004614dac565b610bfe565b34801561040f575f80fd5b5061038c61041e366004614d1c565b609d54101590565b348015610431575f80fd5b506103b6609e5481565b348015610446575f80fd5b506103e3610455366004614df4565b610f3a565b348015610465575f80fd5b506103b660a75481565b34801561047a575f80fd5b5061038c610489366004614d1c565b5f90815260a26020526040902060010154421090565b3480156104aa575f80fd5b506103e36104b9366004614e59565b611434565b3480156104c9575f80fd5b5061038c6104d8366004614d1c565b61181f565b3480156104e8575f80fd5b506103b66104f7366004614d1c565b60a16020525f908152604090205481565b348015610513575f80fd5b506103b6610522366004614d1c565b60a06020525f908152604090205481565b34801561053e575f80fd5b506103b661054d366004614d1c565b60ad6020525f908152604090205481565b348015610569575f80fd5b50609c5461057d906001600160a01b031681565b6040516001600160a01b039091168152602001610398565b3480156105a0575f80fd5b50609b5461057d906001600160a01b031681565b3480156105bf575f80fd5b506103b660aa5481565b6103e36105d7366004614e59565b61184d565b3480156105e7575f80fd5b506103e36105f6366004614eb9565b611c00565b348015610606575f80fd5b506103e3610615366004614d1c565b611fd4565b348015610625575f80fd5b5060655460ff1661038c565b34801561063c575f80fd5b5061067161064b366004614d1c565b60a26020525f908152604090208054600182015460028301546003909301549192909184565b604080519485526020850193909352918301526060820152608001610398565b34801561069c575f80fd5b506106c47f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff9091168152602001610398565b3480156106e8575f80fd5b506103e36106f7366004614d1c565b61207f565b348015610707575f80fd5b506103b6610716366004614d1c565b60ab6020525f908152604090205481565b348015610732575f80fd5b506103e3610741366004614d4e565b61225a565b348015610751575f80fd5b506103e3612317565b348015610765575f80fd5b506103e3610774366004614f6a565b61232a565b348015610784575f80fd5b5060a65461038c9060ff1681565b34801561079d575f80fd5b506033546001600160a01b031661057d565b3480156107ba575f80fd5b5061081b6107c9366004614d1c565b60a46020525f9081526040902080546001820154600283015460039093015467ffffffffffffffff831693680100000000000000009093046001600160a01b0316929060ff8082169161010090041686565b6040805167ffffffffffffffff90971687526001600160a01b03909516602087015293850192909252606084015215156080830152151560a082015260c001610398565b34801561086a575f80fd5b5061038c610879366004614d1c565b5f90815260a4602052604090206003015460ff1690565b34801561089b575f80fd5b506103e36108aa366004614d4e565b612633565b3480156108ba575f80fd5b5061038c6108c9366004614d4e565b609f6020525f908152604090205460ff1681565b3480156108e8575f80fd5b506103b660995481565b3480156108fd575f80fd5b506103e361090c366004614d1c565b612716565b34801561091c575f80fd5b506103b661092b366004614d4e565b60a56020525f908152604090205481565b348015610947575f80fd5b506103b660a85481565b34801561095c575f80fd5b506103e361096b366004614fc5565b6127c6565b34801561097b575f80fd5b506103e361098a366004614d4e565b612aca565b34801561099a575f80fd5b506103e36109a9366004614df4565b612b23565b3480156109b9575f80fd5b506103e36109c8366004614fc5565b612e80565b3480156109d8575f80fd5b506103e36109e7366004615039565b612f09565b3480156109f7575f80fd5b506103e3610a06366004614d1c565b613047565b6103e3610a1936600461506b565b6130ea565b348015610a29575f80fd5b506103b660985481565b348015610a3e575f80fd5b506103e3610a4d366004614d1c565b61367c565b348015610a5d575f80fd5b506103e3610a6c366004614d4e565b6137eb565b348015610a7c575f80fd5b506103b660ac5481565b348015610a91575f80fd5b5060975461057d906001600160a01b031681565b348015610ab0575f80fd5b5061038c610abf366004614d1c565b6138aa565b348015610acf575f80fd5b506103b6609a5481565b348015610ae4575f80fd5b506103e3610af3366004614d1c565b6138f4565b348015610b03575f80fd5b506103e3610b12366004614d4e565b613997565b348015610b22575f80fd5b506103b660a95481565b610b34613a24565b6001600160a01b0381165f908152609f602052604090205460ff1615610ba15760405162461bcd60e51b815260206004820152601f60248201527f6163636f756e7420697320616c72656164792061206368616c6c656e6765720060448201526064015b60405180910390fd5b6001600160a01b0381165f818152609f6020908152604091829020805460ff1916600190811790915591519182527f7feb653c7b1f0d23daeed494225b3f28851cdc8973fcc653866d9b6e205fc00991015b60405180910390a250565b610c06613a24565b5f8111610c555760405162461bcd60e51b815260206004820152601560248201527f636f756e74206d757374206265206e6f6e7a65726f00000000000000000000006044820152606401610b98565b5f80610c618585613a7e565b915091505f610c74836001015160c01c90565b5f81815260a160205260409020549091508214610cd35760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b5f60a181610ce187856150c0565b81526020019081526020015f205414610d615760405162461bcd60e51b8152602060048201526024808201527f726576657274696e67206d7573742073746172742066726f6d2074686520656e60448201527f64696e67000000000000000000000000000000000000000000000000000000006064820152608401610b98565b609d548111610dd85760405162461bcd60e51b815260206004820152602160248201527f63616e206f6e6c792072657665727420756e46696e616c697a6564206261746360448201527f68000000000000000000000000000000000000000000000000000000000000006064820152608401610b98565b610de36001826150d3565b609e555b8315610f3257604051829082907ecae2739091badfd91c373f0a16cede691e0cd25bb80cff77dd5caeb4710146905f90a35f81815260a16020526040812055610e2f816138aa565b15610e8a575f81815260a460209081526040808320600181015490546801000000000000000090046001600160a01b0316845260a59092528220805491929091610e7a9084906150c0565b909155505060a6805460ff191690555b5f81815260a46020526040812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181018290556002810191909155600301805461ffff1916905560a85415801590610eea575060a85481145b15610ef4575f60a8555b6001015f81815260a160205260409020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90940193915081610de7575b505050505050565b60a85415610f8a5760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b610f92613b17565b5f80610f9e8484613a7e565b915091505f610fb1836001015160c01c90565b5f81815260a1602052604090205490915082146110105760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b6110198161181f565b6110655760405162461bcd60e51b815260206004820152600f60248201527f6261746368206e6f7420657869737400000000000000000000000000000000006044820152606401610b98565b61106e816138aa565b156110bb5760405162461bcd60e51b815260206004820152601260248201527f626174636820696e206368616c6c656e676500000000000000000000000000006044820152606401610b98565b5f81815260a4602052604090206003015460ff161561111c5760405162461bcd60e51b815260206004820152601660248201527f62617463682073686f756c6420626520726576657274000000000000000000006044820152606401610b98565b5f81815260a2602052604090206001015442101561117c5760405162461bcd60e51b815260206004820152601960248201527f626174636820696e206368616c6c656e67652077696e646f77000000000000006044820152606401610b98565b605983015160a05f61118f6001856150d3565b81526020019081526020015f2054146111ea5760405162461bcd60e51b815260206004820152601d60248201527f696e636f72726563742070726576696f757320737461746520726f6f740000006044820152606401610b98565b5f81815260a06020526040902054156112455760405162461bcd60e51b815260206004820152601660248201527f626174636820616c7265616479207665726966696564000000000000000000006044820152606401610b98565b80609d54600101146112995760405162461bcd60e51b815260206004820152601560248201527f696e636f727265637420626174636820696e64657800000000000000000000006044820152606401610b98565b609d819055600160a35f6112ae866099015190565b815260208101919091526040015f20805460ff191691151591909117905560798301515f82815260a060205260409020556112fd6112f0846011015160c01c90565b600985015160c01c613b6a565b60a25f61130b6001846150d3565b815260208101919091526040015f908120818155600180820183905560028201839055600390910182905560ab919061134490846150d3565b81526020019081526020015f205f905560ad5f60018361136491906150d3565b81526020019081526020015f205f905560a45f60018361138491906150d3565b815260208082019290925260409081015f90812080547fffffffff000000000000000000000000000000000000000000000000000000001681556001810182905560028101829055600301805461ffff1916905583815260a1909252902054817f26ba82f907317eedc97d0cbef23de76a43dd6edb563bdb6e9407645b950a7a2d611410866079015190565b60998701516040805192835260208301919091520160405180910390a35050505050565b6097546001600160a01b03166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156114a0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114c491906150e6565b6115105760405162461bcd60e51b815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610b98565b60a854156115605760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b611568613b17565b5f49156115b75760405162461bcd60e51b815260206004820152601f60248201527f636f6d6d69745374617465206d757374206e6f7420636172727920626c6f62006044820152606401610b98565b5f6115cd6115c86020850185615101565b613a7e565b5090505f6115df826001015160c01c90565b6115ea9060016150c0565b5f81815260ad602052604090205490915061166d5760405162461bcd60e51b815260206004820152602260248201527f6e6f2073746f72656420626c6f62206861736820666f7220746869732062617460448201527f63680000000000000000000000000000000000000000000000000000000000006064820152608401610b98565b60ac54609b54604080517fb59b1a7800000000000000000000000000000000000000000000000000000000815290514293926001600160a01b03169163b59b1a789160048083019260209291908290030181865afa1580156116d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116f59190615162565b6116ff91906150c0565b1015611767575f6117166080860160608701615179565b61ffff16116117675760405162461bcd60e51b815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610b98565b6097545f906001600160a01b031663d096c3c6336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156117d5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117f99190615162565b905061181885858360ad5f8781526020019081526020015f2054613c27565b5050505050565b5f81815260a260205260408120541580159061184757505f82815260a1602052604090205415155b92915050565b6097546001600160a01b03166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156118b9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118dd91906150e6565b6119295760405162461bcd60e51b815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610b98565b60a854156119795760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b611981613b17565b5f6119926115c86020850185615101565b5090505f6119a4826001015160c01c90565b6119af9060016150c0565b5f81815260ad602052604090205490915015611a335760405162461bcd60e51b815260206004820152602860248201527f636f6d6d69744261746368207265717569726573206e6f2073746f726564206260448201527f6c6f6220686173680000000000000000000000000000000000000000000000006064820152608401610b98565b60ac54609b54604080517fb59b1a7800000000000000000000000000000000000000000000000000000000815290514293926001600160a01b03169163b59b1a789160048083019260209291908290030181865afa158015611a97573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611abb9190615162565b611ac591906150c0565b1015611b2d575f611adc6080860160608701615179565b61ffff1611611b2d5760405162461bcd60e51b815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610b98565b6097545f906001600160a01b031663d096c3c6336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611b9b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bbf9190615162565b90505f804915611bd0575f49611bf2565b7f010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c4440145b9050610f3286868484613c27565b60a85415611c505760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b611c58613b17565b60ac54609e545f90815260a2602052604081205490914291611c7a91906150c0565b1090505f4260ac54609b5f9054906101000a90046001600160a01b03166001600160a01b031663b59b1a786040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cd2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cf69190615162565b611d0091906150c0565b10905081158015611d0e5750805b15611d75575f611d2460808a0160608b01615179565b61ffff1611611d755760405162461bcd60e51b815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610b98565b8180611d7e5750805b611dca5760405162461bcd60e51b815260206004820152600e60248201527f696e76616c69642074696d696e670000000000000000000000000000000000006044820152606401610b98565b5f611ddb6115c860208b018b615101565b5090505f611ded826001015160c01c90565b611df89060016150c0565b5f81815260ad60205260408120549192509015611e98575f4915611e845760405162461bcd60e51b815260206004820152602f60248201527f6d757374206e6f7420636172727920626c6f62207768656e207573696e67207360448201527f746f72656420626c6f62206861736800000000000000000000000000000000006064820152608401610b98565b505f81815260ad6020526040902054611ecb565b5f4915611ea6575f49611ec8565b7f010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c4440145b90505b611ed78b8b5f84613c27565b5f80611ee38b8b613a7e565b915091505f611ef6836001015160c01c90565b905080609e5414611f495760405162461bcd60e51b815260206004820152601660248201527f696e636f727265637420626174636820686561646572000000000000000000006044820152606401610b98565b5f81815260a160205260409020548214611fa55760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b5f81815260a26020526040902042600190910155611fc4838b8b6142a2565b5050505050505050505050505050565b611fdc613a24565b5f81118015611fed57506099548114155b6120395760405162461bcd60e51b815260206004820152601860248201527f696e76616c6964206e65772070726f6f662077696e646f7700000000000000006044820152606401610b98565b609980549082905560408051828152602081018490527f1e3a2094feb4b696dd3d7caea38ad2f41dbdcac3fa3943c7a693aff8a64b0a6191015b60405180910390a15050565b5f54600290610100900460ff1615801561209f57505f5460ff8083169116105b6121115760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610b98565b5f805461ffff191660ff83161761010017905561212f5f5460ff1690565b60ff166002146121815760405162461bcd60e51b815260206004820152601660248201527f6d757374206861766520696e697469616c697a656421000000000000000000006044820152606401610b98565b816121f45760405162461bcd60e51b815260206004820152602760248201527f63616e206e6f742073657420737461746520726f6f742077697468206279746560448201527f73333228302921000000000000000000000000000000000000000000000000006064820152608401610b98565b609e545f90815260ab602052604090205461221d57609e545f90815260ab602052604090208290555b5f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602001612073565b612262613a24565b6001600160a01b0381165f908152609f602052604090205460ff166122c95760405162461bcd60e51b815260206004820152601b60248201527f6163636f756e74206973206e6f742061206368616c6c656e67657200000000006044820152606401610b98565b6001600160a01b0381165f818152609f60209081526040808320805460ff19169055519182527f7feb653c7b1f0d23daeed494225b3f28851cdc8973fcc653866d9b6e205fc0099101610bf3565b61231f613a24565b6123285f614455565b565b5f54610100900460ff161580801561234857505f54600160ff909116105b806123615750303b15801561236157505f5460ff166001145b6123d35760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610b98565b5f805460ff1916600117905580156123f4575f805461ff0019166101001790555b6001600160a01b038616158061241157506001600160a01b038516155b15612448576040517fecc6fdf000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03871661249e5760405162461bcd60e51b815260206004820152601b60248201527f696e76616c6964206c31207374616b696e6720636f6e747261637400000000006044820152606401610b98565b6124a66144be565b6124ae614542565b609780546001600160a01b03808a167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255609b8054898416908316179055609c805492881692909116821790556098859055609984905560a98390556040515f907f728af3d16a5760405e27a082c98ab272e9f0a1d02f0085d41532a26093aedd96908290a3604080515f8152602081018690527fa577f4223f91f74e2dad65bbb8c30807587ae95d0d34288057bb3ec0d398a437910160405180910390a1604080515f8152602081018590527f1e3a2094feb4b696dd3d7caea38ad2f41dbdcac3fa3943c7a693aff8a64b0a61910160405180910390a1604080515f8152602081018490527ffb81bce17f015797e11949d3c332e2bf9453faf68f728447426803138f2b0223910160405180910390a1801561262a575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b61263b613a24565b6001600160a01b038116158015906126615750609c546001600160a01b03828116911614155b6126ad5760405162461bcd60e51b815260206004820152601460248201527f696e76616c6964206e65772076657269666965720000000000000000000000006044820152606401610b98565b609c80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f728af3d16a5760405e27a082c98ab272e9f0a1d02f0085d41532a26093aedd96905f90a35050565b61271e613a24565b5f8111801561272e575060648111155b801561273c575060a9548114155b6127885760405162461bcd60e51b815260206004820152601f60248201527f696e76616c69642070726f6f66207265776172642070657263656e74616765006044820152606401610b98565b60a980549082905560408051828152602081018490527ffb81bce17f015797e11949d3c332e2bf9453faf68f728447426803138f2b02239101612073565b60a854156128165760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b61281e613b17565b6097546001600160a01b03166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561288a573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128ae91906150e6565b6128fa5760405162461bcd60e51b815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610b98565b5f806129068686613a7e565b915091505f612919836001015160c01c90565b5f81815260a1602052604090205490915082146129785760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b612981816138aa565b6129cd5760405162461bcd60e51b815260206004820152601260248201527f626174636820696e206368616c6c656e676500000000000000000000000000006044820152606401610b98565b5f81815260a46020526040902060038101805461ff00191661010017905560a6805460ff191690556099546002909101544291612a09916150c0565b11612a7f575f81815260a4602090815260408083206003908101805460ff1916600117905560a2835292819020909201548251808401909352600783527f54696d656f75740000000000000000000000000000000000000000000000000091830191909152612a7a918391906145c6565b61262a565b612a8a8386866142a2565b61262a81336040518060400160405280600d81526020017f50726f6f66207375636365737300000000000000000000000000000000000000815250614722565b612ad2613a24565b60aa80545f909155612ae482826147ee565b604080516001600160a01b0384168152602081018390527fb1b2058a6969e2d25e47bcaebe8ae21c29a23b2752429315b75e2f4f285f3d879101612073565b612b2b613a24565b5f805260a06020527fb84a74ec6ef4d0e83b6006dfaa014ab4026f9f3b97d186e604d29998a4e808ea5415612ba25760405162461bcd60e51b815260206004820152601660248201527f67656e6573697320626174636820696d706f72746564000000000000000000006044820152606401610b98565b5f80612bae8484613a7e565b915091505f612bc1836001015160c01c90565b90508015612c115760405162461bcd60e51b815260206004820152601360248201527f696e76616c696420626174636820696e646578000000000000000000000000006044820152606401610b98565b5f612c1d846079015190565b905080612c6c5760405162461bcd60e51b815260206004820152600f60248201527f7a65726f20737461746520726f6f7400000000000000000000000000000000006044820152606401610b98565b600984015160c01c15612cc15760405162461bcd60e51b815260206004820152601d60248201527f6c31206d65737361676520706f707065642073686f756c6420626520300000006044820152606401610b98565b5f612ccd856019015190565b03612d1a5760405162461bcd60e51b815260206004820152600e60248201527f7a65726f206461746120686173680000000000000000000000000000000000006044820152606401610b98565b7f010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014612d46856039015190565b14612d935760405162461bcd60e51b815260206004820152601660248201527f696e76616c69642076657273696f6e65642068617368000000000000000000006044820152606401610b98565b5f82815260a1602090815260408083208690558051608081018252428082528184019081528183018581526060830186815288875260a28652848720935184559151600184015551600283015551600390910155603987015160ad83528184205560ab825280832084905560a0909152808220839055609e849055609d84905551849184917f2c32d4ae151744d0bf0b9464a3e897a1d17ed2f1af71f7c9a75f12ce0d28238f9190a3604080518281525f6020820152849184917f26ba82f907317eedc97d0cbef23de76a43dd6edb563bdb6e9407645b950a7a2d910160405180910390a3505050505050565b5f80612e8c8686613a7e565b915091505f612e9f836001015160c01c90565b5f81815260a160205260409020549091508214612efe5760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b61262a8386866142a2565b612f11613a24565b801561301557612f1f614899565b60a65460ff1615612fd45760a7545f90815260a460209081526040808320600181015490546801000000000000000090046001600160a01b0316845260a59092528220805491929091612f739084906150c0565b909155505060a7545f90815260a46020526040812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181018290556002810191909155600301805461ffff1916905560a6805460ff191690555b7f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258335b6040516001600160a01b03909116815260200160405180910390a150565b61301d6148f3565b7f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33612ff7565b50565b61304f613a24565b5f81118015613060575060ac548114155b6130ac5760405162461bcd60e51b815260206004820152601f60248201527f696e76616c6964206e657720726f6c6c75702064656c617920706572696f64006044820152606401610b98565b60ac80549082905560408051828152602081018490527f624e47dc9fb8f8cfeaf4ead4710277cc1757136cfa885e465514cf6d510f0ad19101612073565b335f908152609f602052604090205460ff166131485760405162461bcd60e51b815260206004820152601760248201527f6f6e6c79206368616c6c656e67657220616c6c6f7765640000000000000000006044820152606401610b98565b60a854156131985760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b6131a0613b17565b60a65460ff16156131f35760405162461bcd60e51b815260206004820152601460248201527f616c726561647920696e206368616c6c656e67650000000000000000000000006044820152606401610b98565b8167ffffffffffffffff16609d541061324e5760405162461bcd60e51b815260206004820152601760248201527f626174636820616c72656164792066696e616c697a65640000000000000000006044820152606401610b98565b67ffffffffffffffff82165f90815260a1602052604090205481146132b55760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b6132c88267ffffffffffffffff1661181f565b6133145760405162461bcd60e51b815260206004820152600f60248201527f6261746368206e6f7420657869737400000000000000000000000000000000006044820152606401610b98565b67ffffffffffffffff82165f90815260a460205260409020546801000000000000000090046001600160a01b03161561338f5760405162461bcd60e51b815260206004820152601860248201527f626174636820616c7265616479206368616c6c656e67656400000000000000006044820152606401610b98565b67ffffffffffffffff82165f90815260a26020526040902060010154421061341f5760405162461bcd60e51b815260206004820152603360248201527f63616e6e6f74206368616c6c656e6765206261746368206f757473696465207460448201527f6865206368616c6c656e67652077696e646f77000000000000000000000000006064820152608401610b98565b60975f9054906101000a90046001600160a01b03166001600160a01b0316630d13fd7b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561346f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134939190615162565b3410156134e25760405162461bcd60e51b815260206004820152601260248201527f696e73756666696369656e742076616c756500000000000000000000000000006044820152606401610b98565b67ffffffffffffffff82811660a78190556040805160c0810182528281523360208083018281523484860190815242606086019081525f6080870181815260a0880182815299825260a4909552969096209451855492516001600160a01b031668010000000000000000027fffffffff000000000000000000000000000000000000000000000000000000009093169816979097171783559451600183015591516002820155925160039093018054925115156101000261ff00199415159490941661ffff19909316929092179290921790556001600160a01b03168267ffffffffffffffff167f3a6ea19df25b49e7624e313ce7c1ab23984238e93727260db56a81735b1b9976346040516135fa91815260200190565b60405180910390a35f609d54600161361291906150c0565b90505b609e54811161366a578267ffffffffffffffff168114613658576099545f82815260a26020526040812060010180549091906136529084906150c0565b90915550505b806136628161519a565b915050613615565b505060a6805460ff1916600117905550565b5f54600390610100900460ff1615801561369c57505f5460ff8083169116105b61370e5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610b98565b5f805461ffff191660ff8316176101001781558290036137705760405162461bcd60e51b815260206004820152601b60248201527f696e76616c696420726f6c6c75702064656c617920706572696f6400000000006044820152606401610b98565b60ac829055604080515f8152602081018490527f624e47dc9fb8f8cfeaf4ead4710277cc1757136cfa885e465514cf6d510f0ad1910160405180910390a15f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602001612073565b335f90815260a560205260408120549081900361384a5760405162461bcd60e51b815260206004820152601c60248201527f696e76616c69642062617463684368616c6c656e6765526577617264000000006044820152606401610b98565b335f90815260a5602052604081205561386382826147ee565b816001600160a01b03167f9c25fa83f414ed363c8d39c98fb3e17567b3431cede71eb062c49d2a63ce247a8260405161389e91815260200190565b60405180910390a25050565b5f81815260a460205260408120546801000000000000000090046001600160a01b0316158015906118475750505f90815260a46020526040902060030154610100900460ff161590565b6138fc613a24565b5f8111801561390d57506098548114155b6139595760405162461bcd60e51b815260206004820152601b60248201527f696e76616c6964206e65772066696e616c697a6520706572696f6400000000006044820152606401610b98565b609880549082905560408051828152602081018490527fa577f4223f91f74e2dad65bbb8c30807587ae95d0d34288057bb3ec0d398a4379101612073565b61399f613a24565b6001600160a01b038116613a1b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610b98565b61304481614455565b6033546001600160a01b031633146123285760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b98565b5f805f613a8b858561492c565b90505f8160ff165f03613aac57613aa2868661499c565b9094509050613b09565b8160ff16600103613ac157613aa28686614a05565b60405162461bcd60e51b815260206004820152601960248201527f556e737570706f727465642062617463682076657273696f6e000000000000006044820152606401610b98565b808420925050509250929050565b60655460ff16156123285760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610b98565b805f03613b75575050565b8082035f5b82811015613c2157610100818403811115613b9457508083035b609b546040517f3c7f528300000000000000000000000000000000000000000000000000000000815260048101859052602481018390526001600160a01b0390911690633c7f5283906044015f604051808303815f87803b158015613bf7575f80fd5b505af1158015613c09573d5f803e3d5ffd5b50505050610100830192505061010081019050613b7a565b50505050565b613c3460208501856151d1565b60ff161580613c525750613c4b60208501856151d1565b60ff166001145b613c9e5760405162461bcd60e51b815260206004820152600f60248201527f696e76616c69642076657273696f6e00000000000000000000000000000000006044820152606401610b98565b6080840135613cef5760405162461bcd60e51b815260206004820152601b60248201527f70726576696f757320737461746520726f6f74206973207a65726f00000000006044820152606401610b98565b60a0840135613d405760405162461bcd60e51b815260206004820152601660248201527f6e657720737461746520726f6f74206973207a65726f000000000000000000006044820152606401610b98565b5f80613d526115c86020880188615101565b915091505f613d65836001015160c01c90565b90505f60a181613d768460016150c0565b81526020019081526020015f205414613dd15760405162461bcd60e51b815260206004820152601760248201527f626174636820616c726561647920636f6d6d69747465640000000000000000006044820152606401610b98565b609e548114613e225760405162461bcd60e51b815260206004820152601560248201527f696e636f727265637420626174636820696e64657800000000000000000000006044820152606401610b98565b5f81815260a160205260409020548214613e7e5760405162461bcd60e51b815260206004820152601b60248201527f696e636f727265637420706172656e74206261746368206861736800000000006044820152606401610b98565b5f81815260ab6020526040902054608088013514613ede5760405162461bcd60e51b815260206004820152601d60248201527f696e636f72726563742070726576696f757320737461746520726f6f740000006044820152606401610b98565b5f613eed846011015160c01c90565b90505f613f19613f0360608b0160408c016151f1565b613f1360808c0160608d01615179565b84614a58565b9050613f2b60808a0160608b01615179565b6001939093019261ffff1691909101908560f9613f4b60208c018c6151d1565b60ff16600103613f5a57506101015b604080518281019091529650613f7f87613f7760208e018e6151d1565b60ff16614a9c565b60c085901b6001880152613fad87613f9d60808e0160608f01615179565b61ffff1660c01b60099190910152565b60c084811b6011890152601988018490526039880183905260808c0135605989015260a08c013560798901528b0135609988015261401187613ff260208d018d615101565b60405161400092919061520a565b604051809103902060b99190910152565b60d98701869052600161402760208d018d6151d1565b60ff1610614059576140598761404360608e0160408f016151f1565b67ffffffffffffffff1660c01b60f99190910152565b8087205f86815260a1602090815260408083209390935560ab815282822060a08f0135905560ad905290812083905560a65460ff16156140c25760a7545f90815260a4602052604090206002015460995442916140b5916150c0565b6140bf91906150d3565b90505b604051806080016040528042815260200182609854426140e291906150c0565b6140ec91906150c0565b81526020018d604001602081019061410491906151f1565b67ffffffffffffffff16815260209081018c90525f88815260a2825260409081902083518155838301516001820155908301516002820155606090920151600390920191909155609e8790556097546001600160a01b031692506374fe27b791508b359061417e90614178908e018e615101565b5f614aa3565b5f61418c60408f018f615101565b6040518663ffffffff1660e01b81526004016141ac959493929190615260565b602060405180830381865afa1580156141c7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906141eb91906150e6565b61425d5760405162461bcd60e51b815260206004820152602160248201527f746865207369676e617475726520766572696669636174696f6e206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610b98565b5f84815260a16020526040808220549051909186917f2c32d4ae151744d0bf0b9464a3e897a1d17ed2f1af71f7c9a75f12ce0d28238f9190a350505050505050505050565b806142ef5760405162461bcd60e51b815260206004820152601360248201527f496e76616c69642062617463682070726f6f66000000000000000000000000006044820152606401610b98565b5f6142fe846001015160c01c90565b90505f61430c856039015190565b90505f7f000000000000000000000000000000000000000000000000000000000000000061433b876059015190565b6079880151609989015160b98a015160198b015160405160c09690961b7fffffffffffffffff000000000000000000000000000000000000000000000000166020870152602886019490945260488501929092526068840152608883015260a882015260c8810183905260e801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120609c549091506001600160a01b0316632c09a8486143fd885160f81c90565b858888866040518663ffffffff1660e01b81526004016144219594939291906152d3565b5f6040518083038186803b158015614437575f80fd5b505afa158015614449573d5f803e3d5ffd5b50505050505050505050565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f54610100900460ff1661453a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b98565b612328614af7565b5f54610100900460ff166145be5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b98565b612328614b7f565b60a88390555f83815260a460205260408082205460975491517f45bc4d1000000000000000000000000000000000000000000000000000000000815260048101869052680100000000000000009091046001600160a01b03908116939216906345bc4d10906024016020604051808303815f875af115801561464a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061466e9190615162565b5f86815260a4602052604090206001015490915061468d9082906150c0565b5f86815260a460209081526040808320546801000000000000000090046001600160a01b0316835260a5909152812080549091906146cc9084906150c0565b90915550506040516146df908490615304565b604051908190038120906001600160a01b0384169087907fe70d3820e244d5f71d1a6395db24f3460e8dca966edc1fd3625b6292880a877a905f90a45050505050565b5f83815260a4602052604081206001015460a9549091906064906147469084615330565b6147509190615347565b905061475c81836150d3565b60aa5f82825461476c91906150c0565b90915550506001600160a01b0384165f90815260a56020526040812080548392906147989084906150c0565b90915550506040516147ab908490615304565b604051908190038120906001600160a01b0386169087907fe70d3820e244d5f71d1a6395db24f3460e8dca966edc1fd3625b6292880a877a905f90a45050505050565b8015614895575f826001600160a01b0316826040515f6040518083038185875af1925050503d805f811461483d576040519150601f19603f3d011682016040523d82523d5f602084013e614842565b606091505b50509050806148935760405162461bcd60e51b815260206004820152601b60248201527f526f6c6c75703a20455448207472616e73666572206661696c656400000000006044820152606401610b98565b505b5050565b6148a1613b17565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586148d63390565b6040516001600160a01b03909116815260200160405180910390a1565b6148fb614c04565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa336148d6565b5f8161497a5760405162461bcd60e51b815260206004820152601260248201527f456d7074792062617463682068656164657200000000000000000000000000006044820152606401610b98565b82825f81811061498c5761498c61537f565b919091013560f81c949350505050565b5f8160f98110156149ef5760405162461bcd60e51b815260206004820152601d60248201527f626174636820686561646572206c656e67746820746f6f20736d616c6c0000006044820152606401610b98565b6040519150808483378082016040529250929050565b5f8161010181146149ef5760405162461bcd60e51b815260206004820181905260248201527f626174636820686561646572206c656e67746820697320696e636f72726563746044820152606401610b98565b6040805160c085901b815260f084901b6008820152600a60208502820181019092525f918101614a8d8161ffff871686614c56565b82900390912095945050505050565b8082535050565b60605f80808080614ab6888a018a615499565b9550955095509550955050818710614ad4579450614af09350505050565b838710614ae8578295505050505050614af0565b509293505050505b9392505050565b5f54610100900460ff16614b735760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b98565b6065805460ff19169055565b5f54610100900460ff16614bfb5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b98565b61232833614455565b60655460ff166123285760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610b98565b5f825f03614c65575082614af0565b609b546001600160a01b03165f5b84811015614d12576040517fae453cd5000000000000000000000000000000000000000000000000000000008152600481018590525f906001600160a01b0384169063ae453cd590602401602060405180830381865afa158015614cd9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614cfd9190615162565b87525060209095019460019384019301614c73565b5093949350505050565b5f60208284031215614d2c575f80fd5b5035919050565b80356001600160a01b0381168114614d49575f80fd5b919050565b5f60208284031215614d5e575f80fd5b614af082614d33565b5f8083601f840112614d77575f80fd5b50813567ffffffffffffffff811115614d8e575f80fd5b602083019150836020828501011115614da5575f80fd5b9250929050565b5f805f60408486031215614dbe575f80fd5b833567ffffffffffffffff811115614dd4575f80fd5b614de086828701614d67565b909790965060209590950135949350505050565b5f8060208385031215614e05575f80fd5b823567ffffffffffffffff811115614e1b575f80fd5b614e2785828601614d67565b90969095509350505050565b5f60e08284031215614e43575f80fd5b50919050565b5f60608284031215614e43575f80fd5b5f8060408385031215614e6a575f80fd5b823567ffffffffffffffff80821115614e81575f80fd5b614e8d86838701614e33565b93506020850135915080821115614ea2575f80fd5b50614eaf85828601614e49565b9150509250929050565b5f805f805f8060808789031215614ece575f80fd5b863567ffffffffffffffff80821115614ee5575f80fd5b614ef18a838b01614e33565b97506020890135915080821115614f06575f80fd5b614f128a838b01614e49565b96506040890135915080821115614f27575f80fd5b614f338a838b01614d67565b90965094506060890135915080821115614f4b575f80fd5b50614f5889828a01614d67565b979a9699509497509295939492505050565b5f805f805f8060c08789031215614f7f575f80fd5b614f8887614d33565b9550614f9660208801614d33565b9450614fa460408801614d33565b9350606087013592506080870135915060a087013590509295509295509295565b5f805f8060408587031215614fd8575f80fd5b843567ffffffffffffffff80821115614fef575f80fd5b614ffb88838901614d67565b90965094506020870135915080821115615013575f80fd5b5061502087828801614d67565b95989497509550505050565b8015158114613044575f80fd5b5f60208284031215615049575f80fd5b8135614af08161502c565b803567ffffffffffffffff81168114614d49575f80fd5b5f806040838503121561507c575f80fd5b61508583615054565b946020939093013593505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8082018082111561184757611847615093565b8181038181111561184757611847615093565b5f602082840312156150f6575f80fd5b8151614af08161502c565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615134575f80fd5b83018035915067ffffffffffffffff82111561514e575f80fd5b602001915036819003821315614da5575f80fd5b5f60208284031215615172575f80fd5b5051919050565b5f60208284031215615189575f80fd5b813561ffff81168114614af0575f80fd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036151ca576151ca615093565b5060010190565b5f602082840312156151e1575f80fd5b813560ff81168114614af0575f80fd5b5f60208284031215615201575f80fd5b614af082615054565b818382375f9101908152919050565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f6080820187835260206080602085015281885180845260a08601915060208a0193505f5b818110156152aa5784516001600160a01b031683529383019391830191600101615285565b505087604086015284810360608601526152c5818789615219565b9a9950505050505050505050565b858152846020820152608060408201525f6152f2608083018587615219565b90508260608301529695505050505050565b5f82515f5b818110156153235760208186018101518583015201615309565b505f920191825250919050565b808202811582820484141761184757611847615093565b5f8261537a577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f8301126153e8575f80fd5b8135602067ffffffffffffffff80831115615405576154056153ac565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f83011681018181108482111715615448576154486153ac565b6040529384526020818701810194908101925087851115615467575f80fd5b6020870191505b8482101561548e5761547f82614d33565b8352918301919083019061546e565b979650505050505050565b5f805f805f8060c087890312156154ae575f80fd5b86359550602087013567ffffffffffffffff808211156154cc575f80fd5b6154d88a838b016153d9565b96506040890135955060608901359150808211156154f4575f80fd5b6155008a838b016153d9565b94506080890135935060a089013591508082111561551c575f80fd5b5061552989828a016153d9565b915050929550929550929556fea164736f6c6343000818000a", + Bin: "0x60a060405234801562000010575f80fd5b506040516200578d3803806200578d83398101604081905262000033916200010f565b6001600160401b0381166080526200004a62000051565b506200013e565b5f54610100900460ff1615620000bd5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116146200010d575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b5f6020828403121562000120575f80fd5b81516001600160401b038116811462000137575f80fd5b9392505050565b60805161562f6200015e5f395f81816106a20152614408015261562f5ff3fe608060405260043610610353575f3560e01c8063728cdbca116101bd578063b8d0a1b0116100f2578063d8dc99d211610092578063dff7827e1161006d578063dff7827e14610ac4578063e3fff1dd14610ad9578063f2fde38b14610af8578063fb1e8b0414610b17575f80fd5b8063d8dc99d214610a71578063ddd8a3dc14610a86578063de8b303514610aa5575f80fd5b8063cd4edc69116100cd578063cd4edc6914610a0b578063ce5db8d614610a1e578063cf9a674514610a33578063d279c19114610a52575f80fd5b8063b8d0a1b0146109ae578063bedb86fb146109cd578063c5553892146109ec575f80fd5b8063a479265d1161015d578063b31a77d311610138578063b31a77d31461093c578063b348442514610951578063b35dac4e14610970578063b3e0a5091461098f575f80fd5b8063a479265d146108dd578063a4f209b0146108f2578063abc8d68d14610911575f80fd5b80638f1d3776116101985780638f1d3776146107af578063910129d41461085f57806397fc007c14610890578063a415d8dc146108af575f80fd5b8063728cdbca1461075a57806388b1ea09146107795780638da5cb5b14610792575f80fd5b80632a213ba1116102935780635c975abb11610233578063612672901161020e57806361267290146106dd57806368589dfa146106fc5780636c578c1d14610727578063715018a614610746575f80fd5b80635c975abb1461061a5780635ef7a94a146106315780635f77cf1d14610691575f80fd5b80633e001b661161026e5780633e001b66146105b4578063428868b5146105c95780634e8f1d67146105dc57806357e0af6c146105fb575f80fd5b80632a213ba1146105335780632b7ac3f31461055e5780633b70c18a14610595575f80fd5b806313361101116102fe5780631e8825be116102d95780631e8825be1461049f57806321e2f9e0146104be5780632362f03e146104dd5780632571098d14610508575f80fd5b8063133611011461043b57806318463fb01461045a57806318af3b2b1461046f575f80fd5b806310d445831161032e57806310d44583146103e5578063116a1f4214610404578063121dcd5014610426575f80fd5b806304d772151461035e578063059def61146103a15780630ceb6780146103c4575f80fd5b3661035a57005b5f80fd5b348015610369575f80fd5b5061038c610378366004614e13565b60a36020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156103ac575f80fd5b506103b6609d5481565b604051908152602001610398565b3480156103cf575f80fd5b506103e36103de366004614e40565b610b2c565b005b3480156103f0575f80fd5b506103e36103ff366004614e9e565b610bfe565b34801561040f575f80fd5b5061038c61041e366004614e13565b609d54101590565b348015610431575f80fd5b506103b6609e5481565b348015610446575f80fd5b506103e3610455366004614ee6565b610f3a565b348015610465575f80fd5b506103b660a75481565b34801561047a575f80fd5b5061038c610489366004614e13565b5f90815260a26020526040902060010154421090565b3480156104aa575f80fd5b506103e36104b9366004614f45565b611434565b3480156104c9575f80fd5b5061038c6104d8366004614e13565b61181f565b3480156104e8575f80fd5b506103b66104f7366004614e13565b60a16020525f908152604090205481565b348015610513575f80fd5b506103b6610522366004614e13565b60a06020525f908152604090205481565b34801561053e575f80fd5b506103b661054d366004614e13565b60ad6020525f908152604090205481565b348015610569575f80fd5b50609c5461057d906001600160a01b031681565b6040516001600160a01b039091168152602001610398565b3480156105a0575f80fd5b50609b5461057d906001600160a01b031681565b3480156105bf575f80fd5b506103b660aa5481565b6103e36105d7366004614f45565b61184d565b3480156105e7575f80fd5b506103e36105f6366004614fa5565b611be8565b348015610606575f80fd5b506103e3610615366004614e13565b611f9c565b348015610625575f80fd5b5060655460ff1661038c565b34801561063c575f80fd5b5061067161064b366004614e13565b60a26020525f908152604090208054600182015460028301546003909301549192909184565b604080519485526020850193909352918301526060820152608001610398565b34801561069c575f80fd5b506106c47f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff9091168152602001610398565b3480156106e8575f80fd5b506103e36106f7366004614e13565b612047565b348015610707575f80fd5b506103b6610716366004614e13565b60ab6020525f908152604090205481565b348015610732575f80fd5b506103e3610741366004614e40565b612222565b348015610751575f80fd5b506103e36122df565b348015610765575f80fd5b506103e3610774366004615056565b6122f2565b348015610784575f80fd5b5060a65461038c9060ff1681565b34801561079d575f80fd5b506033546001600160a01b031661057d565b3480156107ba575f80fd5b5061081b6107c9366004614e13565b60a46020525f9081526040902080546001820154600283015460039093015467ffffffffffffffff831693680100000000000000009093046001600160a01b0316929060ff8082169161010090041686565b6040805167ffffffffffffffff90971687526001600160a01b03909516602087015293850192909252606084015215156080830152151560a082015260c001610398565b34801561086a575f80fd5b5061038c610879366004614e13565b5f90815260a4602052604090206003015460ff1690565b34801561089b575f80fd5b506103e36108aa366004614e40565b6125fb565b3480156108ba575f80fd5b5061038c6108c9366004614e40565b609f6020525f908152604090205460ff1681565b3480156108e8575f80fd5b506103b660995481565b3480156108fd575f80fd5b506103e361090c366004614e13565b6126de565b34801561091c575f80fd5b506103b661092b366004614e40565b60a56020525f908152604090205481565b348015610947575f80fd5b506103b660a85481565b34801561095c575f80fd5b506103e361096b3660046150b1565b61278e565b34801561097b575f80fd5b506103e361098a366004614e40565b612a92565b34801561099a575f80fd5b506103e36109a9366004614ee6565b612aeb565b3480156109b9575f80fd5b506103e36109c83660046150b1565b612e48565b3480156109d8575f80fd5b506103e36109e7366004615125565b612ed1565b3480156109f7575f80fd5b506103e3610a06366004614e13565b61300f565b6103e3610a19366004615157565b6130b2565b348015610a29575f80fd5b506103b660985481565b348015610a3e575f80fd5b506103e3610a4d366004614e13565b613644565b348015610a5d575f80fd5b506103e3610a6c366004614e40565b6137b3565b348015610a7c575f80fd5b506103b660ac5481565b348015610a91575f80fd5b5060975461057d906001600160a01b031681565b348015610ab0575f80fd5b5061038c610abf366004614e13565b613872565b348015610acf575f80fd5b506103b6609a5481565b348015610ae4575f80fd5b506103e3610af3366004614e13565b6138bc565b348015610b03575f80fd5b506103e3610b12366004614e40565b61395f565b348015610b22575f80fd5b506103b660a95481565b610b346139ec565b6001600160a01b0381165f908152609f602052604090205460ff1615610ba15760405162461bcd60e51b815260206004820152601f60248201527f6163636f756e7420697320616c72656164792061206368616c6c656e6765720060448201526064015b60405180910390fd5b6001600160a01b0381165f818152609f6020908152604091829020805460ff1916600190811790915591519182527f7feb653c7b1f0d23daeed494225b3f28851cdc8973fcc653866d9b6e205fc00991015b60405180910390a250565b610c066139ec565b5f8111610c555760405162461bcd60e51b815260206004820152601560248201527f636f756e74206d757374206265206e6f6e7a65726f00000000000000000000006044820152606401610b98565b5f80610c618585613a46565b915091505f610c74836001015160c01c90565b5f81815260a160205260409020549091508214610cd35760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b5f60a181610ce187856151ac565b81526020019081526020015f205414610d615760405162461bcd60e51b8152602060048201526024808201527f726576657274696e67206d7573742073746172742066726f6d2074686520656e60448201527f64696e67000000000000000000000000000000000000000000000000000000006064820152608401610b98565b609d548111610dd85760405162461bcd60e51b815260206004820152602160248201527f63616e206f6e6c792072657665727420756e46696e616c697a6564206261746360448201527f68000000000000000000000000000000000000000000000000000000000000006064820152608401610b98565b610de36001826151bf565b609e555b8315610f3257604051829082907ecae2739091badfd91c373f0a16cede691e0cd25bb80cff77dd5caeb4710146905f90a35f81815260a16020526040812055610e2f81613872565b15610e8a575f81815260a460209081526040808320600181015490546801000000000000000090046001600160a01b0316845260a59092528220805491929091610e7a9084906151ac565b909155505060a6805460ff191690555b5f81815260a46020526040812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181018290556002810191909155600301805461ffff1916905560a85415801590610eea575060a85481145b15610ef4575f60a8555b6001015f81815260a160205260409020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90940193915081610de7575b505050505050565b60a85415610f8a5760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b610f92613aee565b5f80610f9e8484613a46565b915091505f610fb1836001015160c01c90565b5f81815260a1602052604090205490915082146110105760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b6110198161181f565b6110655760405162461bcd60e51b815260206004820152600f60248201527f6261746368206e6f7420657869737400000000000000000000000000000000006044820152606401610b98565b61106e81613872565b156110bb5760405162461bcd60e51b815260206004820152601260248201527f626174636820696e206368616c6c656e676500000000000000000000000000006044820152606401610b98565b5f81815260a4602052604090206003015460ff161561111c5760405162461bcd60e51b815260206004820152601660248201527f62617463682073686f756c6420626520726576657274000000000000000000006044820152606401610b98565b5f81815260a2602052604090206001015442101561117c5760405162461bcd60e51b815260206004820152601960248201527f626174636820696e206368616c6c656e67652077696e646f77000000000000006044820152606401610b98565b605983015160a05f61118f6001856151bf565b81526020019081526020015f2054146111ea5760405162461bcd60e51b815260206004820152601d60248201527f696e636f72726563742070726576696f757320737461746520726f6f740000006044820152606401610b98565b5f81815260a06020526040902054156112455760405162461bcd60e51b815260206004820152601660248201527f626174636820616c7265616479207665726966696564000000000000000000006044820152606401610b98565b80609d54600101146112995760405162461bcd60e51b815260206004820152601560248201527f696e636f727265637420626174636820696e64657800000000000000000000006044820152606401610b98565b609d819055600160a35f6112ae866099015190565b815260208101919091526040015f20805460ff191691151591909117905560798301515f82815260a060205260409020556112fd6112f0846011015160c01c90565b600985015160c01c613b41565b60a25f61130b6001846151bf565b815260208101919091526040015f908120818155600180820183905560028201839055600390910182905560ab919061134490846151bf565b81526020019081526020015f205f905560ad5f60018361136491906151bf565b81526020019081526020015f205f905560a45f60018361138491906151bf565b815260208082019290925260409081015f90812080547fffffffff000000000000000000000000000000000000000000000000000000001681556001810182905560028101829055600301805461ffff1916905583815260a1909252902054817f26ba82f907317eedc97d0cbef23de76a43dd6edb563bdb6e9407645b950a7a2d611410866079015190565b60998701516040805192835260208301919091520160405180910390a35050505050565b6097546001600160a01b03166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156114a0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114c491906151d2565b6115105760405162461bcd60e51b815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610b98565b60a854156115605760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b611568613aee565b5f49156115b75760405162461bcd60e51b815260206004820152601f60248201527f636f6d6d69745374617465206d757374206e6f7420636172727920626c6f62006044820152606401610b98565b5f6115cd6115c860208501856151ed565b613a46565b5090505f6115df826001015160c01c90565b6115ea9060016151ac565b5f81815260ad602052604090205490915061166d5760405162461bcd60e51b815260206004820152602260248201527f6e6f2073746f72656420626c6f62206861736820666f7220746869732062617460448201527f63680000000000000000000000000000000000000000000000000000000000006064820152608401610b98565b60ac54609b54604080517fb59b1a7800000000000000000000000000000000000000000000000000000000815290514293926001600160a01b03169163b59b1a789160048083019260209291908290030181865afa1580156116d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116f5919061524e565b6116ff91906151ac565b1015611767575f6117166080860160608701615265565b61ffff16116117675760405162461bcd60e51b815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610b98565b6097545f906001600160a01b031663d096c3c6336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156117d5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117f9919061524e565b905061181885858360ad5f8781526020019081526020015f2054613bfe565b5050505050565b5f81815260a260205260408120541580159061184757505f82815260a1602052604090205415155b92915050565b6097546001600160a01b03166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156118b9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118dd91906151d2565b6119295760405162461bcd60e51b815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610b98565b60a854156119795760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b611981613aee565b5f6119926115c860208501856151ed565b5090505f6119a4826001015160c01c90565b6119af9060016151ac565b5f81815260ad602052604090205490915015611a335760405162461bcd60e51b815260206004820152602860248201527f636f6d6d69744261746368207265717569726573206e6f2073746f726564206260448201527f6c6f6220686173680000000000000000000000000000000000000000000000006064820152608401610b98565b60ac54609b54604080517fb59b1a7800000000000000000000000000000000000000000000000000000000815290514293926001600160a01b03169163b59b1a789160048083019260209291908290030181865afa158015611a97573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611abb919061524e565b611ac591906151ac565b1015611b2d575f611adc6080860160608701615265565b61ffff1611611b2d5760405162461bcd60e51b815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610b98565b6097545f906001600160a01b031663d096c3c6336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015611b9b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bbf919061524e565b90505f611bda611bd26020880188615286565b60ff1661425e565b9050610f3286868484613bfe565b60a85415611c385760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b611c40613aee565b60ac54609e545f90815260a2602052604081205490914291611c6291906151ac565b1090505f4260ac54609b5f9054906101000a90046001600160a01b03166001600160a01b031663b59b1a786040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cba573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cde919061524e565b611ce891906151ac565b10905081158015611cf65750805b15611d5d575f611d0c60808a0160608b01615265565b61ffff1611611d5d5760405162461bcd60e51b815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610b98565b8180611d665750805b611db25760405162461bcd60e51b815260206004820152600e60248201527f696e76616c69642074696d696e670000000000000000000000000000000000006044820152606401610b98565b5f611dc36115c860208b018b6151ed565b5090505f611dd5826001015160c01c90565b611de09060016151ac565b5f81815260ad60205260408120549192509015611e80575f4915611e6c5760405162461bcd60e51b815260206004820152602f60248201527f6d757374206e6f7420636172727920626c6f62207768656e207573696e67207360448201527f746f72656420626c6f62206861736800000000000000000000000000000000006064820152608401610b98565b505f81815260ad6020526040902054611e93565b611e90611bd260208d018d615286565b90505b611e9f8b8b5f84613bfe565b5f80611eab8b8b613a46565b915091505f611ebe836001015160c01c90565b905080609e5414611f115760405162461bcd60e51b815260206004820152601660248201527f696e636f727265637420626174636820686561646572000000000000000000006044820152606401610b98565b5f81815260a160205260409020548214611f6d5760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b5f81815260a26020526040902042600190910155611f8c838b8b614399565b5050505050505050505050505050565b611fa46139ec565b5f81118015611fb557506099548114155b6120015760405162461bcd60e51b815260206004820152601860248201527f696e76616c6964206e65772070726f6f662077696e646f7700000000000000006044820152606401610b98565b609980549082905560408051828152602081018490527f1e3a2094feb4b696dd3d7caea38ad2f41dbdcac3fa3943c7a693aff8a64b0a6191015b60405180910390a15050565b5f54600290610100900460ff1615801561206757505f5460ff8083169116105b6120d95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610b98565b5f805461ffff191660ff8316176101001790556120f75f5460ff1690565b60ff166002146121495760405162461bcd60e51b815260206004820152601660248201527f6d757374206861766520696e697469616c697a656421000000000000000000006044820152606401610b98565b816121bc5760405162461bcd60e51b815260206004820152602760248201527f63616e206e6f742073657420737461746520726f6f742077697468206279746560448201527f73333228302921000000000000000000000000000000000000000000000000006064820152608401610b98565b609e545f90815260ab60205260409020546121e557609e545f90815260ab602052604090208290555b5f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200161203b565b61222a6139ec565b6001600160a01b0381165f908152609f602052604090205460ff166122915760405162461bcd60e51b815260206004820152601b60248201527f6163636f756e74206973206e6f742061206368616c6c656e67657200000000006044820152606401610b98565b6001600160a01b0381165f818152609f60209081526040808320805460ff19169055519182527f7feb653c7b1f0d23daeed494225b3f28851cdc8973fcc653866d9b6e205fc0099101610bf3565b6122e76139ec565b6122f05f61454c565b565b5f54610100900460ff161580801561231057505f54600160ff909116105b806123295750303b15801561232957505f5460ff166001145b61239b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610b98565b5f805460ff1916600117905580156123bc575f805461ff0019166101001790555b6001600160a01b03861615806123d957506001600160a01b038516155b15612410576040517fecc6fdf000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0387166124665760405162461bcd60e51b815260206004820152601b60248201527f696e76616c6964206c31207374616b696e6720636f6e747261637400000000006044820152606401610b98565b61246e6145b5565b612476614639565b609780546001600160a01b03808a167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255609b8054898416908316179055609c805492881692909116821790556098859055609984905560a98390556040515f907f728af3d16a5760405e27a082c98ab272e9f0a1d02f0085d41532a26093aedd96908290a3604080515f8152602081018690527fa577f4223f91f74e2dad65bbb8c30807587ae95d0d34288057bb3ec0d398a437910160405180910390a1604080515f8152602081018590527f1e3a2094feb4b696dd3d7caea38ad2f41dbdcac3fa3943c7a693aff8a64b0a61910160405180910390a1604080515f8152602081018490527ffb81bce17f015797e11949d3c332e2bf9453faf68f728447426803138f2b0223910160405180910390a180156125f2575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b6126036139ec565b6001600160a01b038116158015906126295750609c546001600160a01b03828116911614155b6126755760405162461bcd60e51b815260206004820152601460248201527f696e76616c6964206e65772076657269666965720000000000000000000000006044820152606401610b98565b609c80546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f728af3d16a5760405e27a082c98ab272e9f0a1d02f0085d41532a26093aedd96905f90a35050565b6126e66139ec565b5f811180156126f6575060648111155b8015612704575060a9548114155b6127505760405162461bcd60e51b815260206004820152601f60248201527f696e76616c69642070726f6f66207265776172642070657263656e74616765006044820152606401610b98565b60a980549082905560408051828152602081018490527ffb81bce17f015797e11949d3c332e2bf9453faf68f728447426803138f2b0223910161203b565b60a854156127de5760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b6127e6613aee565b6097546001600160a01b03166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015612852573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061287691906151d2565b6128c25760405162461bcd60e51b815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610b98565b5f806128ce8686613a46565b915091505f6128e1836001015160c01c90565b5f81815260a1602052604090205490915082146129405760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b61294981613872565b6129955760405162461bcd60e51b815260206004820152601260248201527f626174636820696e206368616c6c656e676500000000000000000000000000006044820152606401610b98565b5f81815260a46020526040902060038101805461ff00191661010017905560a6805460ff1916905560995460029091015442916129d1916151ac565b11612a47575f81815260a4602090815260408083206003908101805460ff1916600117905560a2835292819020909201548251808401909352600783527f54696d656f75740000000000000000000000000000000000000000000000000091830191909152612a42918391906146bd565b6125f2565b612a52838686614399565b6125f281336040518060400160405280600d81526020017f50726f6f66207375636365737300000000000000000000000000000000000000815250614819565b612a9a6139ec565b60aa80545f909155612aac82826148e5565b604080516001600160a01b0384168152602081018390527fb1b2058a6969e2d25e47bcaebe8ae21c29a23b2752429315b75e2f4f285f3d87910161203b565b612af36139ec565b5f805260a06020527fb84a74ec6ef4d0e83b6006dfaa014ab4026f9f3b97d186e604d29998a4e808ea5415612b6a5760405162461bcd60e51b815260206004820152601660248201527f67656e6573697320626174636820696d706f72746564000000000000000000006044820152606401610b98565b5f80612b768484613a46565b915091505f612b89836001015160c01c90565b90508015612bd95760405162461bcd60e51b815260206004820152601360248201527f696e76616c696420626174636820696e646578000000000000000000000000006044820152606401610b98565b5f612be5846079015190565b905080612c345760405162461bcd60e51b815260206004820152600f60248201527f7a65726f20737461746520726f6f7400000000000000000000000000000000006044820152606401610b98565b600984015160c01c15612c895760405162461bcd60e51b815260206004820152601d60248201527f6c31206d65737361676520706f707065642073686f756c6420626520300000006044820152606401610b98565b5f612c95856019015190565b03612ce25760405162461bcd60e51b815260206004820152600e60248201527f7a65726f206461746120686173680000000000000000000000000000000000006044820152606401610b98565b7f010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014612d0e856039015190565b14612d5b5760405162461bcd60e51b815260206004820152601660248201527f696e76616c69642076657273696f6e65642068617368000000000000000000006044820152606401610b98565b5f82815260a1602090815260408083208690558051608081018252428082528184019081528183018581526060830186815288875260a28652848720935184559151600184015551600283015551600390910155603987015160ad83528184205560ab825280832084905560a0909152808220839055609e849055609d84905551849184917f2c32d4ae151744d0bf0b9464a3e897a1d17ed2f1af71f7c9a75f12ce0d28238f9190a3604080518281525f6020820152849184917f26ba82f907317eedc97d0cbef23de76a43dd6edb563bdb6e9407645b950a7a2d910160405180910390a3505050505050565b5f80612e548686613a46565b915091505f612e67836001015160c01c90565b5f81815260a160205260409020549091508214612ec65760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b6125f2838686614399565b612ed96139ec565b8015612fdd57612ee7614990565b60a65460ff1615612f9c5760a7545f90815260a460209081526040808320600181015490546801000000000000000090046001600160a01b0316845260a59092528220805491929091612f3b9084906151ac565b909155505060a7545f90815260a46020526040812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181018290556002810191909155600301805461ffff1916905560a6805460ff191690555b7f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258335b6040516001600160a01b03909116815260200160405180910390a150565b612fe56149ea565b7f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33612fbf565b50565b6130176139ec565b5f81118015613028575060ac548114155b6130745760405162461bcd60e51b815260206004820152601f60248201527f696e76616c6964206e657720726f6c6c75702064656c617920706572696f64006044820152606401610b98565b60ac80549082905560408051828152602081018490527f624e47dc9fb8f8cfeaf4ead4710277cc1757136cfa885e465514cf6d510f0ad1910161203b565b335f908152609f602052604090205460ff166131105760405162461bcd60e51b815260206004820152601760248201527f6f6e6c79206368616c6c656e67657220616c6c6f7765640000000000000000006044820152606401610b98565b60a854156131605760405162461bcd60e51b815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610b98565b613168613aee565b60a65460ff16156131bb5760405162461bcd60e51b815260206004820152601460248201527f616c726561647920696e206368616c6c656e67650000000000000000000000006044820152606401610b98565b8167ffffffffffffffff16609d54106132165760405162461bcd60e51b815260206004820152601760248201527f626174636820616c72656164792066696e616c697a65640000000000000000006044820152606401610b98565b67ffffffffffffffff82165f90815260a16020526040902054811461327d5760405162461bcd60e51b815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610b98565b6132908267ffffffffffffffff1661181f565b6132dc5760405162461bcd60e51b815260206004820152600f60248201527f6261746368206e6f7420657869737400000000000000000000000000000000006044820152606401610b98565b67ffffffffffffffff82165f90815260a460205260409020546801000000000000000090046001600160a01b0316156133575760405162461bcd60e51b815260206004820152601860248201527f626174636820616c7265616479206368616c6c656e67656400000000000000006044820152606401610b98565b67ffffffffffffffff82165f90815260a2602052604090206001015442106133e75760405162461bcd60e51b815260206004820152603360248201527f63616e6e6f74206368616c6c656e6765206261746368206f757473696465207460448201527f6865206368616c6c656e67652077696e646f77000000000000000000000000006064820152608401610b98565b60975f9054906101000a90046001600160a01b03166001600160a01b0316630d13fd7b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613437573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061345b919061524e565b3410156134aa5760405162461bcd60e51b815260206004820152601260248201527f696e73756666696369656e742076616c756500000000000000000000000000006044820152606401610b98565b67ffffffffffffffff82811660a78190556040805160c0810182528281523360208083018281523484860190815242606086019081525f6080870181815260a0880182815299825260a4909552969096209451855492516001600160a01b031668010000000000000000027fffffffff000000000000000000000000000000000000000000000000000000009093169816979097171783559451600183015591516002820155925160039093018054925115156101000261ff00199415159490941661ffff19909316929092179290921790556001600160a01b03168267ffffffffffffffff167f3a6ea19df25b49e7624e313ce7c1ab23984238e93727260db56a81735b1b9976346040516135c291815260200190565b60405180910390a35f609d5460016135da91906151ac565b90505b609e548111613632578267ffffffffffffffff168114613620576099545f82815260a260205260408120600101805490919061361a9084906151ac565b90915550505b8061362a816152a6565b9150506135dd565b505060a6805460ff1916600117905550565b5f54600390610100900460ff1615801561366457505f5460ff8083169116105b6136d65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610b98565b5f805461ffff191660ff8316176101001781558290036137385760405162461bcd60e51b815260206004820152601b60248201527f696e76616c696420726f6c6c75702064656c617920706572696f6400000000006044820152606401610b98565b60ac829055604080515f8152602081018490527f624e47dc9fb8f8cfeaf4ead4710277cc1757136cfa885e465514cf6d510f0ad1910160405180910390a15f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200161203b565b335f90815260a56020526040812054908190036138125760405162461bcd60e51b815260206004820152601c60248201527f696e76616c69642062617463684368616c6c656e6765526577617264000000006044820152606401610b98565b335f90815260a5602052604081205561382b82826148e5565b816001600160a01b03167f9c25fa83f414ed363c8d39c98fb3e17567b3431cede71eb062c49d2a63ce247a8260405161386691815260200190565b60405180910390a25050565b5f81815260a460205260408120546801000000000000000090046001600160a01b0316158015906118475750505f90815260a46020526040902060030154610100900460ff161590565b6138c46139ec565b5f811180156138d557506098548114155b6139215760405162461bcd60e51b815260206004820152601b60248201527f696e76616c6964206e65772066696e616c697a6520706572696f6400000000006044820152606401610b98565b609880549082905560408051828152602081018490527fa577f4223f91f74e2dad65bbb8c30807587ae95d0d34288057bb3ec0d398a437910161203b565b6139676139ec565b6001600160a01b0381166139e35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610b98565b61300c8161454c565b6033546001600160a01b031633146122f05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b98565b5f805f613a538585614a23565b90505f8160ff165f03613a7457613a6a8686614a93565b9094509050613ae0565b8160ff1660011480613a8957508160ff166002145b15613a9857613a6a8686614afc565b60405162461bcd60e51b815260206004820152601960248201527f556e737570706f727465642062617463682076657273696f6e000000000000006044820152606401610b98565b808420925050509250929050565b60655460ff16156122f05760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610b98565b805f03613b4c575050565b8082035f5b82811015613bf857610100818403811115613b6b57508083035b609b546040517f3c7f528300000000000000000000000000000000000000000000000000000000815260048101859052602481018390526001600160a01b0390911690633c7f5283906044015f604051808303815f87803b158015613bce575f80fd5b505af1158015613be0573d5f803e3d5ffd5b50505050610100830192505061010081019050613b51565b50505050565b6002613c0d6020860186615286565b60ff161115613c5e5760405162461bcd60e51b815260206004820152600f60248201527f696e76616c69642076657273696f6e00000000000000000000000000000000006044820152606401610b98565b6080840135613caf5760405162461bcd60e51b815260206004820152601b60248201527f70726576696f757320737461746520726f6f74206973207a65726f00000000006044820152606401610b98565b60a0840135613d005760405162461bcd60e51b815260206004820152601660248201527f6e657720737461746520726f6f74206973207a65726f000000000000000000006044820152606401610b98565b5f80613d126115c860208801886151ed565b915091505f613d25836001015160c01c90565b90505f60a181613d368460016151ac565b81526020019081526020015f205414613d915760405162461bcd60e51b815260206004820152601760248201527f626174636820616c726561647920636f6d6d69747465640000000000000000006044820152606401610b98565b609e548114613de25760405162461bcd60e51b815260206004820152601560248201527f696e636f727265637420626174636820696e64657800000000000000000000006044820152606401610b98565b5f81815260a160205260409020548214613e3e5760405162461bcd60e51b815260206004820152601b60248201527f696e636f727265637420706172656e74206261746368206861736800000000006044820152606401610b98565b5f81815260ab6020526040902054608088013514613e9e5760405162461bcd60e51b815260206004820152601d60248201527f696e636f72726563742070726576696f757320737461746520726f6f740000006044820152606401610b98565b5f613ead846011015160c01c90565b90505f613ed9613ec360608b0160408c016152dd565b613ed360808c0160608d01615265565b84614b4f565b9050613eeb60808a0160608b01615265565b60019384019361ffff91909116929092019160f990613f0d60208c018c615286565b60ff1610613f1a57506101015b604080518281019091529550613f3f86613f3760208d018d615286565b60ff16614b93565b60c084901b6001870152613f6d86613f5d60808d0160608e01615265565b61ffff1660c01b60099190910152565b60c083811b6011880152601987018390526039870188905260808b0135605988015260a08b013560798801528a01356099870152613fd186613fb260208c018c6151ed565b604051613fc09291906152f6565b604051809103902060b99190910152565b60d986018590526001613fe760208c018c615286565b60ff1610614019576140198661400360608d0160408e016152dd565b67ffffffffffffffff1660c01b60f99190910152565b8086205f85815260a1602090815260408083209390935560ab815282822060a08e0135905560ad905290812088905560a65460ff16156140825760a7545f90815260a460205260409020600201546099544291614075916151ac565b61407f91906151bf565b90505b604051806080016040528042815260200182609854426140a291906151ac565b6140ac91906151ac565b81526020016140c160608e0160408f016152dd565b67ffffffffffffffff16815260209081018b90525f87815260a2825260409081902083518155838301516001820155908301516002820155606090920151600390920191909155609e8690556097546001600160a01b031692506374fe27b791508a359061413b90614135908d018d6151ed565b5f614b9a565b5f61414960408e018e6151ed565b6040518663ffffffff1660e01b815260040161416995949392919061534c565b602060405180830381865afa158015614184573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906141a891906151d2565b61421a5760405162461bcd60e51b815260206004820152602160248201527f746865207369676e617475726520766572696669636174696f6e206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610b98565b5f83815260a16020526040808220549051909185917f2c32d4ae151744d0bf0b9464a3e897a1d17ed2f1af71f7c9a75f12ce0d28238f9190a3505050505050505050565b5f816002036142ed575f6040515f5b80498061427a5750614289565b6020820283015260010161426d565b6020810280832092016040529092509050806142e75760405162461bcd60e51b815260206004820152601b60248201527f5632207265717569726573206174206c65617374203120626c6f6200000000006044820152606401610b98565b50919050565b600149156143635760405162461bcd60e51b815260206004820152602560248201527f6c6567616379206261746368657320737570706f72742065786163746c79203160448201527f20626c6f620000000000000000000000000000000000000000000000000000006064820152608401610b98565b5f4915614371575f49611847565b507f010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c4440145b919050565b806143e65760405162461bcd60e51b815260206004820152601360248201527f496e76616c69642062617463682070726f6f66000000000000000000000000006044820152606401610b98565b5f6143f5846001015160c01c90565b90505f614403856039015190565b90505f7f0000000000000000000000000000000000000000000000000000000000000000614432876059015190565b6079880151609989015160b98a015160198b015160405160c09690961b7fffffffffffffffff000000000000000000000000000000000000000000000000166020870152602886019490945260488501929092526068840152608883015260a882015260c8810183905260e801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120609c549091506001600160a01b0316632c09a8486144f4885160f81c90565b858888866040518663ffffffff1660e01b81526004016145189594939291906153bf565b5f6040518083038186803b15801561452e575f80fd5b505afa158015614540573d5f803e3d5ffd5b50505050505050505050565b603380546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f54610100900460ff166146315760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b98565b6122f0614bee565b5f54610100900460ff166146b55760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b98565b6122f0614c76565b60a88390555f83815260a460205260408082205460975491517f45bc4d1000000000000000000000000000000000000000000000000000000000815260048101869052680100000000000000009091046001600160a01b03908116939216906345bc4d10906024016020604051808303815f875af1158015614741573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614765919061524e565b5f86815260a460205260409020600101549091506147849082906151ac565b5f86815260a460209081526040808320546801000000000000000090046001600160a01b0316835260a5909152812080549091906147c39084906151ac565b90915550506040516147d69084906153f0565b604051908190038120906001600160a01b0384169087907fe70d3820e244d5f71d1a6395db24f3460e8dca966edc1fd3625b6292880a877a905f90a45050505050565b5f83815260a4602052604081206001015460a95490919060649061483d908461541c565b6148479190615433565b905061485381836151bf565b60aa5f82825461486391906151ac565b90915550506001600160a01b0384165f90815260a560205260408120805483929061488f9084906151ac565b90915550506040516148a29084906153f0565b604051908190038120906001600160a01b0386169087907fe70d3820e244d5f71d1a6395db24f3460e8dca966edc1fd3625b6292880a877a905f90a45050505050565b801561498c575f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114614934576040519150601f19603f3d011682016040523d82523d5f602084013e614939565b606091505b505090508061498a5760405162461bcd60e51b815260206004820152601b60248201527f526f6c6c75703a20455448207472616e73666572206661696c656400000000006044820152606401610b98565b505b5050565b614998613aee565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586149cd3390565b6040516001600160a01b03909116815260200160405180910390a1565b6149f2614cfb565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa336149cd565b5f81614a715760405162461bcd60e51b815260206004820152601260248201527f456d7074792062617463682068656164657200000000000000000000000000006044820152606401610b98565b82825f818110614a8357614a8361546b565b919091013560f81c949350505050565b5f8160f9811015614ae65760405162461bcd60e51b815260206004820152601d60248201527f626174636820686561646572206c656e67746820746f6f20736d616c6c0000006044820152606401610b98565b6040519150808483378082016040529250929050565b5f816101018114614ae65760405162461bcd60e51b815260206004820181905260248201527f626174636820686561646572206c656e67746820697320696e636f72726563746044820152606401610b98565b6040805160c085901b815260f084901b6008820152600a60208502820181019092525f918101614b848161ffff871686614d4d565b82900390912095945050505050565b8082535050565b60605f80808080614bad888a018a615585565b9550955095509550955050818710614bcb579450614be79350505050565b838710614bdf578295505050505050614be7565b509293505050505b9392505050565b5f54610100900460ff16614c6a5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b98565b6065805460ff19169055565b5f54610100900460ff16614cf25760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610b98565b6122f03361454c565b60655460ff166122f05760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610b98565b5f825f03614d5c575082614be7565b609b546001600160a01b03165f5b84811015614e09576040517fae453cd5000000000000000000000000000000000000000000000000000000008152600481018590525f906001600160a01b0384169063ae453cd590602401602060405180830381865afa158015614dd0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614df4919061524e565b87525060209095019460019384019301614d6a565b5093949350505050565b5f60208284031215614e23575f80fd5b5035919050565b80356001600160a01b0381168114614394575f80fd5b5f60208284031215614e50575f80fd5b614be782614e2a565b5f8083601f840112614e69575f80fd5b50813567ffffffffffffffff811115614e80575f80fd5b602083019150836020828501011115614e97575f80fd5b9250929050565b5f805f60408486031215614eb0575f80fd5b833567ffffffffffffffff811115614ec6575f80fd5b614ed286828701614e59565b909790965060209590950135949350505050565b5f8060208385031215614ef7575f80fd5b823567ffffffffffffffff811115614f0d575f80fd5b614f1985828601614e59565b90969095509350505050565b5f60e082840312156142e7575f80fd5b5f606082840312156142e7575f80fd5b5f8060408385031215614f56575f80fd5b823567ffffffffffffffff80821115614f6d575f80fd5b614f7986838701614f25565b93506020850135915080821115614f8e575f80fd5b50614f9b85828601614f35565b9150509250929050565b5f805f805f8060808789031215614fba575f80fd5b863567ffffffffffffffff80821115614fd1575f80fd5b614fdd8a838b01614f25565b97506020890135915080821115614ff2575f80fd5b614ffe8a838b01614f35565b96506040890135915080821115615013575f80fd5b61501f8a838b01614e59565b90965094506060890135915080821115615037575f80fd5b5061504489828a01614e59565b979a9699509497509295939492505050565b5f805f805f8060c0878903121561506b575f80fd5b61507487614e2a565b955061508260208801614e2a565b945061509060408801614e2a565b9350606087013592506080870135915060a087013590509295509295509295565b5f805f80604085870312156150c4575f80fd5b843567ffffffffffffffff808211156150db575f80fd5b6150e788838901614e59565b909650945060208701359150808211156150ff575f80fd5b5061510c87828801614e59565b95989497509550505050565b801515811461300c575f80fd5b5f60208284031215615135575f80fd5b8135614be781615118565b803567ffffffffffffffff81168114614394575f80fd5b5f8060408385031215615168575f80fd5b61517183615140565b946020939093013593505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b808201808211156118475761184761517f565b818103818111156118475761184761517f565b5f602082840312156151e2575f80fd5b8151614be781615118565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615220575f80fd5b83018035915067ffffffffffffffff82111561523a575f80fd5b602001915036819003821315614e97575f80fd5b5f6020828403121561525e575f80fd5b5051919050565b5f60208284031215615275575f80fd5b813561ffff81168114614be7575f80fd5b5f60208284031215615296575f80fd5b813560ff81168114614be7575f80fd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036152d6576152d661517f565b5060010190565b5f602082840312156152ed575f80fd5b614be782615140565b818382375f9101908152919050565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f6080820187835260206080602085015281885180845260a08601915060208a0193505f5b818110156153965784516001600160a01b031683529383019391830191600101615371565b505087604086015284810360608601526153b1818789615305565b9a9950505050505050505050565b858152846020820152608060408201525f6153de608083018587615305565b90508260608301529695505050505050565b5f82515f5b8181101561540f57602081860181015185830152016153f5565b505f920191825250919050565b80820281158282048414176118475761184761517f565b5f82615466577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f8301126154d4575f80fd5b8135602067ffffffffffffffff808311156154f1576154f1615498565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110848211171561553457615534615498565b6040529384526020818701810194908101925087851115615553575f80fd5b6020870191505b8482101561557a5761556b82614e2a565b8352918301919083019061555a565b979650505050505050565b5f805f805f8060c0878903121561559a575f80fd5b86359550602087013567ffffffffffffffff808211156155b8575f80fd5b6155c48a838b016154c5565b96506040890135955060608901359150808211156155e0575f80fd5b6155ec8a838b016154c5565b94506080890135935060a0890135915080821115615608575f80fd5b5061561589828a016154c5565b915050929550929550929556fea164736f6c6343000818000a", } // RollupABI is the input ABI used to generate the binding from. diff --git a/bindings/bindings/rollup_more.go b/bindings/bindings/rollup_more.go index 926d6baf3..a78f509fd 100644 --- a/bindings/bindings/rollup_more.go +++ b/bindings/bindings/rollup_more.go @@ -13,7 +13,7 @@ const RollupStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"co var RollupStorageLayout = new(solc.StorageLayout) -var RollupDeployedBin = "0x608060405260043610610353575f3560e01c8063728cdbca116101bd578063b8d0a1b0116100f2578063d8dc99d211610092578063dff7827e1161006d578063dff7827e14610b1f578063e3fff1dd14610b34578063f2fde38b14610b53578063fb1e8b0414610b72575f80fd5b8063d8dc99d214610abf578063ddd8a3dc14610ad4578063de8b303514610b00575f80fd5b8063cd4edc69116100cd578063cd4edc6914610a59578063ce5db8d614610a6c578063cf9a674514610a81578063d279c19114610aa0575f80fd5b8063b8d0a1b0146109fc578063bedb86fb14610a1b578063c555389214610a3a575f80fd5b8063a479265d1161015d578063b31a77d311610138578063b31a77d31461098a578063b34844251461099f578063b35dac4e146109be578063b3e0a509146109dd575f80fd5b8063a479265d1461092b578063a4f209b014610940578063abc8d68d1461095f575f80fd5b80638f1d3776116101985780638f1d3776146107e3578063910129d4146108ad57806397fc007c146108de578063a415d8dc146108fd575f80fd5b8063728cdbca1461078157806388b1ea09146107a05780638da5cb5b146107b9575f80fd5b80632a213ba1116102935780635c975abb11610233578063612672901161020e578063612672901461070457806368589dfa146107235780636c578c1d1461074e578063715018a61461076d575f80fd5b80635c975abb146106415780635ef7a94a146106585780635f77cf1d146106b8575f80fd5b80633e001b661161026e5780633e001b66146105db578063428868b5146105f05780634e8f1d671461060357806357e0af6c14610622575f80fd5b80632a213ba1146105335780632b7ac3f31461055e5780633b70c18a146105af575f80fd5b806313361101116102fe5780631e8825be116102d95780631e8825be1461049f57806321e2f9e0146104be5780632362f03e146104dd5780632571098d14610508575f80fd5b8063133611011461043b57806318463fb01461045a57806318af3b2b1461046f575f80fd5b806310d445831161032e57806310d44583146103e5578063116a1f4214610404578063121dcd5014610426575f80fd5b806304d772151461035e578063059def61146103a15780630ceb6780146103c4575f80fd5b3661035a57005b5f80fd5b348015610369575f80fd5b5061038c610378366004615b74565b60a36020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156103ac575f80fd5b506103b6609d5481565b604051908152602001610398565b3480156103cf575f80fd5b506103e36103de366004615bb3565b610b87565b005b3480156103f0575f80fd5b506103e36103ff366004615c11565b610cab565b34801561040f575f80fd5b5061038c61041e366004615b74565b609d54101590565b348015610431575f80fd5b506103b6609e5481565b348015610446575f80fd5b506103e3610455366004615c59565b611097565b348015610465575f80fd5b506103b660a75481565b34801561047a575f80fd5b5061038c610489366004615b74565b5f90815260a26020526040902060010154421090565b3480156104aa575f80fd5b506103e36104b9366004615cbe565b6116b6565b3480156104c9575f80fd5b5061038c6104d8366004615b74565b611b64565b3480156104e8575f80fd5b506103b66104f7366004615b74565b60a16020525f908152604090205481565b348015610513575f80fd5b506103b6610522366004615b74565b60a06020525f908152604090205481565b34801561053e575f80fd5b506103b661054d366004615b74565b60ad6020525f908152604090205481565b348015610569575f80fd5b50609c5461058a9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610398565b3480156105ba575f80fd5b50609b5461058a9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156105e6575f80fd5b506103b660aa5481565b6103e36105fe366004615cbe565b611b92565b34801561060e575f80fd5b506103e361061d366004615d1e565b611fee565b34801561062d575f80fd5b506103e361063c366004615b74565b612478565b34801561064c575f80fd5b5060655460ff1661038c565b348015610663575f80fd5b50610698610672366004615b74565b60a26020525f908152604090208054600182015460028301546003909301549192909184565b604080519485526020850193909352918301526060820152608001610398565b3480156106c3575f80fd5b506106eb7f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff9091168152602001610398565b34801561070f575f80fd5b506103e361071e366004615b74565b61253d565b34801561072e575f80fd5b506103b661073d366004615b74565b60ab6020525f908152604090205481565b348015610759575f80fd5b506103e3610768366004615bb3565b6127a0565b348015610778575f80fd5b506103e36128af565b34801561078c575f80fd5b506103e361079b366004615dcf565b6128c2565b3480156107ab575f80fd5b5060a65461038c9060ff1681565b3480156107c4575f80fd5b5060335473ffffffffffffffffffffffffffffffffffffffff1661058a565b3480156107ee575f80fd5b5061085c6107fd366004615b74565b60a46020525f9081526040902080546001820154600283015460039093015467ffffffffffffffff8316936801000000000000000090930473ffffffffffffffffffffffffffffffffffffffff16929060ff8082169161010090041686565b6040805167ffffffffffffffff909716875273ffffffffffffffffffffffffffffffffffffffff909516602087015293850192909252606084015215156080830152151560a082015260c001610398565b3480156108b8575f80fd5b5061038c6108c7366004615b74565b5f90815260a4602052604090206003015460ff1690565b3480156108e9575f80fd5b506103e36108f8366004615bb3565b612c8b565b348015610908575f80fd5b5061038c610917366004615bb3565b609f6020525f908152604090205460ff1681565b348015610936575f80fd5b506103b660995481565b34801561094b575f80fd5b506103e361095a366004615b74565b612daf565b34801561096a575f80fd5b506103b6610979366004615bb3565b60a56020525f908152604090205481565b348015610995575f80fd5b506103b660a85481565b3480156109aa575f80fd5b506103e36109b9366004615e2a565b612e79565b3480156109c9575f80fd5b506103e36109d8366004615bb3565b613258565b3480156109e8575f80fd5b506103e36109f7366004615c59565b6132be565b348015610a07575f80fd5b506103e3610a16366004615e2a565b6136b7565b348015610a26575f80fd5b506103e3610a35366004615e9e565b61375a565b348015610a45575f80fd5b506103e3610a54366004615b74565b6138ed565b6103e3610a67366004615ed0565b6139aa565b348015610a77575f80fd5b506103b660985481565b348015610a8c575f80fd5b506103e3610a9b366004615b74565b6140bf565b348015610aab575f80fd5b506103e3610aba366004615bb3565b61429c565b348015610aca575f80fd5b506103b660ac5481565b348015610adf575f80fd5b5060975461058a9073ffffffffffffffffffffffffffffffffffffffff1681565b348015610b0b575f80fd5b5061038c610b1a366004615b74565b614382565b348015610b2a575f80fd5b506103b6609a5481565b348015610b3f575f80fd5b506103e3610b4e366004615b74565b6143d9565b348015610b5e575f80fd5b506103e3610b6d366004615bb3565b614496565b348015610b7d575f80fd5b506103b660a95481565b610b8f61454a565b73ffffffffffffffffffffffffffffffffffffffff81165f908152609f602052604090205460ff1615610c23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f6163636f756e7420697320616c72656164792061206368616c6c656e6765720060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f818152609f602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591519182527f7feb653c7b1f0d23daeed494225b3f28851cdc8973fcc653866d9b6e205fc00991015b60405180910390a250565b610cb361454a565b5f8111610d1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f636f756e74206d757374206265206e6f6e7a65726f00000000000000000000006044820152606401610c1a565b5f80610d2885856145cb565b915091505f610d3b836001015160c01c90565b5f81815260a160205260409020549091508214610db4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610c1a565b5f60a181610dc28785615f25565b81526020019081526020015f205414610e5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f726576657274696e67206d7573742073746172742066726f6d2074686520656e60448201527f64696e67000000000000000000000000000000000000000000000000000000006064820152608401610c1a565b609d548111610eed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f63616e206f6e6c792072657665727420756e46696e616c697a6564206261746360448201527f68000000000000000000000000000000000000000000000000000000000000006064820152608401610c1a565b610ef8600182615f38565b609e555b831561108f57604051829082907ecae2739091badfd91c373f0a16cede691e0cd25bb80cff77dd5caeb4710146905f90a35f81815260a16020526040812055610f4481614382565b15610fca575f81815260a4602090815260408083206001810154905468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16845260a59092528220805491929091610f9c908490615f25565b909155505060a680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b5f81815260a46020526040812080547fffffffff0000000000000000000000000000000000000000000000000000000016815560018101829055600281019190915560030180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905560a85415801590611047575060a85481145b15611051575f60a8555b6001015f81815260a160205260409020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90940193915081610efc575b505050505050565b60a85415611101576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610c1a565b61110961467e565b5f8061111584846145cb565b915091505f611128836001015160c01c90565b5f81815260a1602052604090205490915082146111a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610c1a565b6111aa81611b64565b611210576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6261746368206e6f7420657869737400000000000000000000000000000000006044820152606401610c1a565b61121981614382565b15611280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f626174636820696e206368616c6c656e676500000000000000000000000000006044820152606401610c1a565b5f81815260a4602052604090206003015460ff16156112fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f62617463682073686f756c6420626520726576657274000000000000000000006044820152606401610c1a565b5f81815260a26020526040902060010154421015611375576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f626174636820696e206368616c6c656e67652077696e646f77000000000000006044820152606401610c1a565b605983015160a05f611388600185615f38565b81526020019081526020015f2054146113fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f696e636f72726563742070726576696f757320737461746520726f6f740000006044820152606401610c1a565b5f81815260a0602052604090205415611472576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f626174636820616c7265616479207665726966696564000000000000000000006044820152606401610c1a565b80609d54600101146114e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f696e636f727265637420626174636820696e64657800000000000000000000006044820152606401610c1a565b609d819055600160a35f6114f5866099015190565b815260208101919091526040015f2080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905560798301515f82815260a06020526040902055611562611555846011015160c01c90565b600985015160c01c6146eb565b60a25f611570600184615f38565b815260208101919091526040015f908120818155600180820183905560028201839055600390910182905560ab91906115a99084615f38565b81526020019081526020015f205f905560ad5f6001836115c99190615f38565b81526020019081526020015f205f905560a45f6001836115e99190615f38565b815260208082019290925260409081015f90812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181018290556002810182905560030180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905583815260a1909252902054817f26ba82f907317eedc97d0cbef23de76a43dd6edb563bdb6e9407645b950a7a2d611692866079015190565b60998701516040805192835260208301919091520160405180910390a35050505050565b60975473ffffffffffffffffffffffffffffffffffffffff166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa15801561173c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117609190615f4b565b6117c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610c1a565b60a85415611830576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610c1a565b61183861467e565b5f49156118a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f636f6d6d69745374617465206d757374206e6f7420636172727920626c6f62006044820152606401610c1a565b5f6118b76118b26020850185615f66565b6145cb565b5090505f6118c9826001015160c01c90565b6118d4906001615f25565b5f81815260ad6020526040902054909150611971576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f6e6f2073746f72656420626c6f62206861736820666f7220746869732062617460448201527f63680000000000000000000000000000000000000000000000000000000000006064820152608401610c1a565b60ac54609b54604080517fb59b1a78000000000000000000000000000000000000000000000000000000008152905142939273ffffffffffffffffffffffffffffffffffffffff169163b59b1a789160048083019260209291908290030181865afa1580156119e2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a069190615fc7565b611a109190615f25565b1015611a92575f611a276080860160608701615fde565b61ffff1611611a92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610c1a565b6097545f9073ffffffffffffffffffffffffffffffffffffffff1663d096c3c6336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa158015611b1a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b3e9190615fc7565b9050611b5d85858360ad5f8781526020019081526020015f20546147b5565b5050505050565b5f81815260a2602052604081205415801590611b8c57505f82815260a1602052604090205415155b92915050565b60975473ffffffffffffffffffffffffffffffffffffffff166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa158015611c18573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c3c9190615f4b565b611ca2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610c1a565b60a85415611d0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610c1a565b611d1461467e565b5f611d256118b26020850185615f66565b5090505f611d37826001015160c01c90565b611d42906001615f25565b5f81815260ad602052604090205490915015611de0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f636f6d6d69744261746368207265717569726573206e6f2073746f726564206260448201527f6c6f6220686173680000000000000000000000000000000000000000000000006064820152608401610c1a565b60ac54609b54604080517fb59b1a78000000000000000000000000000000000000000000000000000000008152905142939273ffffffffffffffffffffffffffffffffffffffff169163b59b1a789160048083019260209291908290030181865afa158015611e51573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e759190615fc7565b611e7f9190615f25565b1015611f01575f611e966080860160608701615fde565b61ffff1611611f01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610c1a565b6097545f9073ffffffffffffffffffffffffffffffffffffffff1663d096c3c6336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa158015611f89573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fad9190615fc7565b90505f804915611fbe575f49611fe0565b7f010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c4440145b905061108f868684846147b5565b60a85415612058576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610c1a565b61206061467e565b60ac54609e545f90815260a26020526040812054909142916120829190615f25565b1090505f4260ac54609b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b59b1a786040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120f4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121189190615fc7565b6121229190615f25565b109050811580156121305750805b156121b1575f61214660808a0160608b01615fde565b61ffff16116121b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610c1a565b81806121ba5750805b612220576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f696e76616c69642074696d696e670000000000000000000000000000000000006044820152606401610c1a565b5f6122316118b260208b018b615f66565b5090505f612243826001015160c01c90565b61224e906001615f25565b5f81815260ad60205260408120549192509015612308575f49156122f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f6d757374206e6f7420636172727920626c6f62207768656e207573696e67207360448201527f746f72656420626c6f62206861736800000000000000000000000000000000006064820152608401610c1a565b505f81815260ad602052604090205461233b565b5f4915612316575f49612338565b7f010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c4440145b90505b6123478b8b5f846147b5565b5f806123538b8b6145cb565b915091505f612366836001015160c01c90565b905080609e54146123d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f696e636f727265637420626174636820686561646572000000000000000000006044820152606401610c1a565b5f81815260a160205260409020548214612449576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610c1a565b5f81815260a26020526040902042600190910155612468838b8b614f0d565b5050505050505050505050505050565b61248061454a565b5f8111801561249157506099548114155b6124f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f696e76616c6964206e65772070726f6f662077696e646f7700000000000000006044820152606401610c1a565b609980549082905560408051828152602081018490527f1e3a2094feb4b696dd3d7caea38ad2f41dbdcac3fa3943c7a693aff8a64b0a6191015b60405180910390a15050565b5f54600290610100900460ff1615801561255d57505f5460ff8083169116105b6125e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610c1a565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff8316176101001790556126245f5460ff1690565b60ff16600214612690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f6d757374206861766520696e697469616c697a656421000000000000000000006044820152606401610c1a565b8161271d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f63616e206e6f742073657420737461746520726f6f742077697468206279746560448201527f73333228302921000000000000000000000000000000000000000000000000006064820152608401610c1a565b609e545f90815260ab602052604090205461274657609e545f90815260ab602052604090208290555b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602001612531565b6127a861454a565b73ffffffffffffffffffffffffffffffffffffffff81165f908152609f602052604090205460ff16612836576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f6163636f756e74206973206e6f742061206368616c6c656e67657200000000006044820152606401610c1a565b73ffffffffffffffffffffffffffffffffffffffff81165f818152609f6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055519182527f7feb653c7b1f0d23daeed494225b3f28851cdc8973fcc653866d9b6e205fc0099101610ca0565b6128b761454a565b6128c05f6150e7565b565b5f54610100900460ff16158080156128e057505f54600160ff909116105b806128f95750303b1580156128f957505f5460ff166001145b612985576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610c1a565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156129e1575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b73ffffffffffffffffffffffffffffffffffffffff86161580612a18575073ffffffffffffffffffffffffffffffffffffffff8516155b15612a4f576040517fecc6fdf000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8716612acc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f696e76616c6964206c31207374616b696e6720636f6e747261637400000000006044820152606401610c1a565b612ad461515d565b612adc6151fb565b6097805473ffffffffffffffffffffffffffffffffffffffff808a167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255609b8054898416908316179055609c805492881692909116821790556098859055609984905560a98390556040515f907f728af3d16a5760405e27a082c98ab272e9f0a1d02f0085d41532a26093aedd96908290a3604080515f8152602081018690527fa577f4223f91f74e2dad65bbb8c30807587ae95d0d34288057bb3ec0d398a437910160405180910390a1604080515f8152602081018590527f1e3a2094feb4b696dd3d7caea38ad2f41dbdcac3fa3943c7a693aff8a64b0a61910160405180910390a1604080515f8152602081018490527ffb81bce17f015797e11949d3c332e2bf9453faf68f728447426803138f2b0223910160405180910390a18015612c82575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b612c9361454a565b73ffffffffffffffffffffffffffffffffffffffff811615801590612cd35750609c5473ffffffffffffffffffffffffffffffffffffffff828116911614155b612d39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f696e76616c6964206e65772076657269666965720000000000000000000000006044820152606401610c1a565b609c805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f728af3d16a5760405e27a082c98ab272e9f0a1d02f0085d41532a26093aedd96905f90a35050565b612db761454a565b5f81118015612dc7575060648111155b8015612dd5575060a9548114155b612e3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f696e76616c69642070726f6f66207265776172642070657263656e74616765006044820152606401610c1a565b60a980549082905560408051828152602081018490527ffb81bce17f015797e11949d3c332e2bf9453faf68f728447426803138f2b02239101612531565b60a85415612ee3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610c1a565b612eeb61467e565b60975473ffffffffffffffffffffffffffffffffffffffff166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa158015612f71573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f959190615f4b565b612ffb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610c1a565b5f8061300786866145cb565b915091505f61301a836001015160c01c90565b5f81815260a160205260409020549091508214613093576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610c1a565b61309c81614382565b613102576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f626174636820696e206368616c6c656e676500000000000000000000000000006044820152606401610c1a565b5f81815260a4602052604090206003810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010017905560a680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055609954600290910154429161317991615f25565b1161320d575f81815260a460209081526040808320600390810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905560a2835292819020909201548251808401909352600783527f54696d656f7574000000000000000000000000000000000000000000000000009183019190915261320891839190615299565b612c82565b613218838686614f0d565b612c8281336040518060400160405280600d81526020017f50726f6f6620737563636573730000000000000000000000000000000000000081525061541c565b61326061454a565b60aa80545f9091556132728282615502565b6040805173ffffffffffffffffffffffffffffffffffffffff84168152602081018390527fb1b2058a6969e2d25e47bcaebe8ae21c29a23b2752429315b75e2f4f285f3d879101612531565b6132c661454a565b5f805260a06020527fb84a74ec6ef4d0e83b6006dfaa014ab4026f9f3b97d186e604d29998a4e808ea5415613357576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f67656e6573697320626174636820696d706f72746564000000000000000000006044820152606401610c1a565b5f8061336384846145cb565b915091505f613376836001015160c01c90565b905080156133e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420626174636820696e646578000000000000000000000000006044820152606401610c1a565b5f6133ec846079015190565b905080613455576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f7a65726f20737461746520726f6f7400000000000000000000000000000000006044820152606401610c1a565b600984015160c01c156134c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6c31206d65737361676520706f707065642073686f756c6420626520300000006044820152606401610c1a565b5f6134d0856019015190565b03613537576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7a65726f206461746120686173680000000000000000000000000000000000006044820152606401610c1a565b7f010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014613563856039015190565b146135ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f696e76616c69642076657273696f6e65642068617368000000000000000000006044820152606401610c1a565b5f82815260a1602090815260408083208690558051608081018252428082528184019081528183018581526060830186815288875260a28652848720935184559151600184015551600283015551600390910155603987015160ad83528184205560ab825280832084905560a0909152808220839055609e849055609d84905551849184917f2c32d4ae151744d0bf0b9464a3e897a1d17ed2f1af71f7c9a75f12ce0d28238f9190a3604080518281525f6020820152849184917f26ba82f907317eedc97d0cbef23de76a43dd6edb563bdb6e9407645b950a7a2d910160405180910390a3505050505050565b5f806136c386866145cb565b915091505f6136d6836001015160c01c90565b5f81815260a16020526040902054909150821461374f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610c1a565b612c82838686614f0d565b61376261454a565b80156138bb576137706155d4565b60a65460ff161561386d5760a7545f90815260a4602090815260408083206001810154905468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16845260a590925282208054919290916137d1908490615f25565b909155505060a7545f90815260a46020526040812080547fffffffff0000000000000000000000000000000000000000000000000000000016815560018101829055600281019190915560030180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905560a680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b7f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a150565b6138c3615659565b7f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33613890565b50565b6138f561454a565b5f81118015613906575060ac548114155b61396c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f696e76616c6964206e657720726f6c6c75702064656c617920706572696f64006044820152606401610c1a565b60ac80549082905560408051828152602081018490527f624e47dc9fb8f8cfeaf4ead4710277cc1757136cfa885e465514cf6d510f0ad19101612531565b335f908152609f602052604090205460ff16613a22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f6f6e6c79206368616c6c656e67657220616c6c6f7765640000000000000000006044820152606401610c1a565b60a85415613a8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610c1a565b613a9461467e565b60a65460ff1615613b01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f616c726561647920696e206368616c6c656e67650000000000000000000000006044820152606401610c1a565b8167ffffffffffffffff16609d5410613b76576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f626174636820616c72656164792066696e616c697a65640000000000000000006044820152606401610c1a565b67ffffffffffffffff82165f90815260a160205260409020548114613bf7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610c1a565b613c0a8267ffffffffffffffff16611b64565b613c70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6261746368206e6f7420657869737400000000000000000000000000000000006044820152606401610c1a565b67ffffffffffffffff82165f90815260a4602052604090205468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1615613d12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f626174636820616c7265616479206368616c6c656e67656400000000000000006044820152606401610c1a565b67ffffffffffffffff82165f90815260a260205260409020600101544210613dbc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f63616e6e6f74206368616c6c656e6765206261746368206f757473696465207460448201527f6865206368616c6c656e67652077696e646f77000000000000000000000000006064820152608401610c1a565b60975f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630d13fd7b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613e26573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613e4a9190615fc7565b341015613eb3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f696e73756666696369656e742076616c756500000000000000000000000000006044820152606401610c1a565b67ffffffffffffffff82811660a78190556040805160c0810182528281523360208083018281523484860190815242606086019081525f6080870181815260a0880182815299825260a49095529690962094518554925173ffffffffffffffffffffffffffffffffffffffff1668010000000000000000027fffffffff00000000000000000000000000000000000000000000000000000000909316981697909717178355945160018301559151600282015592516003909301805492511515610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff941515949094167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009093169290921792909217905573ffffffffffffffffffffffffffffffffffffffff168267ffffffffffffffff167f3a6ea19df25b49e7624e313ce7c1ab23984238e93727260db56a81735b1b99763460405161401f91815260200190565b60405180910390a35f609d5460016140379190615f25565b90505b609e54811161408f578267ffffffffffffffff16811461407d576099545f82815260a2602052604081206001018054909190614077908490615f25565b90915550505b8061408781615fff565b91505061403a565b505060a680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905550565b5f54600390610100900460ff161580156140df57505f5460ff8083169116105b61416b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610c1a565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff831617610100178155829003614204576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f696e76616c696420726f6c6c75702064656c617920706572696f6400000000006044820152606401610c1a565b60ac829055604080515f8152602081018490527f624e47dc9fb8f8cfeaf4ead4710277cc1757136cfa885e465514cf6d510f0ad1910160405180910390a15f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602001612531565b335f90815260a5602052604081205490819003614315576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f696e76616c69642062617463684368616c6c656e6765526577617264000000006044820152606401610c1a565b335f90815260a5602052604081205561432e8282615502565b8173ffffffffffffffffffffffffffffffffffffffff167f9c25fa83f414ed363c8d39c98fb3e17567b3431cede71eb062c49d2a63ce247a8260405161437691815260200190565b60405180910390a25050565b5f81815260a4602052604081205468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1615801590611b8c5750505f90815260a46020526040902060030154610100900460ff161590565b6143e161454a565b5f811180156143f257506098548114155b614458576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f696e76616c6964206e65772066696e616c697a6520706572696f6400000000006044820152606401610c1a565b609880549082905560408051828152602081018490527fa577f4223f91f74e2dad65bbb8c30807587ae95d0d34288057bb3ec0d398a4379101612531565b61449e61454a565b73ffffffffffffffffffffffffffffffffffffffff8116614541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610c1a565b6138ea816150e7565b60335473ffffffffffffffffffffffffffffffffffffffff1633146128c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c1a565b5f805f6145d885856156b0565b90505f8160ff165f036145f9576145ef868661573a565b9094509050614670565b8160ff1660010361460e576145ef86866157bd565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f556e737570706f727465642062617463682076657273696f6e000000000000006044820152606401610c1a565b808420925050509250929050565b60655460ff16156128c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610c1a565b805f036146f6575050565b8082035f5b828110156147af5761010081840381111561471557508083035b609b546040517f3c7f5283000000000000000000000000000000000000000000000000000000008152600481018590526024810183905273ffffffffffffffffffffffffffffffffffffffff90911690633c7f5283906044015f604051808303815f87803b158015614785575f80fd5b505af1158015614797573d5f803e3d5ffd5b505050506101008301925050610100810190506146fb565b50505050565b6147c26020850185616036565b60ff1615806147e057506147d96020850185616036565b60ff166001145b614846576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f696e76616c69642076657273696f6e00000000000000000000000000000000006044820152606401610c1a565b60808401356148b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f70726576696f757320737461746520726f6f74206973207a65726f00000000006044820152606401610c1a565b60a084013561491c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f6e657720737461746520726f6f74206973207a65726f000000000000000000006044820152606401610c1a565b5f8061492e6118b26020880188615f66565b915091505f614941836001015160c01c90565b90505f60a181614952846001615f25565b81526020019081526020015f2054146149c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f626174636820616c726561647920636f6d6d69747465640000000000000000006044820152606401610c1a565b609e548114614a32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f696e636f727265637420626174636820696e64657800000000000000000000006044820152606401610c1a565b5f81815260a160205260409020548214614aa8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f696e636f727265637420706172656e74206261746368206861736800000000006044820152606401610c1a565b5f81815260ab6020526040902054608088013514614b22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f696e636f72726563742070726576696f757320737461746520726f6f740000006044820152606401610c1a565b5f614b31846011015160c01c90565b90505f614b5d614b4760608b0160408c01616056565b614b5760808c0160608d01615fde565b8461582a565b9050614b6f60808a0160608b01615fde565b6001939093019261ffff1691909101908560f9614b8f60208c018c616036565b60ff16600103614b9e57506101015b604080518281019091529650614bc387614bbb60208e018e616036565b60ff1661586e565b60c085901b6001880152614bf187614be160808e0160608f01615fde565b61ffff1660c01b60099190910152565b60c084811b6011890152601988018490526039880183905260808c0135605989015260a08c013560798901528b01356099880152614c5587614c3660208d018d615f66565b604051614c4492919061606f565b604051809103902060b99190910152565b60d987018690526001614c6b60208d018d616036565b60ff1610614c9d57614c9d87614c8760608e0160408f01616056565b67ffffffffffffffff1660c01b60f99190910152565b8087205f86815260a1602090815260408083209390935560ab815282822060a08f0135905560ad905290812083905560a65460ff1615614d065760a7545f90815260a460205260409020600201546099544291614cf991615f25565b614d039190615f38565b90505b60405180608001604052804281526020018260985442614d269190615f25565b614d309190615f25565b81526020018d6040016020810190614d489190616056565b67ffffffffffffffff16815260209081018c90525f88815260a2825260409081902083518155838301516001820155908301516002820155606090920151600390920191909155609e87905560975473ffffffffffffffffffffffffffffffffffffffff1692506374fe27b791508b3590614dcf90614dc9908e018e615f66565b5f615875565b5f614ddd60408f018f615f66565b6040518663ffffffff1660e01b8152600401614dfd9594939291906160c5565b602060405180830381865afa158015614e18573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614e3c9190615f4b565b614ec8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f746865207369676e617475726520766572696669636174696f6e206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610c1a565b5f84815260a16020526040808220549051909186917f2c32d4ae151744d0bf0b9464a3e897a1d17ed2f1af71f7c9a75f12ce0d28238f9190a350505050505050505050565b80614f74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496e76616c69642062617463682070726f6f66000000000000000000000000006044820152606401610c1a565b5f614f83846001015160c01c90565b90505f614f91856039015190565b90505f7f0000000000000000000000000000000000000000000000000000000000000000614fc0876059015190565b6079880151609989015160b98a015160198b015160405160c09690961b7fffffffffffffffff000000000000000000000000000000000000000000000000166020870152602886019490945260488501929092526068840152608883015260a882015260c8810183905260e801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120609c5490915073ffffffffffffffffffffffffffffffffffffffff16632c09a84861508f885160f81c90565b858888866040518663ffffffff1660e01b81526004016150b3959493929190616145565b5f6040518083038186803b1580156150c9575f80fd5b505afa1580156150db573d5f803e3d5ffd5b50505050505050505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f54610100900460ff166151f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610c1a565b6128c06158c9565b5f54610100900460ff16615291576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610c1a565b6128c0615989565b60a88390555f83815260a460205260408082205460975491517f45bc4d10000000000000000000000000000000000000000000000000000000008152600481018690526801000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116939216906345bc4d10906024016020604051808303815f875af115801561532a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061534e9190615fc7565b5f86815260a4602052604090206001015490915061536d908290615f25565b5f86815260a4602090815260408083205468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16835260a5909152812080549091906153b9908490615f25565b90915550506040516153cc908490616176565b6040519081900381209073ffffffffffffffffffffffffffffffffffffffff84169087907fe70d3820e244d5f71d1a6395db24f3460e8dca966edc1fd3625b6292880a877a905f90a45050505050565b5f83815260a4602052604081206001015460a95490919060649061544090846161a2565b61544a91906161b9565b90506154568183615f38565b60aa5f8282546154669190615f25565b909155505073ffffffffffffffffffffffffffffffffffffffff84165f90815260a560205260408120805483929061549f908490615f25565b90915550506040516154b2908490616176565b6040519081900381209073ffffffffffffffffffffffffffffffffffffffff86169087907fe70d3820e244d5f71d1a6395db24f3460e8dca966edc1fd3625b6292880a877a905f90a45050505050565b80156155d0575f8273ffffffffffffffffffffffffffffffffffffffff16826040515f6040518083038185875af1925050503d805f811461555e576040519150601f19603f3d011682016040523d82523d5f602084013e615563565b606091505b50509050806155ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f526f6c6c75703a20455448207472616e73666572206661696c656400000000006044820152606401610c1a565b505b5050565b6155dc61467e565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861562f3390565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b615661615a28565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa3361562f565b5f81615718576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f456d7074792062617463682068656164657200000000000000000000000000006044820152606401610c1a565b82825f81811061572a5761572a6161f1565b919091013560f81c949350505050565b5f8160f98110156157a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f626174636820686561646572206c656e67746820746f6f20736d616c6c0000006044820152606401610c1a565b6040519150808483378082016040529250929050565b5f8161010181146157a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f626174636820686561646572206c656e67746820697320696e636f72726563746044820152606401610c1a565b6040805160c085901b815260f084901b6008820152600a60208502820181019092525f91810161585f8161ffff871686615a94565b82900390912095945050505050565b8082535050565b60605f80808080615888888a018a61630b565b95509550955095509550508187106158a65794506158c29350505050565b8387106158ba5782955050505050506158c2565b509293505050505b9392505050565b5f54610100900460ff1661595f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610c1a565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b5f54610100900460ff16615a1f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610c1a565b6128c0336150e7565b60655460ff166128c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610c1a565b5f825f03615aa35750826158c2565b609b5473ffffffffffffffffffffffffffffffffffffffff165f5b84811015615b6a576040517fae453cd5000000000000000000000000000000000000000000000000000000008152600481018590525f9073ffffffffffffffffffffffffffffffffffffffff84169063ae453cd590602401602060405180830381865afa158015615b31573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190615b559190615fc7565b87525060209095019460019384019301615abe565b5093949350505050565b5f60208284031215615b84575f80fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114615bae575f80fd5b919050565b5f60208284031215615bc3575f80fd5b6158c282615b8b565b5f8083601f840112615bdc575f80fd5b50813567ffffffffffffffff811115615bf3575f80fd5b602083019150836020828501011115615c0a575f80fd5b9250929050565b5f805f60408486031215615c23575f80fd5b833567ffffffffffffffff811115615c39575f80fd5b615c4586828701615bcc565b909790965060209590950135949350505050565b5f8060208385031215615c6a575f80fd5b823567ffffffffffffffff811115615c80575f80fd5b615c8c85828601615bcc565b90969095509350505050565b5f60e08284031215615ca8575f80fd5b50919050565b5f60608284031215615ca8575f80fd5b5f8060408385031215615ccf575f80fd5b823567ffffffffffffffff80821115615ce6575f80fd5b615cf286838701615c98565b93506020850135915080821115615d07575f80fd5b50615d1485828601615cae565b9150509250929050565b5f805f805f8060808789031215615d33575f80fd5b863567ffffffffffffffff80821115615d4a575f80fd5b615d568a838b01615c98565b97506020890135915080821115615d6b575f80fd5b615d778a838b01615cae565b96506040890135915080821115615d8c575f80fd5b615d988a838b01615bcc565b90965094506060890135915080821115615db0575f80fd5b50615dbd89828a01615bcc565b979a9699509497509295939492505050565b5f805f805f8060c08789031215615de4575f80fd5b615ded87615b8b565b9550615dfb60208801615b8b565b9450615e0960408801615b8b565b9350606087013592506080870135915060a087013590509295509295509295565b5f805f8060408587031215615e3d575f80fd5b843567ffffffffffffffff80821115615e54575f80fd5b615e6088838901615bcc565b90965094506020870135915080821115615e78575f80fd5b50615e8587828801615bcc565b95989497509550505050565b80151581146138ea575f80fd5b5f60208284031215615eae575f80fd5b81356158c281615e91565b803567ffffffffffffffff81168114615bae575f80fd5b5f8060408385031215615ee1575f80fd5b615eea83615eb9565b946020939093013593505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115611b8c57611b8c615ef8565b81810381811115611b8c57611b8c615ef8565b5f60208284031215615f5b575f80fd5b81516158c281615e91565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615f99575f80fd5b83018035915067ffffffffffffffff821115615fb3575f80fd5b602001915036819003821315615c0a575f80fd5b5f60208284031215615fd7575f80fd5b5051919050565b5f60208284031215615fee575f80fd5b813561ffff811681146158c2575f80fd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361602f5761602f615ef8565b5060010190565b5f60208284031215616046575f80fd5b813560ff811681146158c2575f80fd5b5f60208284031215616066575f80fd5b6158c282615eb9565b818382375f9101908152919050565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f6080820187835260206080602085015281885180845260a08601915060208a0193505f5b8181101561611c57845173ffffffffffffffffffffffffffffffffffffffff16835293830193918301916001016160ea565b5050876040860152848103606086015261613781878961607e565b9a9950505050505050505050565b858152846020820152608060408201525f61616460808301858761607e565b90508260608301529695505050505050565b5f82515f5b81811015616195576020818601810151858301520161617b565b505f920191825250919050565b8082028115828204841417611b8c57611b8c615ef8565b5f826161ec577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f83011261625a575f80fd5b8135602067ffffffffffffffff808311156162775761627761621e565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811084821117156162ba576162ba61621e565b60405293845260208187018101949081019250878511156162d9575f80fd5b6020870191505b84821015616300576162f182615b8b565b835291830191908301906162e0565b979650505050505050565b5f805f805f8060c08789031215616320575f80fd5b86359550602087013567ffffffffffffffff8082111561633e575f80fd5b61634a8a838b0161624b565b9650604089013595506060890135915080821115616366575f80fd5b6163728a838b0161624b565b94506080890135935060a089013591508082111561638e575f80fd5b5061639b89828a0161624b565b915050929550929550929556fea164736f6c6343000818000a" +var RollupDeployedBin = "0x608060405260043610610353575f3560e01c8063728cdbca116101bd578063b8d0a1b0116100f2578063d8dc99d211610092578063dff7827e1161006d578063dff7827e14610b1f578063e3fff1dd14610b34578063f2fde38b14610b53578063fb1e8b0414610b72575f80fd5b8063d8dc99d214610abf578063ddd8a3dc14610ad4578063de8b303514610b00575f80fd5b8063cd4edc69116100cd578063cd4edc6914610a59578063ce5db8d614610a6c578063cf9a674514610a81578063d279c19114610aa0575f80fd5b8063b8d0a1b0146109fc578063bedb86fb14610a1b578063c555389214610a3a575f80fd5b8063a479265d1161015d578063b31a77d311610138578063b31a77d31461098a578063b34844251461099f578063b35dac4e146109be578063b3e0a509146109dd575f80fd5b8063a479265d1461092b578063a4f209b014610940578063abc8d68d1461095f575f80fd5b80638f1d3776116101985780638f1d3776146107e3578063910129d4146108ad57806397fc007c146108de578063a415d8dc146108fd575f80fd5b8063728cdbca1461078157806388b1ea09146107a05780638da5cb5b146107b9575f80fd5b80632a213ba1116102935780635c975abb11610233578063612672901161020e578063612672901461070457806368589dfa146107235780636c578c1d1461074e578063715018a61461076d575f80fd5b80635c975abb146106415780635ef7a94a146106585780635f77cf1d146106b8575f80fd5b80633e001b661161026e5780633e001b66146105db578063428868b5146105f05780634e8f1d671461060357806357e0af6c14610622575f80fd5b80632a213ba1146105335780632b7ac3f31461055e5780633b70c18a146105af575f80fd5b806313361101116102fe5780631e8825be116102d95780631e8825be1461049f57806321e2f9e0146104be5780632362f03e146104dd5780632571098d14610508575f80fd5b8063133611011461043b57806318463fb01461045a57806318af3b2b1461046f575f80fd5b806310d445831161032e57806310d44583146103e5578063116a1f4214610404578063121dcd5014610426575f80fd5b806304d772151461035e578063059def61146103a15780630ceb6780146103c4575f80fd5b3661035a57005b5f80fd5b348015610369575f80fd5b5061038c610378366004615c9f565b60a36020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156103ac575f80fd5b506103b6609d5481565b604051908152602001610398565b3480156103cf575f80fd5b506103e36103de366004615cd9565b610b87565b005b3480156103f0575f80fd5b506103e36103ff366004615d37565b610cab565b34801561040f575f80fd5b5061038c61041e366004615c9f565b609d54101590565b348015610431575f80fd5b506103b6609e5481565b348015610446575f80fd5b506103e3610455366004615d7f565b611097565b348015610465575f80fd5b506103b660a75481565b34801561047a575f80fd5b5061038c610489366004615c9f565b5f90815260a26020526040902060010154421090565b3480156104aa575f80fd5b506103e36104b9366004615dde565b6116b6565b3480156104c9575f80fd5b5061038c6104d8366004615c9f565b611b64565b3480156104e8575f80fd5b506103b66104f7366004615c9f565b60a16020525f908152604090205481565b348015610513575f80fd5b506103b6610522366004615c9f565b60a06020525f908152604090205481565b34801561053e575f80fd5b506103b661054d366004615c9f565b60ad6020525f908152604090205481565b348015610569575f80fd5b50609c5461058a9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610398565b3480156105ba575f80fd5b50609b5461058a9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156105e6575f80fd5b506103b660aa5481565b6103e36105fe366004615dde565b611b92565b34801561060e575f80fd5b506103e361061d366004615e3e565b611fd6565b34801561062d575f80fd5b506103e361063c366004615c9f565b612440565b34801561064c575f80fd5b5060655460ff1661038c565b348015610663575f80fd5b50610698610672366004615c9f565b60a26020525f908152604090208054600182015460028301546003909301549192909184565b604080519485526020850193909352918301526060820152608001610398565b3480156106c3575f80fd5b506106eb7f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff9091168152602001610398565b34801561070f575f80fd5b506103e361071e366004615c9f565b612505565b34801561072e575f80fd5b506103b661073d366004615c9f565b60ab6020525f908152604090205481565b348015610759575f80fd5b506103e3610768366004615cd9565b612768565b348015610778575f80fd5b506103e3612877565b34801561078c575f80fd5b506103e361079b366004615eef565b61288a565b3480156107ab575f80fd5b5060a65461038c9060ff1681565b3480156107c4575f80fd5b5060335473ffffffffffffffffffffffffffffffffffffffff1661058a565b3480156107ee575f80fd5b5061085c6107fd366004615c9f565b60a46020525f9081526040902080546001820154600283015460039093015467ffffffffffffffff8316936801000000000000000090930473ffffffffffffffffffffffffffffffffffffffff16929060ff8082169161010090041686565b6040805167ffffffffffffffff909716875273ffffffffffffffffffffffffffffffffffffffff909516602087015293850192909252606084015215156080830152151560a082015260c001610398565b3480156108b8575f80fd5b5061038c6108c7366004615c9f565b5f90815260a4602052604090206003015460ff1690565b3480156108e9575f80fd5b506103e36108f8366004615cd9565b612c53565b348015610908575f80fd5b5061038c610917366004615cd9565b609f6020525f908152604090205460ff1681565b348015610936575f80fd5b506103b660995481565b34801561094b575f80fd5b506103e361095a366004615c9f565b612d77565b34801561096a575f80fd5b506103b6610979366004615cd9565b60a56020525f908152604090205481565b348015610995575f80fd5b506103b660a85481565b3480156109aa575f80fd5b506103e36109b9366004615f4a565b612e41565b3480156109c9575f80fd5b506103e36109d8366004615cd9565b613220565b3480156109e8575f80fd5b506103e36109f7366004615d7f565b613286565b348015610a07575f80fd5b506103e3610a16366004615f4a565b61367f565b348015610a26575f80fd5b506103e3610a35366004615fbe565b613722565b348015610a45575f80fd5b506103e3610a54366004615c9f565b6138b5565b6103e3610a67366004615ff0565b613972565b348015610a77575f80fd5b506103b660985481565b348015610a8c575f80fd5b506103e3610a9b366004615c9f565b614087565b348015610aab575f80fd5b506103e3610aba366004615cd9565b614264565b348015610aca575f80fd5b506103b660ac5481565b348015610adf575f80fd5b5060975461058a9073ffffffffffffffffffffffffffffffffffffffff1681565b348015610b0b575f80fd5b5061038c610b1a366004615c9f565b61434a565b348015610b2a575f80fd5b506103b6609a5481565b348015610b3f575f80fd5b506103e3610b4e366004615c9f565b6143a1565b348015610b5e575f80fd5b506103e3610b6d366004615cd9565b61445e565b348015610b7d575f80fd5b506103b660a95481565b610b8f614512565b73ffffffffffffffffffffffffffffffffffffffff81165f908152609f602052604090205460ff1615610c23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f6163636f756e7420697320616c72656164792061206368616c6c656e6765720060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81165f818152609f602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915591519182527f7feb653c7b1f0d23daeed494225b3f28851cdc8973fcc653866d9b6e205fc00991015b60405180910390a250565b610cb3614512565b5f8111610d1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f636f756e74206d757374206265206e6f6e7a65726f00000000000000000000006044820152606401610c1a565b5f80610d288585614593565b915091505f610d3b836001015160c01c90565b5f81815260a160205260409020549091508214610db4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610c1a565b5f60a181610dc28785616045565b81526020019081526020015f205414610e5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f726576657274696e67206d7573742073746172742066726f6d2074686520656e60448201527f64696e67000000000000000000000000000000000000000000000000000000006064820152608401610c1a565b609d548111610eed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f63616e206f6e6c792072657665727420756e46696e616c697a6564206261746360448201527f68000000000000000000000000000000000000000000000000000000000000006064820152608401610c1a565b610ef8600182616058565b609e555b831561108f57604051829082907ecae2739091badfd91c373f0a16cede691e0cd25bb80cff77dd5caeb4710146905f90a35f81815260a16020526040812055610f448161434a565b15610fca575f81815260a4602090815260408083206001810154905468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16845260a59092528220805491929091610f9c908490616045565b909155505060a680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b5f81815260a46020526040812080547fffffffff0000000000000000000000000000000000000000000000000000000016815560018101829055600281019190915560030180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905560a85415801590611047575060a85481145b15611051575f60a8555b6001015f81815260a160205260409020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90940193915081610efc575b505050505050565b60a85415611101576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610c1a565b611109614655565b5f806111158484614593565b915091505f611128836001015160c01c90565b5f81815260a1602052604090205490915082146111a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610c1a565b6111aa81611b64565b611210576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6261746368206e6f7420657869737400000000000000000000000000000000006044820152606401610c1a565b6112198161434a565b15611280576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f626174636820696e206368616c6c656e676500000000000000000000000000006044820152606401610c1a565b5f81815260a4602052604090206003015460ff16156112fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f62617463682073686f756c6420626520726576657274000000000000000000006044820152606401610c1a565b5f81815260a26020526040902060010154421015611375576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f626174636820696e206368616c6c656e67652077696e646f77000000000000006044820152606401610c1a565b605983015160a05f611388600185616058565b81526020019081526020015f2054146113fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f696e636f72726563742070726576696f757320737461746520726f6f740000006044820152606401610c1a565b5f81815260a0602052604090205415611472576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f626174636820616c7265616479207665726966696564000000000000000000006044820152606401610c1a565b80609d54600101146114e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f696e636f727265637420626174636820696e64657800000000000000000000006044820152606401610c1a565b609d819055600160a35f6114f5866099015190565b815260208101919091526040015f2080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905560798301515f82815260a06020526040902055611562611555846011015160c01c90565b600985015160c01c6146c2565b60a25f611570600184616058565b815260208101919091526040015f908120818155600180820183905560028201839055600390910182905560ab91906115a99084616058565b81526020019081526020015f205f905560ad5f6001836115c99190616058565b81526020019081526020015f205f905560a45f6001836115e99190616058565b815260208082019290925260409081015f90812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181018290556002810182905560030180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905583815260a1909252902054817f26ba82f907317eedc97d0cbef23de76a43dd6edb563bdb6e9407645b950a7a2d611692866079015190565b60998701516040805192835260208301919091520160405180910390a35050505050565b60975473ffffffffffffffffffffffffffffffffffffffff166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa15801561173c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611760919061606b565b6117c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610c1a565b60a85415611830576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610c1a565b611838614655565b5f49156118a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f636f6d6d69745374617465206d757374206e6f7420636172727920626c6f62006044820152606401610c1a565b5f6118b76118b26020850185616086565b614593565b5090505f6118c9826001015160c01c90565b6118d4906001616045565b5f81815260ad6020526040902054909150611971576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f6e6f2073746f72656420626c6f62206861736820666f7220746869732062617460448201527f63680000000000000000000000000000000000000000000000000000000000006064820152608401610c1a565b60ac54609b54604080517fb59b1a78000000000000000000000000000000000000000000000000000000008152905142939273ffffffffffffffffffffffffffffffffffffffff169163b59b1a789160048083019260209291908290030181865afa1580156119e2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a0691906160e7565b611a109190616045565b1015611a92575f611a2760808601606087016160fe565b61ffff1611611a92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610c1a565b6097545f9073ffffffffffffffffffffffffffffffffffffffff1663d096c3c6336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa158015611b1a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b3e91906160e7565b9050611b5d85858360ad5f8781526020019081526020015f205461478c565b5050505050565b5f81815260a2602052604081205415801590611b8c57505f82815260a1602052604090205415155b92915050565b60975473ffffffffffffffffffffffffffffffffffffffff166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa158015611c18573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c3c919061606b565b611ca2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610c1a565b60a85415611d0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610c1a565b611d14614655565b5f611d256118b26020850185616086565b5090505f611d37826001015160c01c90565b611d42906001616045565b5f81815260ad602052604090205490915015611de0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f636f6d6d69744261746368207265717569726573206e6f2073746f726564206260448201527f6c6f6220686173680000000000000000000000000000000000000000000000006064820152608401610c1a565b60ac54609b54604080517fb59b1a78000000000000000000000000000000000000000000000000000000008152905142939273ffffffffffffffffffffffffffffffffffffffff169163b59b1a789160048083019260209291908290030181865afa158015611e51573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e7591906160e7565b611e7f9190616045565b1015611f01575f611e9660808601606087016160fe565b61ffff1611611f01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610c1a565b6097545f9073ffffffffffffffffffffffffffffffffffffffff1663d096c3c6336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa158015611f89573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fad91906160e7565b90505f611fc8611fc0602088018861611f565b60ff16614ec9565b905061108f8686848461478c565b60a85415612040576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610c1a565b612048614655565b60ac54609e545f90815260a260205260408120549091429161206a9190616045565b1090505f4260ac54609b5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b59b1a786040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120dc573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061210091906160e7565b61210a9190616045565b109050811580156121185750805b15612199575f61212e60808a0160608b016160fe565b61ffff1611612199576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f6c316d73672064656c61790000000000000000000000000000000000000000006044820152606401610c1a565b81806121a25750805b612208576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f696e76616c69642074696d696e670000000000000000000000000000000000006044820152606401610c1a565b5f6122196118b260208b018b616086565b5090505f61222b826001015160c01c90565b612236906001616045565b5f81815260ad602052604081205491925090156122f0575f49156122dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f6d757374206e6f7420636172727920626c6f62207768656e207573696e67207360448201527f746f72656420626c6f62206861736800000000000000000000000000000000006064820152608401610c1a565b505f81815260ad6020526040902054612303565b612300611fc060208d018d61611f565b90505b61230f8b8b5f8461478c565b5f8061231b8b8b614593565b915091505f61232e836001015160c01c90565b905080609e541461239b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f696e636f727265637420626174636820686561646572000000000000000000006044820152606401610c1a565b5f81815260a160205260409020548214612411576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610c1a565b5f81815260a26020526040902042600190910155612430838b8b615038565b5050505050505050505050505050565b612448614512565b5f8111801561245957506099548114155b6124bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f696e76616c6964206e65772070726f6f662077696e646f7700000000000000006044820152606401610c1a565b609980549082905560408051828152602081018490527f1e3a2094feb4b696dd3d7caea38ad2f41dbdcac3fa3943c7a693aff8a64b0a6191015b60405180910390a15050565b5f54600290610100900460ff1615801561252557505f5460ff8083169116105b6125b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610c1a565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff8316176101001790556125ec5f5460ff1690565b60ff16600214612658576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f6d757374206861766520696e697469616c697a656421000000000000000000006044820152606401610c1a565b816126e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f63616e206e6f742073657420737461746520726f6f742077697468206279746560448201527f73333228302921000000000000000000000000000000000000000000000000006064820152608401610c1a565b609e545f90815260ab602052604090205461270e57609e545f90815260ab602052604090208290555b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020016124f9565b612770614512565b73ffffffffffffffffffffffffffffffffffffffff81165f908152609f602052604090205460ff166127fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f6163636f756e74206973206e6f742061206368616c6c656e67657200000000006044820152606401610c1a565b73ffffffffffffffffffffffffffffffffffffffff81165f818152609f6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055519182527f7feb653c7b1f0d23daeed494225b3f28851cdc8973fcc653866d9b6e205fc0099101610ca0565b61287f614512565b6128885f615212565b565b5f54610100900460ff16158080156128a857505f54600160ff909116105b806128c15750303b1580156128c157505f5460ff166001145b61294d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610c1a565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156129a9575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b73ffffffffffffffffffffffffffffffffffffffff861615806129e0575073ffffffffffffffffffffffffffffffffffffffff8516155b15612a17576040517fecc6fdf000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8716612a94576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f696e76616c6964206c31207374616b696e6720636f6e747261637400000000006044820152606401610c1a565b612a9c615288565b612aa4615326565b6097805473ffffffffffffffffffffffffffffffffffffffff808a167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255609b8054898416908316179055609c805492881692909116821790556098859055609984905560a98390556040515f907f728af3d16a5760405e27a082c98ab272e9f0a1d02f0085d41532a26093aedd96908290a3604080515f8152602081018690527fa577f4223f91f74e2dad65bbb8c30807587ae95d0d34288057bb3ec0d398a437910160405180910390a1604080515f8152602081018590527f1e3a2094feb4b696dd3d7caea38ad2f41dbdcac3fa3943c7a693aff8a64b0a61910160405180910390a1604080515f8152602081018490527ffb81bce17f015797e11949d3c332e2bf9453faf68f728447426803138f2b0223910160405180910390a18015612c4a575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b612c5b614512565b73ffffffffffffffffffffffffffffffffffffffff811615801590612c9b5750609c5473ffffffffffffffffffffffffffffffffffffffff828116911614155b612d01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f696e76616c6964206e65772076657269666965720000000000000000000000006044820152606401610c1a565b609c805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f728af3d16a5760405e27a082c98ab272e9f0a1d02f0085d41532a26093aedd96905f90a35050565b612d7f614512565b5f81118015612d8f575060648111155b8015612d9d575060a9548114155b612e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f696e76616c69642070726f6f66207265776172642070657263656e74616765006044820152606401610c1a565b60a980549082905560408051828152602081018490527ffb81bce17f015797e11949d3c332e2bf9453faf68f728447426803138f2b022391016124f9565b60a85415612eab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610c1a565b612eb3614655565b60975473ffffffffffffffffffffffffffffffffffffffff166368015791336040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381865afa158015612f39573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f5d919061606b565b612fc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6f6e6c7920616374697665207374616b657220616c6c6f7765640000000000006044820152606401610c1a565b5f80612fcf8686614593565b915091505f612fe2836001015160c01c90565b5f81815260a16020526040902054909150821461305b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610c1a565b6130648161434a565b6130ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f626174636820696e206368616c6c656e676500000000000000000000000000006044820152606401610c1a565b5f81815260a4602052604090206003810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010017905560a680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055609954600290910154429161314191616045565b116131d5575f81815260a460209081526040808320600390810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905560a2835292819020909201548251808401909352600783527f54696d656f757400000000000000000000000000000000000000000000000000918301919091526131d0918391906153c4565b612c4a565b6131e0838686615038565b612c4a81336040518060400160405280600d81526020017f50726f6f66207375636365737300000000000000000000000000000000000000815250615547565b613228614512565b60aa80545f90915561323a828261562d565b6040805173ffffffffffffffffffffffffffffffffffffffff84168152602081018390527fb1b2058a6969e2d25e47bcaebe8ae21c29a23b2752429315b75e2f4f285f3d8791016124f9565b61328e614512565b5f805260a06020527fb84a74ec6ef4d0e83b6006dfaa014ab4026f9f3b97d186e604d29998a4e808ea541561331f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f67656e6573697320626174636820696d706f72746564000000000000000000006044820152606401610c1a565b5f8061332b8484614593565b915091505f61333e836001015160c01c90565b905080156133a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420626174636820696e646578000000000000000000000000006044820152606401610c1a565b5f6133b4846079015190565b90508061341d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f7a65726f20737461746520726f6f7400000000000000000000000000000000006044820152606401610c1a565b600984015160c01c1561348c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6c31206d65737361676520706f707065642073686f756c6420626520300000006044820152606401610c1a565b5f613498856019015190565b036134ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7a65726f206461746120686173680000000000000000000000000000000000006044820152606401610c1a565b7f010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c44401461352b856039015190565b14613592576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f696e76616c69642076657273696f6e65642068617368000000000000000000006044820152606401610c1a565b5f82815260a1602090815260408083208690558051608081018252428082528184019081528183018581526060830186815288875260a28652848720935184559151600184015551600283015551600390910155603987015160ad83528184205560ab825280832084905560a0909152808220839055609e849055609d84905551849184917f2c32d4ae151744d0bf0b9464a3e897a1d17ed2f1af71f7c9a75f12ce0d28238f9190a3604080518281525f6020820152849184917f26ba82f907317eedc97d0cbef23de76a43dd6edb563bdb6e9407645b950a7a2d910160405180910390a3505050505050565b5f8061368b8686614593565b915091505f61369e836001015160c01c90565b5f81815260a160205260409020549091508214613717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610c1a565b612c4a838686615038565b61372a614512565b8015613883576137386156ff565b60a65460ff16156138355760a7545f90815260a4602090815260408083206001810154905468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16845260a59092528220805491929091613799908490616045565b909155505060a7545f90815260a46020526040812080547fffffffff0000000000000000000000000000000000000000000000000000000016815560018101829055600281019190915560030180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905560a680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b7f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a150565b61388b615784565b7f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33613858565b50565b6138bd614512565b5f811180156138ce575060ac548114155b613934576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f696e76616c6964206e657720726f6c6c75702064656c617920706572696f64006044820152606401610c1a565b60ac80549082905560408051828152602081018490527f624e47dc9fb8f8cfeaf4ead4710277cc1757136cfa885e465514cf6d510f0ad191016124f9565b335f908152609f602052604090205460ff166139ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f6f6e6c79206368616c6c656e67657220616c6c6f7765640000000000000000006044820152606401610c1a565b60a85415613a54576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f70656e64696e67207265766572742072657175657374000000000000000000006044820152606401610c1a565b613a5c614655565b60a65460ff1615613ac9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f616c726561647920696e206368616c6c656e67650000000000000000000000006044820152606401610c1a565b8167ffffffffffffffff16609d5410613b3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f626174636820616c72656164792066696e616c697a65640000000000000000006044820152606401610c1a565b67ffffffffffffffff82165f90815260a160205260409020548114613bbf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f696e636f727265637420626174636820686173680000000000000000000000006044820152606401610c1a565b613bd28267ffffffffffffffff16611b64565b613c38576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f6261746368206e6f7420657869737400000000000000000000000000000000006044820152606401610c1a565b67ffffffffffffffff82165f90815260a4602052604090205468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1615613cda576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f626174636820616c7265616479206368616c6c656e67656400000000000000006044820152606401610c1a565b67ffffffffffffffff82165f90815260a260205260409020600101544210613d84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f63616e6e6f74206368616c6c656e6765206261746368206f757473696465207460448201527f6865206368616c6c656e67652077696e646f77000000000000000000000000006064820152608401610c1a565b60975f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630d13fd7b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613dee573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613e1291906160e7565b341015613e7b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f696e73756666696369656e742076616c756500000000000000000000000000006044820152606401610c1a565b67ffffffffffffffff82811660a78190556040805160c0810182528281523360208083018281523484860190815242606086019081525f6080870181815260a0880182815299825260a49095529690962094518554925173ffffffffffffffffffffffffffffffffffffffff1668010000000000000000027fffffffff00000000000000000000000000000000000000000000000000000000909316981697909717178355945160018301559151600282015592516003909301805492511515610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff941515949094167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009093169290921792909217905573ffffffffffffffffffffffffffffffffffffffff168267ffffffffffffffff167f3a6ea19df25b49e7624e313ce7c1ab23984238e93727260db56a81735b1b997634604051613fe791815260200190565b60405180910390a35f609d546001613fff9190616045565b90505b609e548111614057578267ffffffffffffffff168114614045576099545f82815260a260205260408120600101805490919061403f908490616045565b90915550505b8061404f8161613f565b915050614002565b505060a680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905550565b5f54600390610100900460ff161580156140a757505f5460ff8083169116105b614133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610c1a565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff8316176101001781558290036141cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f696e76616c696420726f6c6c75702064656c617920706572696f6400000000006044820152606401610c1a565b60ac829055604080515f8152602081018490527f624e47dc9fb8f8cfeaf4ead4710277cc1757136cfa885e465514cf6d510f0ad1910160405180910390a15f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020016124f9565b335f90815260a56020526040812054908190036142dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f696e76616c69642062617463684368616c6c656e6765526577617264000000006044820152606401610c1a565b335f90815260a560205260408120556142f6828261562d565b8173ffffffffffffffffffffffffffffffffffffffff167f9c25fa83f414ed363c8d39c98fb3e17567b3431cede71eb062c49d2a63ce247a8260405161433e91815260200190565b60405180910390a25050565b5f81815260a4602052604081205468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1615801590611b8c5750505f90815260a46020526040902060030154610100900460ff161590565b6143a9614512565b5f811180156143ba57506098548114155b614420576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f696e76616c6964206e65772066696e616c697a6520706572696f6400000000006044820152606401610c1a565b609880549082905560408051828152602081018490527fa577f4223f91f74e2dad65bbb8c30807587ae95d0d34288057bb3ec0d398a43791016124f9565b614466614512565b73ffffffffffffffffffffffffffffffffffffffff8116614509576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610c1a565b6138b281615212565b60335473ffffffffffffffffffffffffffffffffffffffff163314612888576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c1a565b5f805f6145a085856157db565b90505f8160ff165f036145c1576145b78686615865565b9094509050614647565b8160ff16600114806145d657508160ff166002145b156145e5576145b786866158e8565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f556e737570706f727465642062617463682076657273696f6e000000000000006044820152606401610c1a565b808420925050509250929050565b60655460ff1615612888576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610c1a565b805f036146cd575050565b8082035f5b82811015614786576101008184038111156146ec57508083035b609b546040517f3c7f5283000000000000000000000000000000000000000000000000000000008152600481018590526024810183905273ffffffffffffffffffffffffffffffffffffffff90911690633c7f5283906044015f604051808303815f87803b15801561475c575f80fd5b505af115801561476e573d5f803e3d5ffd5b505050506101008301925050610100810190506146d2565b50505050565b600261479b602086018661611f565b60ff161115614806576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f696e76616c69642076657273696f6e00000000000000000000000000000000006044820152606401610c1a565b6080840135614871576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f70726576696f757320737461746520726f6f74206973207a65726f00000000006044820152606401610c1a565b60a08401356148dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f6e657720737461746520726f6f74206973207a65726f000000000000000000006044820152606401610c1a565b5f806148ee6118b26020880188616086565b915091505f614901836001015160c01c90565b90505f60a181614912846001616045565b81526020019081526020015f205414614987576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f626174636820616c726561647920636f6d6d69747465640000000000000000006044820152606401610c1a565b609e5481146149f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f696e636f727265637420626174636820696e64657800000000000000000000006044820152606401610c1a565b5f81815260a160205260409020548214614a68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f696e636f727265637420706172656e74206261746368206861736800000000006044820152606401610c1a565b5f81815260ab6020526040902054608088013514614ae2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f696e636f72726563742070726576696f757320737461746520726f6f740000006044820152606401610c1a565b5f614af1846011015160c01c90565b90505f614b1d614b0760608b0160408c01616176565b614b1760808c0160608d016160fe565b84615955565b9050614b2f60808a0160608b016160fe565b60019384019361ffff91909116929092019160f990614b5160208c018c61611f565b60ff1610614b5e57506101015b604080518281019091529550614b8386614b7b60208d018d61611f565b60ff16615999565b60c084901b6001870152614bb186614ba160808d0160608e016160fe565b61ffff1660c01b60099190910152565b60c083811b6011880152601987018390526039870188905260808b0135605988015260a08b013560798801528a01356099870152614c1586614bf660208c018c616086565b604051614c0492919061618f565b604051809103902060b99190910152565b60d986018590526001614c2b60208c018c61611f565b60ff1610614c5d57614c5d86614c4760608d0160408e01616176565b67ffffffffffffffff1660c01b60f99190910152565b8086205f85815260a1602090815260408083209390935560ab815282822060a08e0135905560ad905290812088905560a65460ff1615614cc65760a7545f90815260a460205260409020600201546099544291614cb991616045565b614cc39190616058565b90505b60405180608001604052804281526020018260985442614ce69190616045565b614cf09190616045565b8152602001614d0560608e0160408f01616176565b67ffffffffffffffff16815260209081018b90525f87815260a2825260409081902083518155838301516001820155908301516002820155606090920151600390920191909155609e86905560975473ffffffffffffffffffffffffffffffffffffffff1692506374fe27b791508a3590614d8c90614d86908d018d616086565b5f6159a0565b5f614d9a60408e018e616086565b6040518663ffffffff1660e01b8152600401614dba9594939291906161e5565b602060405180830381865afa158015614dd5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614df9919061606b565b614e85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f746865207369676e617475726520766572696669636174696f6e206661696c6560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610c1a565b5f83815260a16020526040808220549051909185917f2c32d4ae151744d0bf0b9464a3e897a1d17ed2f1af71f7c9a75f12ce0d28238f9190a3505050505050505050565b5f81600203614f72575f6040515f5b804980614ee55750614ef4565b60208202830152600101614ed8565b602081028083209201604052909250905080614f6c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5632207265717569726573206174206c65617374203120626c6f6200000000006044820152606401610c1a565b50919050565b60014915615002576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f6c6567616379206261746368657320737570706f72742065786163746c79203160448201527f20626c6f620000000000000000000000000000000000000000000000000000006064820152608401610c1a565b5f4915615010575f49611b8c565b507f010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c4440145b919050565b8061509f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f496e76616c69642062617463682070726f6f66000000000000000000000000006044820152606401610c1a565b5f6150ae846001015160c01c90565b90505f6150bc856039015190565b90505f7f00000000000000000000000000000000000000000000000000000000000000006150eb876059015190565b6079880151609989015160b98a015160198b015160405160c09690961b7fffffffffffffffff000000000000000000000000000000000000000000000000166020870152602886019490945260488501929092526068840152608883015260a882015260c8810183905260e801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120609c5490915073ffffffffffffffffffffffffffffffffffffffff16632c09a8486151ba885160f81c90565b858888866040518663ffffffff1660e01b81526004016151de959493929190616265565b5f6040518083038186803b1580156151f4575f80fd5b505afa158015615206573d5f803e3d5ffd5b50505050505050505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f54610100900460ff1661531e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610c1a565b6128886159f4565b5f54610100900460ff166153bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610c1a565b612888615ab4565b60a88390555f83815260a460205260408082205460975491517f45bc4d10000000000000000000000000000000000000000000000000000000008152600481018690526801000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116939216906345bc4d10906024016020604051808303815f875af1158015615455573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061547991906160e7565b5f86815260a46020526040902060010154909150615498908290616045565b5f86815260a4602090815260408083205468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16835260a5909152812080549091906154e4908490616045565b90915550506040516154f7908490616296565b6040519081900381209073ffffffffffffffffffffffffffffffffffffffff84169087907fe70d3820e244d5f71d1a6395db24f3460e8dca966edc1fd3625b6292880a877a905f90a45050505050565b5f83815260a4602052604081206001015460a95490919060649061556b90846162c2565b61557591906162d9565b90506155818183616058565b60aa5f8282546155919190616045565b909155505073ffffffffffffffffffffffffffffffffffffffff84165f90815260a56020526040812080548392906155ca908490616045565b90915550506040516155dd908490616296565b6040519081900381209073ffffffffffffffffffffffffffffffffffffffff86169087907fe70d3820e244d5f71d1a6395db24f3460e8dca966edc1fd3625b6292880a877a905f90a45050505050565b80156156fb575f8273ffffffffffffffffffffffffffffffffffffffff16826040515f6040518083038185875af1925050503d805f8114615689576040519150601f19603f3d011682016040523d82523d5f602084013e61568e565b606091505b50509050806156f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f526f6c6c75703a20455448207472616e73666572206661696c656400000000006044820152606401610c1a565b505b5050565b615707614655565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861575a3390565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b61578c615b53565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa3361575a565b5f81615843576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f456d7074792062617463682068656164657200000000000000000000000000006044820152606401610c1a565b82825f81811061585557615855616311565b919091013560f81c949350505050565b5f8160f98110156158d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f626174636820686561646572206c656e67746820746f6f20736d616c6c0000006044820152606401610c1a565b6040519150808483378082016040529250929050565b5f8161010181146158d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f626174636820686561646572206c656e67746820697320696e636f72726563746044820152606401610c1a565b6040805160c085901b815260f084901b6008820152600a60208502820181019092525f91810161598a8161ffff871686615bbf565b82900390912095945050505050565b8082535050565b60605f808080806159b3888a018a61642b565b95509550955095509550508187106159d15794506159ed9350505050565b8387106159e55782955050505050506159ed565b509293505050505b9392505050565b5f54610100900460ff16615a8a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610c1a565b606580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b5f54610100900460ff16615b4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610c1a565b61288833615212565b60655460ff16612888576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610c1a565b5f825f03615bce5750826159ed565b609b5473ffffffffffffffffffffffffffffffffffffffff165f5b84811015615c95576040517fae453cd5000000000000000000000000000000000000000000000000000000008152600481018590525f9073ffffffffffffffffffffffffffffffffffffffff84169063ae453cd590602401602060405180830381865afa158015615c5c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190615c8091906160e7565b87525060209095019460019384019301615be9565b5093949350505050565b5f60208284031215615caf575f80fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114615033575f80fd5b5f60208284031215615ce9575f80fd5b6159ed82615cb6565b5f8083601f840112615d02575f80fd5b50813567ffffffffffffffff811115615d19575f80fd5b602083019150836020828501011115615d30575f80fd5b9250929050565b5f805f60408486031215615d49575f80fd5b833567ffffffffffffffff811115615d5f575f80fd5b615d6b86828701615cf2565b909790965060209590950135949350505050565b5f8060208385031215615d90575f80fd5b823567ffffffffffffffff811115615da6575f80fd5b615db285828601615cf2565b90969095509350505050565b5f60e08284031215614f6c575f80fd5b5f60608284031215614f6c575f80fd5b5f8060408385031215615def575f80fd5b823567ffffffffffffffff80821115615e06575f80fd5b615e1286838701615dbe565b93506020850135915080821115615e27575f80fd5b50615e3485828601615dce565b9150509250929050565b5f805f805f8060808789031215615e53575f80fd5b863567ffffffffffffffff80821115615e6a575f80fd5b615e768a838b01615dbe565b97506020890135915080821115615e8b575f80fd5b615e978a838b01615dce565b96506040890135915080821115615eac575f80fd5b615eb88a838b01615cf2565b90965094506060890135915080821115615ed0575f80fd5b50615edd89828a01615cf2565b979a9699509497509295939492505050565b5f805f805f8060c08789031215615f04575f80fd5b615f0d87615cb6565b9550615f1b60208801615cb6565b9450615f2960408801615cb6565b9350606087013592506080870135915060a087013590509295509295509295565b5f805f8060408587031215615f5d575f80fd5b843567ffffffffffffffff80821115615f74575f80fd5b615f8088838901615cf2565b90965094506020870135915080821115615f98575f80fd5b50615fa587828801615cf2565b95989497509550505050565b80151581146138b2575f80fd5b5f60208284031215615fce575f80fd5b81356159ed81615fb1565b803567ffffffffffffffff81168114615033575f80fd5b5f8060408385031215616001575f80fd5b61600a83615fd9565b946020939093013593505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b80820180821115611b8c57611b8c616018565b81810381811115611b8c57611b8c616018565b5f6020828403121561607b575f80fd5b81516159ed81615fb1565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126160b9575f80fd5b83018035915067ffffffffffffffff8211156160d3575f80fd5b602001915036819003821315615d30575f80fd5b5f602082840312156160f7575f80fd5b5051919050565b5f6020828403121561610e575f80fd5b813561ffff811681146159ed575f80fd5b5f6020828403121561612f575f80fd5b813560ff811681146159ed575f80fd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361616f5761616f616018565b5060010190565b5f60208284031215616186575f80fd5b6159ed82615fd9565b818382375f9101908152919050565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f6080820187835260206080602085015281885180845260a08601915060208a0193505f5b8181101561623c57845173ffffffffffffffffffffffffffffffffffffffff168352938301939183019160010161620a565b5050876040860152848103606086015261625781878961619e565b9a9950505050505050505050565b858152846020820152608060408201525f61628460808301858761619e565b90508260608301529695505050505050565b5f82515f5b818110156162b5576020818601810151858301520161629b565b505f920191825250919050565b8082028115828204841417611b8c57611b8c616018565b5f8261630c577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f83011261637a575f80fd5b8135602067ffffffffffffffff808311156163975761639761633e565b8260051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f830116810181811084821117156163da576163da61633e565b60405293845260208187018101949081019250878511156163f9575f80fd5b6020870191505b848210156164205761641182615cb6565b83529183019190830190616400565b979650505050505050565b5f805f805f8060c08789031215616440575f80fd5b86359550602087013567ffffffffffffffff8082111561645e575f80fd5b61646a8a838b0161636b565b9650604089013595506060890135915080821115616486575f80fd5b6164928a838b0161636b565b94506080890135935060a08901359150808211156164ae575f80fd5b506164bb89828a0161636b565b915050929550929550929556fea164736f6c6343000818000a" func init() { if err := json.Unmarshal([]byte(RollupStorageLayoutJSON), RollupStorageLayout); err != nil { diff --git a/bindings/bindings/zkevmverifierv1.go b/bindings/bindings/zkevmverifierv1.go index b8a903a4e..a633be843 100644 --- a/bindings/bindings/zkevmverifierv1.go +++ b/bindings/bindings/zkevmverifierv1.go @@ -31,8 +31,8 @@ var ( // ZkEvmVerifierV1MetaData contains all meta data concerning the ZkEvmVerifierV1 contract. var ZkEvmVerifierV1MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_programVkey\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"received\",\"type\":\"bytes4\"},{\"internalType\":\"bytes4\",\"name\":\"expected\",\"type\":\"bytes4\"}],\"name\":\"WrongVerifierSelector\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"VERIFIER_HASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"internalType\":\"uint256[]\",\"name\":\"public_inputs\",\"type\":\"uint256[]\"}],\"name\":\"Verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"publicValues\",\"type\":\"bytes\"}],\"name\":\"hashPublicValues\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"programVkey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"publicInputHash\",\"type\":\"bytes32\"}],\"name\":\"verifyBatch\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"publicInputHash\",\"type\":\"bytes\"}],\"name\":\"verifyPlonk\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"programVKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"publicValues\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proofBytes\",\"type\":\"bytes\"}],\"name\":\"verifyProof\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801562000010575f80fd5b50604051620032263803806200322683398101604081905262000033916200003b565b5f5562000053565b5f602082840312156200004c575f80fd5b5051919050565b6131c580620000615f395ff3fe608060405234801561000f575f80fd5b5060043610610085575f3560e01c80637e4f7a8a116100585780637e4f7a8a146100f2578063a48fd34b14610115578063c8bd017614610128578063ffa1ad741461013b575f80fd5b806309665ee7146100895780632a510436146100a457806341493c60146100ca5780636b61d8e7146100df575b5f80fd5b6100915f5481565b6040519081526020015b60405180910390f35b7fd4e8ecd2357dd882209800acd6abb443d231cf287d77ba62b732ce937c8b56e7610091565b6100dd6100d8366004612d64565b61017a565b005b6100916100ed366004612dd8565b610388565b610105610100366004612e17565b610404565b604051901515815260200161009b565b6100dd610123366004612ea9565b612c23565b6100dd610136366004612f10565b612c90565b604080518082018252600681527f76352e302e3000000000000000000000000000000000000000000000000000006020820152905161009b9190612fb9565b5f6101886004828486612fd2565b61019191612ff9565b90507fd4e8ecd2357dd882209800acd6abb443d231cf287d77ba62b732ce937c8b56e77fd4e8ecd2000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461025f576040517f988066a10000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000080841660048301528216602482015260440160405180910390fd5b5f61026a8787610388565b6040805160028082526060820183529293505f929091602083019080368337019050509050885f1c815f815181106102a4576102a4613041565b602002602001018181525050815f1c816001815181106102c6576102c6613041565b60209081029190910101525f30637e4f7a8a6102e5886004818c612fd2565b856040518463ffffffff1660e01b8152600401610304939291906130b5565b602060405180830381865afa15801561031f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610343919061310c565b90508061037c576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050505050565b5f7f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f1b600284846040516103be92919061312b565b602060405180830381855afa1580156103d9573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906103fc919061313a565b169392505050565b5f6040516102408101610416846108a6565b61042085856108b9565b61042986610908565b6104328761091e565b5f61043e86868a610ab8565b905061044981610dee565b90506104558189610e54565b90506104618189610ee2565b5060608201517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000006104b884630100000085612bb8565b086101c0840152506104cb818587610f4d565b6104d682868a6112c2565b91507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018183086101a08401525061050d9050611667565b610516866127ac565b61051f866126fd565b61052886612324565b61053186611e50565b61053a86611bb6565b610543866117b8565b61020001519050612c1b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f77726f6e67206e756d626572206f66207075626c696320696e707574730000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6572726f72206d6f6420657870000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6572726f72206563206f7065726174696f6e00000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f696e707574732061726520626967676572207468616e207200000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f77726f6e672070726f6f662073697a65000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f6f70656e696e677320626967676572207468616e2072000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f6572726f722070616972696e67000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6572726f722076657269667900000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6572726f722072616e646f6d2067656e206b7a670000000000000000000000006044820152606481fd5b600281146108b6576108b661054f565b50565b5f5b81811015610903577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000833511156108f4576108f461066c565b602092909201916001016108bb565b505050565b61036081811461091a5761091a6106cb565b5050565b61018081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000813511156109545761095461072a565b506101a081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000008135111561098b5761098b61072a565b506101c081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000813511156109c2576109c261072a565b506101e081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000813511156109f9576109f961072a565b5061020081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610a3057610a3061072a565b5061026081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610a6757610a6761072a565b5061030081015f5b6001811015610903577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000082351115610aa957610aa961072a565b60209190910190600101610a6f565b5f60405161024081016467616d6d6181527f239ed22af3191cfccd323949e417667defbcb082d9f31527488e523372ea9e7a60208201527f213da3cb623029a98e0186dc8c1a3a31ee249ab93bfb68abc1103900890eccb960408201527f01fd59b61f15d097ad7701c4dc12b8739eadc1d54664773c3ed5d8104c296c2a60608201527e22ee53909feab41bb47f0e6ddb802bb6096fd2027d89c22d94b4e56e227cd060808201527f14992dea1a6515e3f8a2250e30cb9e3bad58ff44bbfdd1390bc8d0a8f2bddd0f60a08201527f1e82777c7079b474d31f9fedafca8f2d108de5c58a2df629a8af49cd424c8c2960c08201527f060081d04d187d301d4223990acab3c887713358f1705af7f53e07aca0f709dd60e08201527f16911506ad1ccf9b39db250ce7752278c8115127c4f85080c2bd153946b4a5be6101008201527f279df33b57d698efd752579ee90674a7241ecdb21c6cb35cdf8ef7c1af73160a6101208201527f202fa12c1e82de2f49dc4c5bc771b94c8495544bb0055c4c381744cc3d1d332d6101408201527f040315f3fd753e8cca89f353d096fb94fcdf9cd41973954a3dd4ec58cba79d5f6101608201527f18e0b4a84e9429c05d0fd0d304acd0f3cfa93437356c112199d4d7c0162a1c9e6101808201527f2e14e072ab351d1b3838323f75ecf9b6c08043c230423d515febd04e29336b776101a08201527f1553e1a7b6e18ba105733244604cd37d82371c3a7b0503fa4aff460870170bcf6101c08201527f0c203d7594efa49bd977084de30db24ce843e501791176c21b5beda79ceaf1366101e08201527f0c4bddeb52250b0114282b00285f224b812fc581f2b55e5c3a49472069f901f36102008201527f2fb4fbb4677318edec4b80fc8fa22ffcce4a51d5f3771e575e726e790a9f9cbe6102208201527f28518b11376dc02418849d45b1f3b0e00d3f74502d713b002b9d7293a1018d79610240820152610260810160208602808883379081019060c0808784375061030501905060208282601b820160025afa905080610db857610db86107e8565b5080519250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182066040820152509392505050565b5f60405161024060405101636265746181528360208201526020816024601c840160025afa80610e2057610e206107e8565b5080519250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018206602082015250919050565b5f60405161024060405101606564616c7068618252602082018681526020810190506103208601600160400280828437928301929190910190506040610220870182375060208282601b850160025afa905080610eb357610eb36107e8565b50517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181069091529392505050565b60405161024060405101637a657461815283602082015260c0808401604083013760208160e4601c840160025afa80610f1d57610f1d6107e8565b50517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019006606091909101525050565b5f60405160608101516101c0820151915085610f6b81878585610fe6565b5f92505f91505b85821015610fdc577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001853582510992507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018385086020958601959094506001929092019101610f72565b5050509392505050565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e427ce32d4886b01bfe313ba1dba6db8b2045d128178a7164500e0a6c1183096001855f5b868110156110d4577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103860882527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b840992506020919091019060010161102f565b506110e0818789611198565b5060019050855f5b8681101561118e577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001868551090982526020820191507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b840992506001016110e8565b5050505050505050565b600183525f805b838110156111ed5781850151828401517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181830990506020840193508084880152505060018101905061119f565b50602081038201915080840193505061122e6020840160027f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001038551612bb8565b5f5b838110156112bb5760208503945082517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018651840984527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018184097fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090940193925050600101611230565b5050505050565b5f60405160608101516101c0820151915061032084015f806112ea896020850135853561146e565b91506112fd8962a653508a018787611333565b90507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018082840987089998505050505050505050565b5f61135f85857f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b612bb8565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001817f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103840894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e427ce32d4886b01bfe313ba1dba6db8b2045d128178a7164500e0a6c1182099050611418867f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff87612bb8565b94507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018482099695505050505050565b5f83525f602084015280604084015250806060830152505f6080820153603060818201535f60828201536042608382015360536084820153604260858201536032608682015360326087820153602d608882015360506089820153606c608a820153606f608b820153606e608c820153606b608d820153600b608e8201535f602082608f8460025afa80611504576115046107e8565b8251600160208501536042602185015360536022850153604260238501536032602485015360326025850153602d602685015360506027850153606c6028850153606f6029850153606e602a850153606b602b850153600b602c850153602084602d8660025afa91508161157a5761157a6107e8565b8351186020840152600260408401536042604184015360536042840153604260438401536032604484015360326045840153602d604684015360506047840153606c6048840153606f6049840153606e604a840153606b604b840153600b604c84015360208301602081602d8360025afa915050806115fb576115fb6107e8565b507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017001000000000000000000000000000000008351099050602082015160801c7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018183089392505050565b604051610240604051016101c08201517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001036060850151086116ed837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff83612bb8565b90507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e427ce32d4886b01bfe313ba1dba6db8b2045d128178a7164500e0a6c11820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018282098451935091507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001905082820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018282099050806080840152505050565b60405161024081016101608201518152610180820151602082015261028083013560408201526102a08301356060820152610220830135608082015261024083013560a08201526102c083013560c08201526102e083013560e082015260608201516101008201526101e08201516101208201526020816101408360025afa8061184457611844610847565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182510690508160408101925061028085013581526102a0850135602082015261189483836102c0880184612b1f565b61016084016118a98484610220890184612b1f565b61014085016118bd84610260890183612b66565b7f1fa4be93b5e7f7e674d5059b63554fab99638b304ed8310e9fa44c281ac9b03b85527f1a01ae7fac6228e39d3cb5a5e71fd31160f3241e79a5f48ffb3737e6c389b7216020860152805160408087019182529095908160608160075afa91508161192a5761192a6107e8565b60208101915081517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703825261196286828586612a16565b50508360408501945061197f8560608801516102808a0184612aad565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b60608801510995507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000186850993506119ff85856102c08a0184612b1f565b611a0b85828485612a16565b50602082810180517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd470381528251865291810151908501527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260408501527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60608501527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60808501527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60a0850152905160c0840152805160e08401527f22f1acbb03c4508760c2430af35865e7cdf9f3eb1224504fdcc3708ddb954a486101008401527f2a344fad01c2ed0ed73142ae1752429eaea515c6f3f6b941103cc21c2308e1cb6101208401527f159f15b842ba9c8449aa3268f981010d4c7142e5193473d80b464e964845c3f86101408401527f0efd30ac7b6f8d0d3ccbc2207587c2acbad1532dc0293f0d034cf8258cd428b3610160840152925061090390508160405160205f6101808460085afa80611ba857611ba8610789565b505f51610200919091015250565b6040516102406040510160208101604082016101e084015180610160860160e08701518152610100870151610180880152610120870151610140880152611c0186835f8b0184612b1f565b611c14826101808a016101408a01612b66565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018383099150611c49868360408b0184612b1f565b611c5c826101a08a016101408a01612b66565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018383099150611c91868360808b0184612b1f565b611ca4826101c08a016101408a01612b66565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183830991507f239ed22af3191cfccd323949e417667defbcb082d9f31527488e523372ea9e7a86527f213da3cb623029a98e0186dc8c1a3a31ee249ab93bfb68abc1103900890eccb98552611d1c84838884612ad8565b611d2f826101e08a016101408a01612b66565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183830991507f01fd59b61f15d097ad7701c4dc12b8739eadc1d54664773c3ed5d8104c296c2a86527e22ee53909feab41bb47f0e6ddb802bb6096fd2027d89c22d94b4e56e227cd08552611da684838884612ad8565b611db9826102008a016101408a01612b66565b61030088017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184840992507f2fb4fbb4677318edec4b80fc8fa22ffcce4a51d5f3771e575e726e790a9f9cbe87527f28518b11376dc02418849d45b1f3b0e00d3f74502d713b002b9d7293a1018d798652611e3685848985612ad8565b611e4583826101408b01612b66565b505050505050505050565b6040516467616d6d616102408201908152606082015161026083015260e08201516102808301526101008201516102a083015260c0836102c08401377f239ed22af3191cfccd323949e417667defbcb082d9f31527488e523372ea9e7a6101408201527f213da3cb623029a98e0186dc8c1a3a31ee249ab93bfb68abc1103900890eccb96101608201527f01fd59b61f15d097ad7701c4dc12b8739eadc1d54664773c3ed5d8104c296c2a610180808301919091527e22ee53909feab41bb47f0e6ddb802bb6096fd2027d89c22d94b4e56e227cd06101a0808401919091527f2fb4fbb4677318edec4b80fc8fa22ffcce4a51d5f3771e575e726e790a9f9cbe6101c0808501919091527f28518b11376dc02418849d45b1f3b0e00d3f74502d713b002b9d7293a1018d796101e0808601919091526101208601516102008087019190915293870135610220860152918601356102408501528501356102608401528401356102808301528301356102a08201526102c081016103008401602081833750610260840135602091820152601b906102e5906101e085018285850160025afa9250505080612005576120056107e8565b506101e00180517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019006905250565b604051610240604051017f060081d04d187d301d4223990acab3c887713358f1705af7f53e07aca0f709dd81527f16911506ad1ccf9b39db250ce7752278c8115127c4f85080c2bd153946b4a5be602082015261209e604082016101808501358360e08601612a82565b7f279df33b57d698efd752579ee90674a7241ecdb21c6cb35cdf8ef7c1af73160a81527f202fa12c1e82de2f49dc4c5bc771b94c8495544bb0055c4c381744cc3d1d332d60208201526120fe604082016101a08501358360e08601612ad8565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0840135610180850135097f040315f3fd753e8cca89f353d096fb94fcdf9cd41973954a3dd4ec58cba79d5f82527f18e0b4a84e9429c05d0fd0d304acd0f3cfa93437356c112199d4d7c0162a1c9e602083015261218760408301828460e08701612ad8565b507f2e14e072ab351d1b3838323f75ecf9b6c08043c230423d515febd04e29336b7781527f1553e1a7b6e18ba105733244604cd37d82371c3a7b0503fa4aff460870170bcf60208201526121e8604082016101c08501358360e08601612ad8565b7f0c203d7594efa49bd977084de30db24ce843e501791176c21b5beda79ceaf13681527f0c4bddeb52250b0114282b00285f224b812fc581f2b55e5c3a49472069f901f36020820152612243604082018260e0850180612a16565b610300830161032084015f5b600181101561228f5781358452602082013560208501526122796040850184358660e08901612ad8565b602092909201916040919091019060010161224f565b5050507f14992dea1a6515e3f8a2250e30cb9e3bad58ff44bbfdd1390bc8d0a8f2bddd0f81527f1e82777c7079b474d31f9fedafca8f2d108de5c58a2df629a8af49cd424c8c2960208201526122ed60408201858360e08601612ad8565b6102208301358152610240830135602082015261231260408201868360e08601612ad8565b6112bb8160a0840160e0850180612a16565b6040516020810151604082015160608301515f8401517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184610260880135097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101e088013586097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610180890135820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000161020089013587097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a08a0135820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000186820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018284097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600580097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001878a0998507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101808c01358a0894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000188860894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160058a0993507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a08c0135850893507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000188850893507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001818a099250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101c08b0135830891507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000187830891507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183850997507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018289097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001908103985085890997507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160808a01518908975061037c88828c612034565b60405160026301000000016102406040510161271e81836060860151612bb8565b91506127338183610140870160a08701612aad565b61274681610100860160a0860180612a4c565b612755818360a0860180612a82565b6127678160c0860160a0860180612a4c565b61277e816101c085015160a0860160a08701612a82565b505060c00180517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703905250565b6040515f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160208301516101e08501350990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040830151820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610180840135820890505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160208401516102008601350990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040840151820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0850135820890505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160408501516101c08701350890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182840992507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018184099250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000015f840151830991507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610260850135830991507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0840151830860808401519092507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000190810391508183087f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001036101209390930192909252505050565b8151845260208201516020850152825160408501526020830151606085015260408160808660065afa806112bb576112bb61060d565b8151845260208201516020850152823560408501526020830135606085015260408160808660065afa806112bb576112bb61060d565b815184526020820151602085015282604085015260408160608660075afa806112bb576112bb61060d565b813584526020820135602085015282604085015260408160608660075afa806112bb576112bb61060d565b815184526020820151602085015282604085015260408460608660075afa815160408601526020820151606086015260408260808760065afa16806112bb576112bb61060d565b813584526020820135602085015282604085015260408460608660075afa815160408601526020820151606086015260408260808760065afa16806112bb576112bb61060d565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001838335097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181835108825250505050565b602083526020808401526020604084015280606084015250806080830152507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160a08201525f60208260c08460055afa80612c1557612c156105ae565b50505190565b949350505050565b5f546040517f41493c6000000000000000000000000000000000000000000000000000000000815230916341493c6091612c689190869086908a908a90600401613151565b5f6040518083038186803b158015612c7e575f80fd5b505afa15801561118e573d5f803e3d5ffd5b3073ffffffffffffffffffffffffffffffffffffffff1663a48fd34b848484604051602001612cc191815260200190565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401612cee93929190613189565b5f6040518083038186803b158015612d04575f80fd5b505afa158015612d16573d5f803e3d5ffd5b50505050505050565b5f8083601f840112612d2f575f80fd5b50813567ffffffffffffffff811115612d46575f80fd5b602083019150836020828501011115612d5d575f80fd5b9250929050565b5f805f805f60608688031215612d78575f80fd5b85359450602086013567ffffffffffffffff80821115612d96575f80fd5b612da289838a01612d1f565b90965094506040880135915080821115612dba575f80fd5b50612dc788828901612d1f565b969995985093965092949392505050565b5f8060208385031215612de9575f80fd5b823567ffffffffffffffff811115612dff575f80fd5b612e0b85828601612d1f565b90969095509350505050565b5f805f8060408587031215612e2a575f80fd5b843567ffffffffffffffff80821115612e41575f80fd5b612e4d88838901612d1f565b90965094506020870135915080821115612e65575f80fd5b818701915087601f830112612e78575f80fd5b813581811115612e86575f80fd5b8860208260051b8501011115612e9a575f80fd5b95989497505060200194505050565b5f805f8060408587031215612ebc575f80fd5b843567ffffffffffffffff80821115612ed3575f80fd5b612edf88838901612d1f565b90965094506020870135915080821115612ef7575f80fd5b50612f0487828801612d1f565b95989497509550505050565b5f805f60408486031215612f22575f80fd5b833567ffffffffffffffff811115612f38575f80fd5b612f4486828701612d1f565b909790965060209590950135949350505050565b5f81518084525f5b81811015612f7c57602081850181015186830182015201612f60565b505f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f612fcb6020830184612f58565b9392505050565b5f8085851115612fe0575f80fd5b83861115612fec575f80fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156130395780818660040360031b1b83161692505b505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b604081525f6130c860408301858761306e565b8281036020848101919091528451808352858201928201905f5b818110156130fe578451835293830193918301916001016130e2565b509098975050505050505050565b5f6020828403121561311c575f80fd5b81518015158114612fcb575f80fd5b818382375f9101908152919050565b5f6020828403121561314a575f80fd5b5051919050565b858152606060208201525f61316a60608301868861306e565b828103604084015261317d81858761306e565b98975050505050505050565b604081525f61319c60408301858761306e565b82810360208401526131ae8185612f58565b969550505050505056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_programVkey\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidExitCode\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidVkRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"received\",\"type\":\"bytes4\"},{\"internalType\":\"bytes4\",\"name\":\"expected\",\"type\":\"bytes4\"}],\"name\":\"WrongVerifierSelector\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"VERIFIER_HASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VERSION\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"VK_ROOT\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"internalType\":\"uint256[]\",\"name\":\"public_inputs\",\"type\":\"uint256[]\"}],\"name\":\"Verify\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"publicValues\",\"type\":\"bytes\"}],\"name\":\"hashPublicValues\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"programVkey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"publicInputHash\",\"type\":\"bytes32\"}],\"name\":\"verifyBatch\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"proof\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"publicInputHash\",\"type\":\"bytes\"}],\"name\":\"verifyPlonk\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"programVKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"publicValues\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"proofBytes\",\"type\":\"bytes\"}],\"name\":\"verifyProof\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x608060405234801562000010575f80fd5b50604051620034133803806200341383398101604081905262000033916200003b565b5f5562000053565b5f602082840312156200004c575f80fd5b5051919050565b6133b280620000615f395ff3fe608060405234801561000f575f80fd5b506004361061009f575f3560e01c80637cad4e1311610072578063a48fd34b11610058578063a48fd34b14610154578063c8bd017614610167578063ffa1ad741461017a575f80fd5b80637cad4e131461010c5780637e4f7a8a14610131575f80fd5b806309665ee7146100a35780632a510436146100be57806341493c60146100e45780636b61d8e7146100f9575b5f80fd5b6100ab5f5481565b6040519081526020015b60405180910390f35b7f5a093a2fcb46394f5cadfe55c44d4d572fad9cec7aeb38026b0278322ef07fac6100ab565b6100f76100f2366004612f15565b6101b9565b005b6100ab610107366004612f89565b610527565b7e2f850ee998974d6cc00e50cd0814b098c05bfade466d28573240d057f253526100ab565b61014461013f366004612fc8565b6105a5565b60405190151581526020016100b5565b6100f761016236600461305a565b612dd4565b6100f76101753660046130c1565b612e41565b604080518082018252600681527f76362e312e300000000000000000000000000000000000000000000000000000602082015290516100b5919061316a565b5f6101c76004828486613183565b6101d0916131aa565b90507f5a093a2fcb46394f5cadfe55c44d4d572fad9cec7aeb38026b0278322ef07fac7f5a093a2f000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461029e576040517f988066a10000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000080841660048301528216602482015260440160405180910390fd5b7e2f850ee998974d6cc00e50cd0814b098c05bfade466d28573240d057f253525f6102c98888610527565b90505f6102da60246004888a613183565b6102e3916131f2565b90505f6102f460446024898b613183565b6102fd916131f2565b90505f61030e606460448a8c613183565b610317916131f2565b60408051600580825260c082019092529192505f91906020820160a0803683370190505090508c5f1c815f815181106103525761035261322e565b602002602001018181525050845f1c816001815181106103745761037461322e565b60200260200101818152505083816002815181106103945761039461322e565b60200260200101818152505082816003815181106103b4576103b461322e565b60200260200101818152505081816004815181106103d4576103d461322e565b60209081029190910101528315610417576040517f1fcf917700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b858314610450576040517fd58aec5800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f3073ffffffffffffffffffffffffffffffffffffffff16637e4f7a8a8c8c606490809261048093929190613183565b856040518463ffffffff1660e01b815260040161049f939291906132a2565b602060405180830381865afa1580156104ba573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104de91906132f9565b905080610517576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050505050565b5f7f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f1b6002848460405161055d929190613318565b602060405180830381855afa158015610578573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061059b9190613327565b1690505b92915050565b5f60405161024081016105b784610a47565b6105c18585610a5a565b6105ca86610aa9565b6105d387610abf565b5f6105df86868a610c59565b90506105ea81610f90565b90506105f68189610ff6565b90506106028189611084565b5060608201517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000061065984630200000085612d69565b086101c08401525061066c8185876110ef565b61067782868a611464565b91507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018183086101a0840152506106ae905061180a565b6106b78661295d565b6106c0866128ae565b6106c9866124c9565b6106d286611ff4565b6106db86611d59565b6106e48661195b565b61020001519050612dcc565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f77726f6e67206e756d626572206f66207075626c696320696e707574730000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6572726f72206d6f6420657870000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6572726f72206563206f7065726174696f6e00000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f696e707574732061726520626967676572207468616e207200000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f77726f6e672070726f6f662073697a65000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f6f70656e696e677320626967676572207468616e2072000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f6572726f722070616972696e67000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6572726f722076657269667900000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6572726f722072616e646f6d2067656e206b7a670000000000000000000000006044820152606481fd5b60058114610a5757610a576106f0565b50565b5f5b81811015610aa4577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000083351115610a9557610a9561080d565b60209290920191600101610a5c565b505050565b610360818114610abb57610abb61086c565b5050565b61018081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610af557610af56108cb565b506101a081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610b2c57610b2c6108cb565b506101c081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610b6357610b636108cb565b506101e081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610b9a57610b9a6108cb565b5061020081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610bd157610bd16108cb565b5061026081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610c0857610c086108cb565b5061030081015f5b6001811015610aa4577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000082351115610c4a57610c4a6108cb565b60209190910190600101610c10565b5f60405161024081016467616d6d6181527f2dc54336c06a06f4cf81d186d61710b54b7cc8a885d62068fa20ef5affcc9b2960208201527f0de6d6ca530719fcbbc72fb363fcfe8e678cc8e1ff97ae510902c38704c155d360408201527f016d52b549f5a97e0d20ffd0a98365c9a7d93e3877552678c0ee5a5584413e0160608201527f0969091657a75b12b7eea04d595cba1e87304cb4dd5cfdc78530707d1309732460808201527f1090a057ba86e7a26bf16afd35cb54435f66d95cfe43f55c5ef02db7209e931c60a08201527f2bf5be16a8b5a734fb51960de6ad22594c7bab0936545a91bfdc56a896deba2260c08201527f14ff07d809a066622eeec2671abfea3c61f1cbb4ed507e1decc4bd943a856e8160e08201527f1d6b52dd76d02b4dcd2708bee7f60d4a9ba11305894ec5374da8eb13d120914e6101008201527f2188d80f62696638d9914aebd8f9c50232936e7a3945a8967b010105b1bef2e16101208201527f25bbd1a7a916c59eb45e823e61d067f014a5d7721b0826ee6029c823f078bf056101408201527f048f55df25aea5672048ff344d6ae33323302e49ba4d8f7f3d3d57e1342a5c2c6101608201527f2438994c3232ec28ebbf2010fdcb6b7426ba5da25ae499d2e091a53c8fd7dfec6101808201527f18ee8d5a878f07a6729ecf3d71944fd4a15f2e903a77ee2303b6ab61f9c5509f6101a08201527f02f4278497f8821e95247cda1733795c328ff1505f8ca4535c35d921641583796101c08201527f07c21121e364b3cabb19d7f3cc18ee406b0f3ded1ac8f779508e692e24aff89d6101e08201527f2158407e9af4cedca94a99a2e2ec6718311d1f86b39f89f466c4835badb09ffb6102008201527f2f0a1d1b0bc53914c138f532c5f5eb08aa154bec4694e77a3a1152aea194ca826102208201527f2fe78306d51211fa7d2ecf1c3ccec2d626525525bae105ed19cff3b218ffd6ec610240820152610260810160208602808883379081019060c0808784375061030501905060208282601b820160025afa905080610f5a57610f5a610989565b5080519250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182066040820152509392505050565b5f60405161024060405101636265746181528360208201526020816024601c840160025afa80610fc257610fc2610989565b5080519250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018206602082015250919050565b5f60405161024060405101606564616c7068618252602082018681526020810190506103208601600160400280828437928301929190910190506040610220870182375060208282601b850160025afa90508061105557611055610989565b50517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181069091529392505050565b60405161024060405101637a657461815283602082015260c0808401604083013760208160e4601c840160025afa806110bf576110bf610989565b50517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019006606091909101525050565b5f60405160608101516101c082015191508561110d81878585611188565b5f92505f91505b8582101561117e577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001853582510992507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018385086020958601959094506001929092019101611114565b5050509392505050565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e5aaf0a66b91f8030da595e7d1c6787b9b45fc54c546729acf1ff05360983096001855f5b86811015611276577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103860882527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f2a734ebb326341efa19b0361d9130cd47b26b7488dc6d26eeccd4f3eb878331a84099250602091909101906001016111d1565b5061128281878961133a565b5060019050855f5b86811015611330577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001868551090982526020820191507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f2a734ebb326341efa19b0361d9130cd47b26b7488dc6d26eeccd4f3eb878331a8409925060010161128a565b5050505050505050565b600183525f805b8381101561138f5781850151828401517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001818309905060208401935080848801525050600181019050611341565b5060208103820191508084019350506113d06020840160027f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001038551612d69565b5f5b8381101561145d5760208503945082517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018651840984527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018184097fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909401939250506001016113d2565b5050505050565b5f60405160608101516101c0820151915061032084015f8061148c8960208501358535611611565b91506114a0896301821df98a0187876114d6565b90507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018082840987089998505050505050505050565b5f61150285857f2a734ebb326341efa19b0361d9130cd47b26b7488dc6d26eeccd4f3eb878331a612d69565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001817f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103840894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e5aaf0a66b91f8030da595e7d1c6787b9b45fc54c546729acf1ff053609820990506115bb867f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff87612d69565b94507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018482099695505050505050565b5f83525f602084015280604084015250806060830152505f6080820153603060818201535f60828201536042608382015360536084820153604260858201536032608682015360326087820153602d608882015360506089820153606c608a820153606f608b820153606e608c820153606b608d820153600b608e8201535f602082608f8460025afa806116a7576116a7610989565b8251600160208501536042602185015360536022850153604260238501536032602485015360326025850153602d602685015360506027850153606c6028850153606f6029850153606e602a850153606b602b850153600b602c850153602084602d8660025afa91508161171d5761171d610989565b8351186020840152600260408401536042604184015360536042840153604260438401536032604484015360326045840153602d604684015360506047840153606c6048840153606f6049840153606e604a840153606b604b840153600b604c84015360208301602081602d8360025afa9150508061179e5761179e610989565b507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017001000000000000000000000000000000008351099050602082015160801c7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018183089392505050565b604051610240604051016101c08201517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103606085015108611890837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff83612d69565b90507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e5aaf0a66b91f8030da595e7d1c6787b9b45fc54c546729acf1ff053609820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018282098451935091507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001905082820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018282099050806080840152505050565b60405161024081016101608201518152610180820151602082015261028083013560408201526102a08301356060820152610220830135608082015261024083013560a08201526102c083013560c08201526102e083013560e082015260608201516101008201526101e08201516101208201526020816101408360025afa806119e7576119e76109e8565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182510690508160408101925061028085013581526102a08501356020820152611a3783836102c0880184612cd0565b6101608401611a4c8484610220890184612cd0565b6101408501611a6084610260890183612d17565b7f1fa4be93b5e7f7e674d5059b63554fab99638b304ed8310e9fa44c281ac9b03b85527f1a01ae7fac6228e39d3cb5a5e71fd31160f3241e79a5f48ffb3737e6c389b7216020860152805160408087019182529095908160608160075afa915081611acd57611acd610989565b60208101915081517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47038252611b0586828586612bc7565b505083604085019450611b228560608801516102808a0184612c5e565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f2a734ebb326341efa19b0361d9130cd47b26b7488dc6d26eeccd4f3eb878331a60608801510995507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018685099350611ba285856102c08a0184612cd0565b611bae85828485612bc7565b50602082810180517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd470381528251865291810151908501527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260408501527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60608501527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60808501527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60a0850152905160c0840152805160e08401527f22f1acbb03c4508760c2430af35865e7cdf9f3eb1224504fdcc3708ddb954a486101008401527f2a344fad01c2ed0ed73142ae1752429eaea515c6f3f6b941103cc21c2308e1cb6101208401527f159f15b842ba9c8449aa3268f981010d4c7142e5193473d80b464e964845c3f86101408401527f0efd30ac7b6f8d0d3ccbc2207587c2acbad1532dc0293f0d034cf8258cd428b36101608401529250610aa490508160405160205f6101808460085afa80611d4b57611d4b61092a565b505f51610200919091015250565b6040516102406040510160208101604082016101e084015180610160860160e08701518152610100870151610180880152610120870151610140880152611da486835f8b0184612cd0565b611db7826101808a016101408a01612d17565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018383099150611dec868360408b0184612cd0565b611dff826101a08a016101408a01612d17565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018383099150611e34868360808b0184612cd0565b611e47826101c08a016101408a01612d17565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183830991507f2dc54336c06a06f4cf81d186d61710b54b7cc8a885d62068fa20ef5affcc9b2986527f0de6d6ca530719fcbbc72fb363fcfe8e678cc8e1ff97ae510902c38704c155d38552611ebf84838884612c89565b611ed2826101e08a016101408a01612d17565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183830991507f016d52b549f5a97e0d20ffd0a98365c9a7d93e3877552678c0ee5a5584413e0186527f0969091657a75b12b7eea04d595cba1e87304cb4dd5cfdc78530707d130973248552611f4a84838884612c89565b611f5d826102008a016101408a01612d17565b61030088017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184840992507f2f0a1d1b0bc53914c138f532c5f5eb08aa154bec4694e77a3a1152aea194ca8287527f2fe78306d51211fa7d2ecf1c3ccec2d626525525bae105ed19cff3b218ffd6ec8652611fda85848985612c89565b611fe983826101408b01612d17565b505050505050505050565b6040516467616d6d616102408201908152606082015161026083015260e08201516102808301526101008201516102a083015260c0836102c08401377f2dc54336c06a06f4cf81d186d61710b54b7cc8a885d62068fa20ef5affcc9b296101408201527f0de6d6ca530719fcbbc72fb363fcfe8e678cc8e1ff97ae510902c38704c155d36101608201527f016d52b549f5a97e0d20ffd0a98365c9a7d93e3877552678c0ee5a5584413e01610180808301919091527f0969091657a75b12b7eea04d595cba1e87304cb4dd5cfdc78530707d130973246101a0808401919091527f2f0a1d1b0bc53914c138f532c5f5eb08aa154bec4694e77a3a1152aea194ca826101c0808501919091527f2fe78306d51211fa7d2ecf1c3ccec2d626525525bae105ed19cff3b218ffd6ec6101e0808601919091526101208601516102008087019190915293870135610220860152918601356102408501528501356102608401528401356102808301528301356102a08201526102c081016103008401602081833750610260840135602091820152601b906102e5906101e085018285850160025afa92505050806121aa576121aa610989565b506101e00180517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019006905250565b604051610240604051017f14ff07d809a066622eeec2671abfea3c61f1cbb4ed507e1decc4bd943a856e8181527f1d6b52dd76d02b4dcd2708bee7f60d4a9ba11305894ec5374da8eb13d120914e6020820152612243604082016101808501358360e08601612c33565b7f2188d80f62696638d9914aebd8f9c50232936e7a3945a8967b010105b1bef2e181527f25bbd1a7a916c59eb45e823e61d067f014a5d7721b0826ee6029c823f078bf0560208201526122a3604082016101a08501358360e08601612c89565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0840135610180850135097f048f55df25aea5672048ff344d6ae33323302e49ba4d8f7f3d3d57e1342a5c2c82527f2438994c3232ec28ebbf2010fdcb6b7426ba5da25ae499d2e091a53c8fd7dfec602083015261232c60408301828460e08701612c89565b507f18ee8d5a878f07a6729ecf3d71944fd4a15f2e903a77ee2303b6ab61f9c5509f81527f02f4278497f8821e95247cda1733795c328ff1505f8ca4535c35d92164158379602082015261238d604082016101c08501358360e08601612c89565b7f07c21121e364b3cabb19d7f3cc18ee406b0f3ded1ac8f779508e692e24aff89d81527f2158407e9af4cedca94a99a2e2ec6718311d1f86b39f89f466c4835badb09ffb60208201526123e8604082018260e0850180612bc7565b610300830161032084015f5b600181101561243457813584526020820135602085015261241e6040850184358660e08901612c89565b60209290920191604091909101906001016123f4565b5050507f1090a057ba86e7a26bf16afd35cb54435f66d95cfe43f55c5ef02db7209e931c81527f2bf5be16a8b5a734fb51960de6ad22594c7bab0936545a91bfdc56a896deba22602082015261249260408201858360e08601612c89565b610220830135815261024083013560208201526124b760408201868360e08601612c89565b61145d8160a0840160e0850180612bc7565b6040516020810151604082015160608301515f8401517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184610260880135097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101e088013586097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610180890135820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000161020089013587097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a08a0135820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000186820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018284097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600580097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001878a0998507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101808c01358a0894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000188860894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160058a0993507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a08c0135850893507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000188850893507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001818a099250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101c08b0135830891507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000187830891507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183850997507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018289097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001908103985085890997507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160808a0151890897506128a288828c6121d9565b50505050505050505050565b6040516002630200000001610240604051016128cf81836060860151612d69565b91506128e48183610140870160a08701612c5e565b6128f781610100860160a0860180612bfd565b612906818360a0860180612c33565b6129188160c0860160a0860180612bfd565b61292f816101c085015160a0860160a08701612c33565b505060c00180517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703905250565b6040515f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160208301516101e08501350990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040830151820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610180840135820890505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160208401516102008601350990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040840151820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0850135820890505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160408501516101c08701350890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182840992507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018184099250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000015f840151830991507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610260850135830991507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0840151830860808401519092507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000190810391508183087f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001036101209390930192909252505050565b8151845260208201516020850152825160408501526020830151606085015260408160808660065afa8061145d5761145d6107ae565b8151845260208201516020850152823560408501526020830135606085015260408160808660065afa8061145d5761145d6107ae565b815184526020820151602085015282604085015260408160608660075afa8061145d5761145d6107ae565b813584526020820135602085015282604085015260408160608660075afa8061145d5761145d6107ae565b815184526020820151602085015282604085015260408460608660075afa815160408601526020820151606086015260408260808760065afa168061145d5761145d6107ae565b813584526020820135602085015282604085015260408460608660075afa815160408601526020820151606086015260408260808760065afa168061145d5761145d6107ae565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001838335097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181835108825250505050565b602083526020808401526020604084015280606084015250806080830152507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160a08201525f60208260c08460055afa80612dc657612dc661074f565b50505190565b949350505050565b5f546040517f41493c6000000000000000000000000000000000000000000000000000000000815230916341493c6091612e199190869086908a908a9060040161333e565b5f6040518083038186803b158015612e2f575f80fd5b505afa158015611330573d5f803e3d5ffd5b3073ffffffffffffffffffffffffffffffffffffffff1663a48fd34b848484604051602001612e7291815260200190565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401612e9f93929190613376565b5f6040518083038186803b158015612eb5575f80fd5b505afa158015612ec7573d5f803e3d5ffd5b50505050505050565b5f8083601f840112612ee0575f80fd5b50813567ffffffffffffffff811115612ef7575f80fd5b602083019150836020828501011115612f0e575f80fd5b9250929050565b5f805f805f60608688031215612f29575f80fd5b85359450602086013567ffffffffffffffff80821115612f47575f80fd5b612f5389838a01612ed0565b90965094506040880135915080821115612f6b575f80fd5b50612f7888828901612ed0565b969995985093965092949392505050565b5f8060208385031215612f9a575f80fd5b823567ffffffffffffffff811115612fb0575f80fd5b612fbc85828601612ed0565b90969095509350505050565b5f805f8060408587031215612fdb575f80fd5b843567ffffffffffffffff80821115612ff2575f80fd5b612ffe88838901612ed0565b90965094506020870135915080821115613016575f80fd5b818701915087601f830112613029575f80fd5b813581811115613037575f80fd5b8860208260051b850101111561304b575f80fd5b95989497505060200194505050565b5f805f806040858703121561306d575f80fd5b843567ffffffffffffffff80821115613084575f80fd5b61309088838901612ed0565b909650945060208701359150808211156130a8575f80fd5b506130b587828801612ed0565b95989497509550505050565b5f805f604084860312156130d3575f80fd5b833567ffffffffffffffff8111156130e9575f80fd5b6130f586828701612ed0565b909790965060209590950135949350505050565b5f81518084525f5b8181101561312d57602081850181015186830182015201613111565b505f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f61317c6020830184613109565b9392505050565b5f8085851115613191575f80fd5b8386111561319d575f80fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156131ea5780818660040360031b1b83161692505b505092915050565b8035602083101561059f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b604081525f6132b560408301858761325b565b8281036020848101919091528451808352858201928201905f5b818110156132eb578451835293830193918301916001016132cf565b509098975050505050505050565b5f60208284031215613309575f80fd5b8151801515811461317c575f80fd5b818382375f9101908152919050565b5f60208284031215613337575f80fd5b5051919050565b858152606060208201525f61335760608301868861325b565b828103604084015261336a81858761325b565b98975050505050505050565b604081525f61338960408301858761325b565b828103602084015261339b8185613109565b969550505050505056fea164736f6c6343000818000a", } // ZkEvmVerifierV1ABI is the input ABI used to generate the binding from. @@ -264,6 +264,37 @@ func (_ZkEvmVerifierV1 *ZkEvmVerifierV1CallerSession) VERSION() (string, error) return _ZkEvmVerifierV1.Contract.VERSION(&_ZkEvmVerifierV1.CallOpts) } +// VKROOT is a free data retrieval call binding the contract method 0x7cad4e13. +// +// Solidity: function VK_ROOT() pure returns(bytes32) +func (_ZkEvmVerifierV1 *ZkEvmVerifierV1Caller) VKROOT(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _ZkEvmVerifierV1.contract.Call(opts, &out, "VK_ROOT") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// VKROOT is a free data retrieval call binding the contract method 0x7cad4e13. +// +// Solidity: function VK_ROOT() pure returns(bytes32) +func (_ZkEvmVerifierV1 *ZkEvmVerifierV1Session) VKROOT() ([32]byte, error) { + return _ZkEvmVerifierV1.Contract.VKROOT(&_ZkEvmVerifierV1.CallOpts) +} + +// VKROOT is a free data retrieval call binding the contract method 0x7cad4e13. +// +// Solidity: function VK_ROOT() pure returns(bytes32) +func (_ZkEvmVerifierV1 *ZkEvmVerifierV1CallerSession) VKROOT() ([32]byte, error) { + return _ZkEvmVerifierV1.Contract.VKROOT(&_ZkEvmVerifierV1.CallOpts) +} + // Verify is a free data retrieval call binding the contract method 0x7e4f7a8a. // // Solidity: function Verify(bytes proof, uint256[] public_inputs) view returns(bool success) diff --git a/bindings/bindings/zkevmverifierv1_more.go b/bindings/bindings/zkevmverifierv1_more.go index 30895a160..6e07f58a5 100644 --- a/bindings/bindings/zkevmverifierv1_more.go +++ b/bindings/bindings/zkevmverifierv1_more.go @@ -13,7 +13,7 @@ const ZkEvmVerifierV1StorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contra var ZkEvmVerifierV1StorageLayout = new(solc.StorageLayout) -var ZkEvmVerifierV1DeployedBin = "0x608060405234801561000f575f80fd5b5060043610610085575f3560e01c80637e4f7a8a116100585780637e4f7a8a146100f2578063a48fd34b14610115578063c8bd017614610128578063ffa1ad741461013b575f80fd5b806309665ee7146100895780632a510436146100a457806341493c60146100ca5780636b61d8e7146100df575b5f80fd5b6100915f5481565b6040519081526020015b60405180910390f35b7fd4e8ecd2357dd882209800acd6abb443d231cf287d77ba62b732ce937c8b56e7610091565b6100dd6100d8366004612d64565b61017a565b005b6100916100ed366004612dd8565b610388565b610105610100366004612e17565b610404565b604051901515815260200161009b565b6100dd610123366004612ea9565b612c23565b6100dd610136366004612f10565b612c90565b604080518082018252600681527f76352e302e3000000000000000000000000000000000000000000000000000006020820152905161009b9190612fb9565b5f6101886004828486612fd2565b61019191612ff9565b90507fd4e8ecd2357dd882209800acd6abb443d231cf287d77ba62b732ce937c8b56e77fd4e8ecd2000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461025f576040517f988066a10000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000080841660048301528216602482015260440160405180910390fd5b5f61026a8787610388565b6040805160028082526060820183529293505f929091602083019080368337019050509050885f1c815f815181106102a4576102a4613041565b602002602001018181525050815f1c816001815181106102c6576102c6613041565b60209081029190910101525f30637e4f7a8a6102e5886004818c612fd2565b856040518463ffffffff1660e01b8152600401610304939291906130b5565b602060405180830381865afa15801561031f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610343919061310c565b90508061037c576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050505050565b5f7f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f1b600284846040516103be92919061312b565b602060405180830381855afa1580156103d9573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906103fc919061313a565b169392505050565b5f6040516102408101610416846108a6565b61042085856108b9565b61042986610908565b6104328761091e565b5f61043e86868a610ab8565b905061044981610dee565b90506104558189610e54565b90506104618189610ee2565b5060608201517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000006104b884630100000085612bb8565b086101c0840152506104cb818587610f4d565b6104d682868a6112c2565b91507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018183086101a08401525061050d9050611667565b610516866127ac565b61051f866126fd565b61052886612324565b61053186611e50565b61053a86611bb6565b610543866117b8565b61020001519050612c1b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f77726f6e67206e756d626572206f66207075626c696320696e707574730000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6572726f72206d6f6420657870000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6572726f72206563206f7065726174696f6e00000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f696e707574732061726520626967676572207468616e207200000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f77726f6e672070726f6f662073697a65000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f6f70656e696e677320626967676572207468616e2072000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f6572726f722070616972696e67000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6572726f722076657269667900000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6572726f722072616e646f6d2067656e206b7a670000000000000000000000006044820152606481fd5b600281146108b6576108b661054f565b50565b5f5b81811015610903577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000833511156108f4576108f461066c565b602092909201916001016108bb565b505050565b61036081811461091a5761091a6106cb565b5050565b61018081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000813511156109545761095461072a565b506101a081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000008135111561098b5761098b61072a565b506101c081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000813511156109c2576109c261072a565b506101e081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000813511156109f9576109f961072a565b5061020081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610a3057610a3061072a565b5061026081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610a6757610a6761072a565b5061030081015f5b6001811015610903577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000082351115610aa957610aa961072a565b60209190910190600101610a6f565b5f60405161024081016467616d6d6181527f239ed22af3191cfccd323949e417667defbcb082d9f31527488e523372ea9e7a60208201527f213da3cb623029a98e0186dc8c1a3a31ee249ab93bfb68abc1103900890eccb960408201527f01fd59b61f15d097ad7701c4dc12b8739eadc1d54664773c3ed5d8104c296c2a60608201527e22ee53909feab41bb47f0e6ddb802bb6096fd2027d89c22d94b4e56e227cd060808201527f14992dea1a6515e3f8a2250e30cb9e3bad58ff44bbfdd1390bc8d0a8f2bddd0f60a08201527f1e82777c7079b474d31f9fedafca8f2d108de5c58a2df629a8af49cd424c8c2960c08201527f060081d04d187d301d4223990acab3c887713358f1705af7f53e07aca0f709dd60e08201527f16911506ad1ccf9b39db250ce7752278c8115127c4f85080c2bd153946b4a5be6101008201527f279df33b57d698efd752579ee90674a7241ecdb21c6cb35cdf8ef7c1af73160a6101208201527f202fa12c1e82de2f49dc4c5bc771b94c8495544bb0055c4c381744cc3d1d332d6101408201527f040315f3fd753e8cca89f353d096fb94fcdf9cd41973954a3dd4ec58cba79d5f6101608201527f18e0b4a84e9429c05d0fd0d304acd0f3cfa93437356c112199d4d7c0162a1c9e6101808201527f2e14e072ab351d1b3838323f75ecf9b6c08043c230423d515febd04e29336b776101a08201527f1553e1a7b6e18ba105733244604cd37d82371c3a7b0503fa4aff460870170bcf6101c08201527f0c203d7594efa49bd977084de30db24ce843e501791176c21b5beda79ceaf1366101e08201527f0c4bddeb52250b0114282b00285f224b812fc581f2b55e5c3a49472069f901f36102008201527f2fb4fbb4677318edec4b80fc8fa22ffcce4a51d5f3771e575e726e790a9f9cbe6102208201527f28518b11376dc02418849d45b1f3b0e00d3f74502d713b002b9d7293a1018d79610240820152610260810160208602808883379081019060c0808784375061030501905060208282601b820160025afa905080610db857610db86107e8565b5080519250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182066040820152509392505050565b5f60405161024060405101636265746181528360208201526020816024601c840160025afa80610e2057610e206107e8565b5080519250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018206602082015250919050565b5f60405161024060405101606564616c7068618252602082018681526020810190506103208601600160400280828437928301929190910190506040610220870182375060208282601b850160025afa905080610eb357610eb36107e8565b50517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181069091529392505050565b60405161024060405101637a657461815283602082015260c0808401604083013760208160e4601c840160025afa80610f1d57610f1d6107e8565b50517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019006606091909101525050565b5f60405160608101516101c0820151915085610f6b81878585610fe6565b5f92505f91505b85821015610fdc577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001853582510992507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018385086020958601959094506001929092019101610f72565b5050509392505050565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e427ce32d4886b01bfe313ba1dba6db8b2045d128178a7164500e0a6c1183096001855f5b868110156110d4577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103860882527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b840992506020919091019060010161102f565b506110e0818789611198565b5060019050855f5b8681101561118e577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001868551090982526020820191507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b840992506001016110e8565b5050505050505050565b600183525f805b838110156111ed5781850151828401517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181830990506020840193508084880152505060018101905061119f565b50602081038201915080840193505061122e6020840160027f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001038551612bb8565b5f5b838110156112bb5760208503945082517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018651840984527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018184097fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090940193925050600101611230565b5050505050565b5f60405160608101516101c0820151915061032084015f806112ea896020850135853561146e565b91506112fd8962a653508a018787611333565b90507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018082840987089998505050505050505050565b5f61135f85857f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b612bb8565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001817f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103840894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e427ce32d4886b01bfe313ba1dba6db8b2045d128178a7164500e0a6c1182099050611418867f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff87612bb8565b94507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018482099695505050505050565b5f83525f602084015280604084015250806060830152505f6080820153603060818201535f60828201536042608382015360536084820153604260858201536032608682015360326087820153602d608882015360506089820153606c608a820153606f608b820153606e608c820153606b608d820153600b608e8201535f602082608f8460025afa80611504576115046107e8565b8251600160208501536042602185015360536022850153604260238501536032602485015360326025850153602d602685015360506027850153606c6028850153606f6029850153606e602a850153606b602b850153600b602c850153602084602d8660025afa91508161157a5761157a6107e8565b8351186020840152600260408401536042604184015360536042840153604260438401536032604484015360326045840153602d604684015360506047840153606c6048840153606f6049840153606e604a840153606b604b840153600b604c84015360208301602081602d8360025afa915050806115fb576115fb6107e8565b507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017001000000000000000000000000000000008351099050602082015160801c7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018183089392505050565b604051610240604051016101c08201517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001036060850151086116ed837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff83612bb8565b90507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e427ce32d4886b01bfe313ba1dba6db8b2045d128178a7164500e0a6c11820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018282098451935091507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001905082820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018282099050806080840152505050565b60405161024081016101608201518152610180820151602082015261028083013560408201526102a08301356060820152610220830135608082015261024083013560a08201526102c083013560c08201526102e083013560e082015260608201516101008201526101e08201516101208201526020816101408360025afa8061184457611844610847565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182510690508160408101925061028085013581526102a0850135602082015261189483836102c0880184612b1f565b61016084016118a98484610220890184612b1f565b61014085016118bd84610260890183612b66565b7f1fa4be93b5e7f7e674d5059b63554fab99638b304ed8310e9fa44c281ac9b03b85527f1a01ae7fac6228e39d3cb5a5e71fd31160f3241e79a5f48ffb3737e6c389b7216020860152805160408087019182529095908160608160075afa91508161192a5761192a6107e8565b60208101915081517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703825261196286828586612a16565b50508360408501945061197f8560608801516102808a0184612aad565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b60608801510995507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000186850993506119ff85856102c08a0184612b1f565b611a0b85828485612a16565b50602082810180517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd470381528251865291810151908501527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260408501527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60608501527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60808501527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60a0850152905160c0840152805160e08401527f22f1acbb03c4508760c2430af35865e7cdf9f3eb1224504fdcc3708ddb954a486101008401527f2a344fad01c2ed0ed73142ae1752429eaea515c6f3f6b941103cc21c2308e1cb6101208401527f159f15b842ba9c8449aa3268f981010d4c7142e5193473d80b464e964845c3f86101408401527f0efd30ac7b6f8d0d3ccbc2207587c2acbad1532dc0293f0d034cf8258cd428b3610160840152925061090390508160405160205f6101808460085afa80611ba857611ba8610789565b505f51610200919091015250565b6040516102406040510160208101604082016101e084015180610160860160e08701518152610100870151610180880152610120870151610140880152611c0186835f8b0184612b1f565b611c14826101808a016101408a01612b66565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018383099150611c49868360408b0184612b1f565b611c5c826101a08a016101408a01612b66565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018383099150611c91868360808b0184612b1f565b611ca4826101c08a016101408a01612b66565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183830991507f239ed22af3191cfccd323949e417667defbcb082d9f31527488e523372ea9e7a86527f213da3cb623029a98e0186dc8c1a3a31ee249ab93bfb68abc1103900890eccb98552611d1c84838884612ad8565b611d2f826101e08a016101408a01612b66565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183830991507f01fd59b61f15d097ad7701c4dc12b8739eadc1d54664773c3ed5d8104c296c2a86527e22ee53909feab41bb47f0e6ddb802bb6096fd2027d89c22d94b4e56e227cd08552611da684838884612ad8565b611db9826102008a016101408a01612b66565b61030088017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184840992507f2fb4fbb4677318edec4b80fc8fa22ffcce4a51d5f3771e575e726e790a9f9cbe87527f28518b11376dc02418849d45b1f3b0e00d3f74502d713b002b9d7293a1018d798652611e3685848985612ad8565b611e4583826101408b01612b66565b505050505050505050565b6040516467616d6d616102408201908152606082015161026083015260e08201516102808301526101008201516102a083015260c0836102c08401377f239ed22af3191cfccd323949e417667defbcb082d9f31527488e523372ea9e7a6101408201527f213da3cb623029a98e0186dc8c1a3a31ee249ab93bfb68abc1103900890eccb96101608201527f01fd59b61f15d097ad7701c4dc12b8739eadc1d54664773c3ed5d8104c296c2a610180808301919091527e22ee53909feab41bb47f0e6ddb802bb6096fd2027d89c22d94b4e56e227cd06101a0808401919091527f2fb4fbb4677318edec4b80fc8fa22ffcce4a51d5f3771e575e726e790a9f9cbe6101c0808501919091527f28518b11376dc02418849d45b1f3b0e00d3f74502d713b002b9d7293a1018d796101e0808601919091526101208601516102008087019190915293870135610220860152918601356102408501528501356102608401528401356102808301528301356102a08201526102c081016103008401602081833750610260840135602091820152601b906102e5906101e085018285850160025afa9250505080612005576120056107e8565b506101e00180517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019006905250565b604051610240604051017f060081d04d187d301d4223990acab3c887713358f1705af7f53e07aca0f709dd81527f16911506ad1ccf9b39db250ce7752278c8115127c4f85080c2bd153946b4a5be602082015261209e604082016101808501358360e08601612a82565b7f279df33b57d698efd752579ee90674a7241ecdb21c6cb35cdf8ef7c1af73160a81527f202fa12c1e82de2f49dc4c5bc771b94c8495544bb0055c4c381744cc3d1d332d60208201526120fe604082016101a08501358360e08601612ad8565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0840135610180850135097f040315f3fd753e8cca89f353d096fb94fcdf9cd41973954a3dd4ec58cba79d5f82527f18e0b4a84e9429c05d0fd0d304acd0f3cfa93437356c112199d4d7c0162a1c9e602083015261218760408301828460e08701612ad8565b507f2e14e072ab351d1b3838323f75ecf9b6c08043c230423d515febd04e29336b7781527f1553e1a7b6e18ba105733244604cd37d82371c3a7b0503fa4aff460870170bcf60208201526121e8604082016101c08501358360e08601612ad8565b7f0c203d7594efa49bd977084de30db24ce843e501791176c21b5beda79ceaf13681527f0c4bddeb52250b0114282b00285f224b812fc581f2b55e5c3a49472069f901f36020820152612243604082018260e0850180612a16565b610300830161032084015f5b600181101561228f5781358452602082013560208501526122796040850184358660e08901612ad8565b602092909201916040919091019060010161224f565b5050507f14992dea1a6515e3f8a2250e30cb9e3bad58ff44bbfdd1390bc8d0a8f2bddd0f81527f1e82777c7079b474d31f9fedafca8f2d108de5c58a2df629a8af49cd424c8c2960208201526122ed60408201858360e08601612ad8565b6102208301358152610240830135602082015261231260408201868360e08601612ad8565b6112bb8160a0840160e0850180612a16565b6040516020810151604082015160608301515f8401517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184610260880135097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101e088013586097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610180890135820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000161020089013587097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a08a0135820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000186820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018284097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600580097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001878a0998507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101808c01358a0894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000188860894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160058a0993507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a08c0135850893507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000188850893507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001818a099250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101c08b0135830891507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000187830891507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183850997507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018289097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001908103985085890997507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160808a01518908975061037c88828c612034565b60405160026301000000016102406040510161271e81836060860151612bb8565b91506127338183610140870160a08701612aad565b61274681610100860160a0860180612a4c565b612755818360a0860180612a82565b6127678160c0860160a0860180612a4c565b61277e816101c085015160a0860160a08701612a82565b505060c00180517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703905250565b6040515f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160208301516101e08501350990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040830151820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610180840135820890505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160208401516102008601350990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040840151820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0850135820890505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160408501516101c08701350890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182840992507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018184099250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000015f840151830991507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610260850135830991507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0840151830860808401519092507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000190810391508183087f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001036101209390930192909252505050565b8151845260208201516020850152825160408501526020830151606085015260408160808660065afa806112bb576112bb61060d565b8151845260208201516020850152823560408501526020830135606085015260408160808660065afa806112bb576112bb61060d565b815184526020820151602085015282604085015260408160608660075afa806112bb576112bb61060d565b813584526020820135602085015282604085015260408160608660075afa806112bb576112bb61060d565b815184526020820151602085015282604085015260408460608660075afa815160408601526020820151606086015260408260808760065afa16806112bb576112bb61060d565b813584526020820135602085015282604085015260408460608660075afa815160408601526020820151606086015260408260808760065afa16806112bb576112bb61060d565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001838335097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181835108825250505050565b602083526020808401526020604084015280606084015250806080830152507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160a08201525f60208260c08460055afa80612c1557612c156105ae565b50505190565b949350505050565b5f546040517f41493c6000000000000000000000000000000000000000000000000000000000815230916341493c6091612c689190869086908a908a90600401613151565b5f6040518083038186803b158015612c7e575f80fd5b505afa15801561118e573d5f803e3d5ffd5b3073ffffffffffffffffffffffffffffffffffffffff1663a48fd34b848484604051602001612cc191815260200190565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401612cee93929190613189565b5f6040518083038186803b158015612d04575f80fd5b505afa158015612d16573d5f803e3d5ffd5b50505050505050565b5f8083601f840112612d2f575f80fd5b50813567ffffffffffffffff811115612d46575f80fd5b602083019150836020828501011115612d5d575f80fd5b9250929050565b5f805f805f60608688031215612d78575f80fd5b85359450602086013567ffffffffffffffff80821115612d96575f80fd5b612da289838a01612d1f565b90965094506040880135915080821115612dba575f80fd5b50612dc788828901612d1f565b969995985093965092949392505050565b5f8060208385031215612de9575f80fd5b823567ffffffffffffffff811115612dff575f80fd5b612e0b85828601612d1f565b90969095509350505050565b5f805f8060408587031215612e2a575f80fd5b843567ffffffffffffffff80821115612e41575f80fd5b612e4d88838901612d1f565b90965094506020870135915080821115612e65575f80fd5b818701915087601f830112612e78575f80fd5b813581811115612e86575f80fd5b8860208260051b8501011115612e9a575f80fd5b95989497505060200194505050565b5f805f8060408587031215612ebc575f80fd5b843567ffffffffffffffff80821115612ed3575f80fd5b612edf88838901612d1f565b90965094506020870135915080821115612ef7575f80fd5b50612f0487828801612d1f565b95989497509550505050565b5f805f60408486031215612f22575f80fd5b833567ffffffffffffffff811115612f38575f80fd5b612f4486828701612d1f565b909790965060209590950135949350505050565b5f81518084525f5b81811015612f7c57602081850181015186830182015201612f60565b505f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f612fcb6020830184612f58565b9392505050565b5f8085851115612fe0575f80fd5b83861115612fec575f80fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156130395780818660040360031b1b83161692505b505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b604081525f6130c860408301858761306e565b8281036020848101919091528451808352858201928201905f5b818110156130fe578451835293830193918301916001016130e2565b509098975050505050505050565b5f6020828403121561311c575f80fd5b81518015158114612fcb575f80fd5b818382375f9101908152919050565b5f6020828403121561314a575f80fd5b5051919050565b858152606060208201525f61316a60608301868861306e565b828103604084015261317d81858761306e565b98975050505050505050565b604081525f61319c60408301858761306e565b82810360208401526131ae8185612f58565b969550505050505056fea164736f6c6343000818000a" +var ZkEvmVerifierV1DeployedBin = "0x608060405234801561000f575f80fd5b506004361061009f575f3560e01c80637cad4e1311610072578063a48fd34b11610058578063a48fd34b14610154578063c8bd017614610167578063ffa1ad741461017a575f80fd5b80637cad4e131461010c5780637e4f7a8a14610131575f80fd5b806309665ee7146100a35780632a510436146100be57806341493c60146100e45780636b61d8e7146100f9575b5f80fd5b6100ab5f5481565b6040519081526020015b60405180910390f35b7f5a093a2fcb46394f5cadfe55c44d4d572fad9cec7aeb38026b0278322ef07fac6100ab565b6100f76100f2366004612f15565b6101b9565b005b6100ab610107366004612f89565b610527565b7e2f850ee998974d6cc00e50cd0814b098c05bfade466d28573240d057f253526100ab565b61014461013f366004612fc8565b6105a5565b60405190151581526020016100b5565b6100f761016236600461305a565b612dd4565b6100f76101753660046130c1565b612e41565b604080518082018252600681527f76362e312e300000000000000000000000000000000000000000000000000000602082015290516100b5919061316a565b5f6101c76004828486613183565b6101d0916131aa565b90507f5a093a2fcb46394f5cadfe55c44d4d572fad9cec7aeb38026b0278322ef07fac7f5a093a2f000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461029e576040517f988066a10000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000080841660048301528216602482015260440160405180910390fd5b7e2f850ee998974d6cc00e50cd0814b098c05bfade466d28573240d057f253525f6102c98888610527565b90505f6102da60246004888a613183565b6102e3916131f2565b90505f6102f460446024898b613183565b6102fd916131f2565b90505f61030e606460448a8c613183565b610317916131f2565b60408051600580825260c082019092529192505f91906020820160a0803683370190505090508c5f1c815f815181106103525761035261322e565b602002602001018181525050845f1c816001815181106103745761037461322e565b60200260200101818152505083816002815181106103945761039461322e565b60200260200101818152505082816003815181106103b4576103b461322e565b60200260200101818152505081816004815181106103d4576103d461322e565b60209081029190910101528315610417576040517f1fcf917700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b858314610450576040517fd58aec5800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f3073ffffffffffffffffffffffffffffffffffffffff16637e4f7a8a8c8c606490809261048093929190613183565b856040518463ffffffff1660e01b815260040161049f939291906132a2565b602060405180830381865afa1580156104ba573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104de91906132f9565b905080610517576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050505050565b5f7f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f1b6002848460405161055d929190613318565b602060405180830381855afa158015610578573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061059b9190613327565b1690505b92915050565b5f60405161024081016105b784610a47565b6105c18585610a5a565b6105ca86610aa9565b6105d387610abf565b5f6105df86868a610c59565b90506105ea81610f90565b90506105f68189610ff6565b90506106028189611084565b5060608201517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000061065984630200000085612d69565b086101c08401525061066c8185876110ef565b61067782868a611464565b91507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018183086101a0840152506106ae905061180a565b6106b78661295d565b6106c0866128ae565b6106c9866124c9565b6106d286611ff4565b6106db86611d59565b6106e48661195b565b61020001519050612dcc565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f77726f6e67206e756d626572206f66207075626c696320696e707574730000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6572726f72206d6f6420657870000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6572726f72206563206f7065726174696f6e00000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f696e707574732061726520626967676572207468616e207200000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f77726f6e672070726f6f662073697a65000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f6f70656e696e677320626967676572207468616e2072000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f6572726f722070616972696e67000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6572726f722076657269667900000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6572726f722072616e646f6d2067656e206b7a670000000000000000000000006044820152606481fd5b60058114610a5757610a576106f0565b50565b5f5b81811015610aa4577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000083351115610a9557610a9561080d565b60209290920191600101610a5c565b505050565b610360818114610abb57610abb61086c565b5050565b61018081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610af557610af56108cb565b506101a081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610b2c57610b2c6108cb565b506101c081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610b6357610b636108cb565b506101e081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610b9a57610b9a6108cb565b5061020081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610bd157610bd16108cb565b5061026081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610c0857610c086108cb565b5061030081015f5b6001811015610aa4577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000082351115610c4a57610c4a6108cb565b60209190910190600101610c10565b5f60405161024081016467616d6d6181527f2dc54336c06a06f4cf81d186d61710b54b7cc8a885d62068fa20ef5affcc9b2960208201527f0de6d6ca530719fcbbc72fb363fcfe8e678cc8e1ff97ae510902c38704c155d360408201527f016d52b549f5a97e0d20ffd0a98365c9a7d93e3877552678c0ee5a5584413e0160608201527f0969091657a75b12b7eea04d595cba1e87304cb4dd5cfdc78530707d1309732460808201527f1090a057ba86e7a26bf16afd35cb54435f66d95cfe43f55c5ef02db7209e931c60a08201527f2bf5be16a8b5a734fb51960de6ad22594c7bab0936545a91bfdc56a896deba2260c08201527f14ff07d809a066622eeec2671abfea3c61f1cbb4ed507e1decc4bd943a856e8160e08201527f1d6b52dd76d02b4dcd2708bee7f60d4a9ba11305894ec5374da8eb13d120914e6101008201527f2188d80f62696638d9914aebd8f9c50232936e7a3945a8967b010105b1bef2e16101208201527f25bbd1a7a916c59eb45e823e61d067f014a5d7721b0826ee6029c823f078bf056101408201527f048f55df25aea5672048ff344d6ae33323302e49ba4d8f7f3d3d57e1342a5c2c6101608201527f2438994c3232ec28ebbf2010fdcb6b7426ba5da25ae499d2e091a53c8fd7dfec6101808201527f18ee8d5a878f07a6729ecf3d71944fd4a15f2e903a77ee2303b6ab61f9c5509f6101a08201527f02f4278497f8821e95247cda1733795c328ff1505f8ca4535c35d921641583796101c08201527f07c21121e364b3cabb19d7f3cc18ee406b0f3ded1ac8f779508e692e24aff89d6101e08201527f2158407e9af4cedca94a99a2e2ec6718311d1f86b39f89f466c4835badb09ffb6102008201527f2f0a1d1b0bc53914c138f532c5f5eb08aa154bec4694e77a3a1152aea194ca826102208201527f2fe78306d51211fa7d2ecf1c3ccec2d626525525bae105ed19cff3b218ffd6ec610240820152610260810160208602808883379081019060c0808784375061030501905060208282601b820160025afa905080610f5a57610f5a610989565b5080519250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182066040820152509392505050565b5f60405161024060405101636265746181528360208201526020816024601c840160025afa80610fc257610fc2610989565b5080519250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018206602082015250919050565b5f60405161024060405101606564616c7068618252602082018681526020810190506103208601600160400280828437928301929190910190506040610220870182375060208282601b850160025afa90508061105557611055610989565b50517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181069091529392505050565b60405161024060405101637a657461815283602082015260c0808401604083013760208160e4601c840160025afa806110bf576110bf610989565b50517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019006606091909101525050565b5f60405160608101516101c082015191508561110d81878585611188565b5f92505f91505b8582101561117e577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001853582510992507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018385086020958601959094506001929092019101611114565b5050509392505050565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e5aaf0a66b91f8030da595e7d1c6787b9b45fc54c546729acf1ff05360983096001855f5b86811015611276577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103860882527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f2a734ebb326341efa19b0361d9130cd47b26b7488dc6d26eeccd4f3eb878331a84099250602091909101906001016111d1565b5061128281878961133a565b5060019050855f5b86811015611330577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001868551090982526020820191507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f2a734ebb326341efa19b0361d9130cd47b26b7488dc6d26eeccd4f3eb878331a8409925060010161128a565b5050505050505050565b600183525f805b8381101561138f5781850151828401517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001818309905060208401935080848801525050600181019050611341565b5060208103820191508084019350506113d06020840160027f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001038551612d69565b5f5b8381101561145d5760208503945082517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018651840984527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018184097fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909401939250506001016113d2565b5050505050565b5f60405160608101516101c0820151915061032084015f8061148c8960208501358535611611565b91506114a0896301821df98a0187876114d6565b90507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018082840987089998505050505050505050565b5f61150285857f2a734ebb326341efa19b0361d9130cd47b26b7488dc6d26eeccd4f3eb878331a612d69565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001817f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103840894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e5aaf0a66b91f8030da595e7d1c6787b9b45fc54c546729acf1ff053609820990506115bb867f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff87612d69565b94507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018482099695505050505050565b5f83525f602084015280604084015250806060830152505f6080820153603060818201535f60828201536042608382015360536084820153604260858201536032608682015360326087820153602d608882015360506089820153606c608a820153606f608b820153606e608c820153606b608d820153600b608e8201535f602082608f8460025afa806116a7576116a7610989565b8251600160208501536042602185015360536022850153604260238501536032602485015360326025850153602d602685015360506027850153606c6028850153606f6029850153606e602a850153606b602b850153600b602c850153602084602d8660025afa91508161171d5761171d610989565b8351186020840152600260408401536042604184015360536042840153604260438401536032604484015360326045840153602d604684015360506047840153606c6048840153606f6049840153606e604a840153606b604b840153600b604c84015360208301602081602d8360025afa9150508061179e5761179e610989565b507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017001000000000000000000000000000000008351099050602082015160801c7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018183089392505050565b604051610240604051016101c08201517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103606085015108611890837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff83612d69565b90507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e5aaf0a66b91f8030da595e7d1c6787b9b45fc54c546729acf1ff053609820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018282098451935091507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001905082820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018282099050806080840152505050565b60405161024081016101608201518152610180820151602082015261028083013560408201526102a08301356060820152610220830135608082015261024083013560a08201526102c083013560c08201526102e083013560e082015260608201516101008201526101e08201516101208201526020816101408360025afa806119e7576119e76109e8565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182510690508160408101925061028085013581526102a08501356020820152611a3783836102c0880184612cd0565b6101608401611a4c8484610220890184612cd0565b6101408501611a6084610260890183612d17565b7f1fa4be93b5e7f7e674d5059b63554fab99638b304ed8310e9fa44c281ac9b03b85527f1a01ae7fac6228e39d3cb5a5e71fd31160f3241e79a5f48ffb3737e6c389b7216020860152805160408087019182529095908160608160075afa915081611acd57611acd610989565b60208101915081517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47038252611b0586828586612bc7565b505083604085019450611b228560608801516102808a0184612c5e565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f2a734ebb326341efa19b0361d9130cd47b26b7488dc6d26eeccd4f3eb878331a60608801510995507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018685099350611ba285856102c08a0184612cd0565b611bae85828485612bc7565b50602082810180517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd470381528251865291810151908501527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260408501527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60608501527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60808501527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60a0850152905160c0840152805160e08401527f22f1acbb03c4508760c2430af35865e7cdf9f3eb1224504fdcc3708ddb954a486101008401527f2a344fad01c2ed0ed73142ae1752429eaea515c6f3f6b941103cc21c2308e1cb6101208401527f159f15b842ba9c8449aa3268f981010d4c7142e5193473d80b464e964845c3f86101408401527f0efd30ac7b6f8d0d3ccbc2207587c2acbad1532dc0293f0d034cf8258cd428b36101608401529250610aa490508160405160205f6101808460085afa80611d4b57611d4b61092a565b505f51610200919091015250565b6040516102406040510160208101604082016101e084015180610160860160e08701518152610100870151610180880152610120870151610140880152611da486835f8b0184612cd0565b611db7826101808a016101408a01612d17565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018383099150611dec868360408b0184612cd0565b611dff826101a08a016101408a01612d17565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018383099150611e34868360808b0184612cd0565b611e47826101c08a016101408a01612d17565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183830991507f2dc54336c06a06f4cf81d186d61710b54b7cc8a885d62068fa20ef5affcc9b2986527f0de6d6ca530719fcbbc72fb363fcfe8e678cc8e1ff97ae510902c38704c155d38552611ebf84838884612c89565b611ed2826101e08a016101408a01612d17565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183830991507f016d52b549f5a97e0d20ffd0a98365c9a7d93e3877552678c0ee5a5584413e0186527f0969091657a75b12b7eea04d595cba1e87304cb4dd5cfdc78530707d130973248552611f4a84838884612c89565b611f5d826102008a016101408a01612d17565b61030088017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184840992507f2f0a1d1b0bc53914c138f532c5f5eb08aa154bec4694e77a3a1152aea194ca8287527f2fe78306d51211fa7d2ecf1c3ccec2d626525525bae105ed19cff3b218ffd6ec8652611fda85848985612c89565b611fe983826101408b01612d17565b505050505050505050565b6040516467616d6d616102408201908152606082015161026083015260e08201516102808301526101008201516102a083015260c0836102c08401377f2dc54336c06a06f4cf81d186d61710b54b7cc8a885d62068fa20ef5affcc9b296101408201527f0de6d6ca530719fcbbc72fb363fcfe8e678cc8e1ff97ae510902c38704c155d36101608201527f016d52b549f5a97e0d20ffd0a98365c9a7d93e3877552678c0ee5a5584413e01610180808301919091527f0969091657a75b12b7eea04d595cba1e87304cb4dd5cfdc78530707d130973246101a0808401919091527f2f0a1d1b0bc53914c138f532c5f5eb08aa154bec4694e77a3a1152aea194ca826101c0808501919091527f2fe78306d51211fa7d2ecf1c3ccec2d626525525bae105ed19cff3b218ffd6ec6101e0808601919091526101208601516102008087019190915293870135610220860152918601356102408501528501356102608401528401356102808301528301356102a08201526102c081016103008401602081833750610260840135602091820152601b906102e5906101e085018285850160025afa92505050806121aa576121aa610989565b506101e00180517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019006905250565b604051610240604051017f14ff07d809a066622eeec2671abfea3c61f1cbb4ed507e1decc4bd943a856e8181527f1d6b52dd76d02b4dcd2708bee7f60d4a9ba11305894ec5374da8eb13d120914e6020820152612243604082016101808501358360e08601612c33565b7f2188d80f62696638d9914aebd8f9c50232936e7a3945a8967b010105b1bef2e181527f25bbd1a7a916c59eb45e823e61d067f014a5d7721b0826ee6029c823f078bf0560208201526122a3604082016101a08501358360e08601612c89565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0840135610180850135097f048f55df25aea5672048ff344d6ae33323302e49ba4d8f7f3d3d57e1342a5c2c82527f2438994c3232ec28ebbf2010fdcb6b7426ba5da25ae499d2e091a53c8fd7dfec602083015261232c60408301828460e08701612c89565b507f18ee8d5a878f07a6729ecf3d71944fd4a15f2e903a77ee2303b6ab61f9c5509f81527f02f4278497f8821e95247cda1733795c328ff1505f8ca4535c35d92164158379602082015261238d604082016101c08501358360e08601612c89565b7f07c21121e364b3cabb19d7f3cc18ee406b0f3ded1ac8f779508e692e24aff89d81527f2158407e9af4cedca94a99a2e2ec6718311d1f86b39f89f466c4835badb09ffb60208201526123e8604082018260e0850180612bc7565b610300830161032084015f5b600181101561243457813584526020820135602085015261241e6040850184358660e08901612c89565b60209290920191604091909101906001016123f4565b5050507f1090a057ba86e7a26bf16afd35cb54435f66d95cfe43f55c5ef02db7209e931c81527f2bf5be16a8b5a734fb51960de6ad22594c7bab0936545a91bfdc56a896deba22602082015261249260408201858360e08601612c89565b610220830135815261024083013560208201526124b760408201868360e08601612c89565b61145d8160a0840160e0850180612bc7565b6040516020810151604082015160608301515f8401517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184610260880135097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101e088013586097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610180890135820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000161020089013587097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a08a0135820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000186820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018284097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600580097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001878a0998507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101808c01358a0894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000188860894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160058a0993507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a08c0135850893507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000188850893507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001818a099250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101c08b0135830891507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000187830891507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183850997507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018289097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001908103985085890997507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160808a0151890897506128a288828c6121d9565b50505050505050505050565b6040516002630200000001610240604051016128cf81836060860151612d69565b91506128e48183610140870160a08701612c5e565b6128f781610100860160a0860180612bfd565b612906818360a0860180612c33565b6129188160c0860160a0860180612bfd565b61292f816101c085015160a0860160a08701612c33565b505060c00180517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703905250565b6040515f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160208301516101e08501350990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040830151820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610180840135820890505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160208401516102008601350990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040840151820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0850135820890505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160408501516101c08701350890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182840992507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018184099250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000015f840151830991507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610260850135830991507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0840151830860808401519092507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000190810391508183087f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001036101209390930192909252505050565b8151845260208201516020850152825160408501526020830151606085015260408160808660065afa8061145d5761145d6107ae565b8151845260208201516020850152823560408501526020830135606085015260408160808660065afa8061145d5761145d6107ae565b815184526020820151602085015282604085015260408160608660075afa8061145d5761145d6107ae565b813584526020820135602085015282604085015260408160608660075afa8061145d5761145d6107ae565b815184526020820151602085015282604085015260408460608660075afa815160408601526020820151606086015260408260808760065afa168061145d5761145d6107ae565b813584526020820135602085015282604085015260408460608660075afa815160408601526020820151606086015260408260808760065afa168061145d5761145d6107ae565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001838335097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181835108825250505050565b602083526020808401526020604084015280606084015250806080830152507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160a08201525f60208260c08460055afa80612dc657612dc661074f565b50505190565b949350505050565b5f546040517f41493c6000000000000000000000000000000000000000000000000000000000815230916341493c6091612e199190869086908a908a9060040161333e565b5f6040518083038186803b158015612e2f575f80fd5b505afa158015611330573d5f803e3d5ffd5b3073ffffffffffffffffffffffffffffffffffffffff1663a48fd34b848484604051602001612e7291815260200190565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401612e9f93929190613376565b5f6040518083038186803b158015612eb5575f80fd5b505afa158015612ec7573d5f803e3d5ffd5b50505050505050565b5f8083601f840112612ee0575f80fd5b50813567ffffffffffffffff811115612ef7575f80fd5b602083019150836020828501011115612f0e575f80fd5b9250929050565b5f805f805f60608688031215612f29575f80fd5b85359450602086013567ffffffffffffffff80821115612f47575f80fd5b612f5389838a01612ed0565b90965094506040880135915080821115612f6b575f80fd5b50612f7888828901612ed0565b969995985093965092949392505050565b5f8060208385031215612f9a575f80fd5b823567ffffffffffffffff811115612fb0575f80fd5b612fbc85828601612ed0565b90969095509350505050565b5f805f8060408587031215612fdb575f80fd5b843567ffffffffffffffff80821115612ff2575f80fd5b612ffe88838901612ed0565b90965094506020870135915080821115613016575f80fd5b818701915087601f830112613029575f80fd5b813581811115613037575f80fd5b8860208260051b850101111561304b575f80fd5b95989497505060200194505050565b5f805f806040858703121561306d575f80fd5b843567ffffffffffffffff80821115613084575f80fd5b61309088838901612ed0565b909650945060208701359150808211156130a8575f80fd5b506130b587828801612ed0565b95989497509550505050565b5f805f604084860312156130d3575f80fd5b833567ffffffffffffffff8111156130e9575f80fd5b6130f586828701612ed0565b909790965060209590950135949350505050565b5f81518084525f5b8181101561312d57602081850181015186830182015201613111565b505f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f61317c6020830184613109565b9392505050565b5f8085851115613191575f80fd5b8386111561319d575f80fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156131ea5780818660040360031b1b83161692505b505092915050565b8035602083101561059f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b604081525f6132b560408301858761325b565b8281036020848101919091528451808352858201928201905f5b818110156132eb578451835293830193918301916001016132cf565b509098975050505050505050565b5f60208284031215613309575f80fd5b8151801515811461317c575f80fd5b818382375f9101908152919050565b5f60208284031215613337575f80fd5b5051919050565b858152606060208201525f61335760608301868861325b565b828103604084015261336a81858761325b565b98975050505050505050565b604081525f61338960408301858761325b565b828103602084015261339b8185613109565b969550505050505056fea164736f6c6343000818000a" func init() { if err := json.Unmarshal([]byte(ZkEvmVerifierV1StorageLayoutJSON), ZkEvmVerifierV1StorageLayout); err != nil { diff --git a/tx-submitter/batch/batch_cache.go b/common/batch/batch_cache.go similarity index 74% rename from tx-submitter/batch/batch_cache.go rename to common/batch/batch_cache.go index 293466552..508ed63e4 100644 --- a/tx-submitter/batch/batch_cache.go +++ b/common/batch/batch_cache.go @@ -9,10 +9,7 @@ import ( "fmt" "math/big" "sync" - - "morph-l2/tx-submitter/db" - "morph-l2/tx-submitter/iface" - "morph-l2/tx-submitter/types" + "sync/atomic" "github.com/morph-l2/go-ethereum/accounts/abi/bind" "github.com/morph-l2/go-ethereum/common" @@ -21,10 +18,12 @@ import ( "github.com/morph-l2/go-ethereum/crypto" "github.com/morph-l2/go-ethereum/eth" "github.com/morph-l2/go-ethereum/log" + + "morph-l2/common/blob" ) -// BatchCache is a structure for caching and building batch data -// Stores all batch information starting from 0, and has the functionality to pack batches +// BatchCache holds sealed and in-progress rollup batches: it syncs from L1/L2 or local DB, +// packs consecutive L2 blocks into a chunk, seals with blob sidecars, and exposes query/delete APIs. type BatchCache struct { mu sync.RWMutex ctx context.Context @@ -59,36 +58,60 @@ type BatchCache struct { currentBlockNumber uint64 currentBlockHash common.Hash - // Function to determine if batch is upgraded + // Function to determine if batch is upgraded (V0 -> V1) isBatchUpgraded func(uint64) bool + // Function to determine if batch is V2 upgraded (V1 -> V2, multi-blob) + isBatchV2Upgraded func(uint64) bool // Clients and contracts - l1Client iface.Client - l2Clients iface.L2Clients - rollupContract iface.IRollup - l2Caller *types.L2Caller + l1Client L1HeaderClient + l2Clients L2MultiClient + rollupContract RollupBatchReader + l2Gov L2GovCaller // config batchTimeOut uint64 blockInterval uint64 + maxBlobCount int + + // replayL1CommittedBatches is true while InitAndSyncFromRollup is rebuilding committed batches from L2. + replayL1CommittedBatches atomic.Bool } +type batchPackProgressState struct { + lastLoggedOverallPercent uint64 +} + +const batchProgressLogStepPercent uint64 = 20 + +// replayProtocolMaxBlobs is the EIP-4844 per-transaction blob ceiling used when re-sealing +// batches already committed on L1 (independent of max_blob_count flag). +const replayProtocolMaxBlobs = 6 + // NewBatchCache creates and initializes a new BatchCache instance func NewBatchCache( isBatchUpgraded func(uint64) bool, - l1Client iface.Client, - l2Clients []iface.L2Client, - rollupContract iface.IRollup, - l2Caller *types.L2Caller, - ldb *db.Db, + isBatchV2Upgraded func(uint64) bool, + maxBlobCount int, + l1Client L1HeaderClient, + l2Clients L2MultiClient, + rollupContract RollupBatchReader, + l2Gov L2GovCaller, + ldb SealedBatchKV, ) *BatchCache { if isBatchUpgraded == nil { // Default implementation: always returns true (use V1 version) isBatchUpgraded = func(uint64) bool { return true } } + if isBatchV2Upgraded == nil { + // Default: V2 not yet activated + isBatchV2Upgraded = func(uint64) bool { return false } + } + if maxBlobCount <= 0 { + log.Crit("maxBlobCount must be greater than 0") + } ctx := context.Background() - ifL2Clients := iface.L2Clients{Clients: l2Clients} - _, err := ifL2Clients.BlockNumber(ctx) + _, err := l2Clients.BlockNumber(ctx) if err != nil { log.Error("Error getting block number", "err", err) } @@ -113,11 +136,13 @@ func NewBatchCache( currentBlockNumber: 0, currentBlockHash: common.Hash{}, isBatchUpgraded: isBatchUpgraded, + isBatchV2Upgraded: isBatchV2Upgraded, l1Client: l1Client, - l2Clients: iface.L2Clients{Clients: l2Clients}, + l2Clients: l2Clients, rollupContract: rollupContract, - l2Caller: l2Caller, + l2Gov: l2Gov, batchStorage: NewBatchStorage(ldb), + maxBlobCount: maxBlobCount, } } @@ -269,6 +294,9 @@ func (bc *BatchCache) InitAndSyncFromRollup() error { if bc.initDone { return nil } + bc.replayL1CommittedBatches.Store(true) + defer bc.replayL1CommittedBatches.Store(false) + err := bc.Init() if err != nil { return err @@ -290,7 +318,8 @@ func (bc *BatchCache) InitAndSyncFromRollup() error { return fmt.Errorf("get batch block range err: %w,start %v, end %v", err, startNum, endNum) } log.Info("assemble batch block range", "startNum", startNum, "endNum", endNum) - batchHeaderBytes, err := bc.assembleBatchHeaderFromL2Blocks(startNum, endNum) + replayIdx := i + batchHeaderBytes, err := bc.assembleBatchHeaderFromL2Blocks(startNum, endNum, &replayIdx) if err != nil { return err } @@ -317,11 +346,11 @@ func (bc *BatchCache) LatestBatchIndex() (uint64, error) { } func (bc *BatchCache) updateBatchConfigFromGov() error { - interval, err := bc.l2Caller.BatchBlockInterval(nil) + interval, err := bc.l2Gov.BatchBlockInterval(nil) if err != nil { return err } - timeout, err := bc.l2Caller.BatchTimeout(nil) + timeout, err := bc.l2Gov.BatchTimeout(nil) if err != nil { return err } @@ -452,7 +481,7 @@ func (bc *BatchCache) GetLatestSealedBatchIndex() uint64 { // CalculateCapWithProposalBlock calculates batch capacity after including the specified block func (bc *BatchCache) CalculateCapWithProposalBlock(blockNumber uint64, withdrawRoot common.Hash) (bool, error) { - if len(bc.l2Clients.Clients) == 0 { + if bc.l2Clients.Len() == 0 { return false, fmt.Errorf("l2 client is nil") } @@ -514,11 +543,20 @@ func (bc *BatchCache) CalculateCapWithProposalBlock(blockNumber uint64, withdraw bc.currentWithdrawRoot = withdrawRoot // Check capacity: if compressed size would exceed limit after adding current block + effectiveBlobCount := bc.effectiveMaxBlobCount(header.Time) + log.Debug("batch capacity check", + "proposedBlock", blockNumber, + "blockTime", header.Time, + "compressedLimitBytes", effectiveBlobCount*blob.MaxBlobBytesSize, + "effectiveBlobCount", effectiveBlobCount, + "configuredMaxBlobCount", bc.maxBlobCount, + "v2Upgraded", bc.isBatchV2Upgraded(header.Time), + ) var exceeded bool if bc.isBatchUpgraded(header.Time) { - exceeded, err = bc.batchData.WillExceedCompressedSizeLimit(blockContext, txsPayload) + exceeded, err = bc.batchData.WillExceedCompressedSizeLimit(blockContext, txsPayload, effectiveBlobCount) } else { - exceeded, err = bc.batchData.EstimateCompressedSizeWithNewPayload(txsPayload) + exceeded, err = bc.batchData.EstimateCompressedSizeWithNewPayload(txsPayload, effectiveBlobCount) } if err != nil { return false, fmt.Errorf("failed to estimate compressed size: %w", err) @@ -608,7 +646,11 @@ func (bc *BatchCache) FetchAndCacheHeader(blockNumber uint64, withdrawRoot commo // - error: returns error if sealing fails // // Note: Sealed batch will be stored in BatchCache's sealedBatches, not sent anywhere -func (bc *BatchCache) SealBatch(sequencerSets []byte, blockTimestamp uint64) (uint64, BatchHeaderBytes, bool, error) { +// +// replayCommittedBatchIndex, when non-nil, is the rollup batch index being re-sealed while syncing +// from L1 (InitAndSyncFromRollup). After V2 multi-blob, blob capacity is capped at replayProtocolMaxBlobs +// (6), not max_blob_count, without querying L1 CommitBatch logs. +func (bc *BatchCache) SealBatch(sequencerSets []byte, blockTimestamp uint64, replayCommittedBatchIndex *uint64) (uint64, BatchHeaderBytes, bool, error) { bc.mu.Lock() defer bc.mu.Unlock() @@ -617,24 +659,37 @@ func (bc *BatchCache) SealBatch(sequencerSets []byte, blockTimestamp uint64) (ui return 0, BatchHeaderBytes{}, false, errors.New("failed to seal batch: batch cache is empty") } + sealBlobCap := bc.sealEffectiveBlobCount(blockTimestamp, replayCommittedBatchIndex) + // Compress data and calculate dataHash - compressedPayload, batchDataHash, err := bc.handleBatchSealing(blockTimestamp) + compressedPayload, batchDataHash, sealBlobCap, err := bc.handleBatchSealing(blockTimestamp, sealBlobCap, replayCommittedBatchIndex) if err != nil { return 0, BatchHeaderBytes{}, false, fmt.Errorf("failed to handle batch sealing: %w", err) } // Check if sealed data size reaches expected value - // Expected value: compressed payload size close to or reaches MaxBlobBytesSize - // Use 90% as threshold, i.e., if compressed size >= MaxBlobBytesSize * 0.9, consider it reached expected - threshold := float64(MaxBlobBytesSize) * 0.9 + // Expected value: compressed payload size close to or reaches total blob capacity + // Use 90% as threshold, i.e., if compressed size >= totalCapacity * 0.9, consider it reached expected + effectiveBlobCount := sealBlobCap + totalBlobCapacity := effectiveBlobCount * blob.MaxBlobBytesSize + threshold := float64(totalBlobCapacity) * 0.9 expectedSizeThreshold := uint64(threshold) reachedExpectedSize := uint64(len(compressedPayload)) >= expectedSizeThreshold // Generate blob sidecar - sidecar, err := MakeBlobTxSidecar(compressedPayload) + sidecar, err := blob.MakeBlobTxSidecar(compressedPayload, effectiveBlobCount) if err != nil { return 0, BatchHeaderBytes{}, false, fmt.Errorf("failed to create blob sidecar: %w", err) } + log.Info("Sealing batch payload stats", + "compressedPayloadBytes", len(compressedPayload), + "effectiveBlobCount", effectiveBlobCount, + "configuredMaxBlobCount", bc.maxBlobCount, + "replayCommittedBatchIndex", replayCommittedBatchIndex, + "v2Upgraded", bc.isBatchV2Upgraded(blockTimestamp), + "sidecarBlobCount", len(sidecar.Blobs), + "sidecarCapacityBytes", effectiveBlobCount*blob.MaxBlobBytesSize, + ) // Create batch header batchHeader := bc.createBatchHeader(batchDataHash, sidecar, crypto.Keccak256Hash(sequencerSets), blockTimestamp) @@ -711,7 +766,7 @@ func (bc *BatchCache) SealBatch(sequencerSets []byte, blockTimestamp uint64) (ui // Save block count before resetting batch data for logging blockCount := bc.batchData.BlockNum() - bc.logSealedBatch(batchHeader, batchHash, blockCount) + bc.logSealedBatch(batchHeader, batchHash, blockCount, len(sidecar.Blobs)) // Reset currently accumulated batch data bc.batchData = NewBatchData() @@ -719,8 +774,9 @@ func (bc *BatchCache) SealBatch(sequencerSets []byte, blockTimestamp uint64) (ui return batchIndex, batchHeader, reachedExpectedSize, nil } -// handleBatchSealing determines which version to use for compression and calculates data hash -func (bc *BatchCache) handleBatchSealing(blockTimestamp uint64) ([]byte, common.Hash, error) { +// handleBatchSealing determines which version to use for compression and calculates data hash. +// The returned sealBlobCap may be raised during L1 batch replay so the compressed payload fits. +func (bc *BatchCache) handleBatchSealing(blockTimestamp uint64, sealBlobCap int, replayCommittedBatchIndex *uint64) ([]byte, common.Hash, int, error) { var ( compressedPayload []byte batchDataHash common.Hash @@ -729,33 +785,107 @@ func (bc *BatchCache) handleBatchSealing(blockTimestamp uint64) ([]byte, common. // Check if upgraded version should be used if bc.isBatchUpgraded(blockTimestamp) { - compressedPayload, err = CompressBatchBytes(bc.batchData.TxsPayloadV2()) + compressedPayload, err = blob.CompressBatchBytes(bc.batchData.TxsPayloadV2()) if err != nil { - return nil, common.Hash{}, fmt.Errorf("failed to compress upgraded payload: %w", err) + return nil, common.Hash{}, sealBlobCap, fmt.Errorf("failed to compress upgraded payload: %w", err) } - if len(compressedPayload) <= MaxBlobBytesSize { + replayRaise := replayCommittedBatchIndex != nil || bc.replayL1CommittedBatches.Load() + + if replayRaise { + needed := (len(compressedPayload) + blob.MaxBlobBytesSize - 1) / blob.MaxBlobBytesSize + if needed > replayProtocolMaxBlobs { + if replayCommittedBatchIndex != nil { + return nil, common.Hash{}, sealBlobCap, fmt.Errorf( + "replay batch %d: compressed payload needs %d blobs (protocol max %d)", + *replayCommittedBatchIndex, needed, replayProtocolMaxBlobs, + ) + } + return nil, common.Hash{}, sealBlobCap, fmt.Errorf( + "replay (L1 sync): compressed payload needs %d blobs (protocol max %d)", needed, replayProtocolMaxBlobs, + ) + } + if needed > sealBlobCap { + if replayCommittedBatchIndex != nil { + log.Info("replay: raising seal blob cap to fit compressed V2 payload", + "batchIndex", *replayCommittedBatchIndex, + "fromBlobs", sealBlobCap, "toBlobs", needed, + "compressedBytes", len(compressedPayload)) + } else { + log.Info("replay: raising seal blob cap to fit compressed V2 payload", + "fromBlobs", sealBlobCap, "toBlobs", needed, + "compressedBytes", len(compressedPayload)) + } + sealBlobCap = needed + } + } + + if len(compressedPayload) <= sealBlobCap*blob.MaxBlobBytesSize { batchDataHash, err = bc.batchData.DataHashV2() if err != nil { - return nil, common.Hash{}, fmt.Errorf("failed to calculate upgraded data hash: %w", err) + return nil, common.Hash{}, sealBlobCap, fmt.Errorf("failed to calculate upgraded data hash: %w", err) } - return compressedPayload, batchDataHash, nil + return compressedPayload, batchDataHash, sealBlobCap, nil + } + if bc.isBatchV2Upgraded(blockTimestamp) { + return nil, common.Hash{}, sealBlobCap, fmt.Errorf( + "compressed V2 batch size %d exceeds capacity for %d blobs (%d bytes)", + len(compressedPayload), sealBlobCap, sealBlobCap*blob.MaxBlobBytesSize, + ) } } // Fall back to the old version - compressedPayload, err = CompressBatchBytes(bc.batchData.TxsPayload()) + compressedPayload, err = blob.CompressBatchBytes(bc.batchData.TxsPayload()) if err != nil { - return nil, common.Hash{}, fmt.Errorf("failed to compress payload: %w", err) + return nil, common.Hash{}, sealBlobCap, fmt.Errorf("failed to compress payload: %w", err) } + + replayRaise := replayCommittedBatchIndex != nil || bc.replayL1CommittedBatches.Load() + + if replayRaise { + needed := (len(compressedPayload) + blob.MaxBlobBytesSize - 1) / blob.MaxBlobBytesSize + if needed > replayProtocolMaxBlobs { + if replayCommittedBatchIndex != nil { + return nil, common.Hash{}, sealBlobCap, fmt.Errorf( + "replay batch %d: legacy compressed payload needs %d blobs (protocol max %d)", + *replayCommittedBatchIndex, needed, replayProtocolMaxBlobs, + ) + } + return nil, common.Hash{}, sealBlobCap, fmt.Errorf( + "replay (L1 sync): legacy compressed payload needs %d blobs (protocol max %d)", needed, replayProtocolMaxBlobs, + ) + } + if needed > sealBlobCap { + if replayCommittedBatchIndex != nil { + log.Info("replay: raising seal blob cap to fit legacy compressed payload", + "batchIndex", *replayCommittedBatchIndex, + "fromBlobs", sealBlobCap, "toBlobs", needed, + "compressedBytes", len(compressedPayload)) + } else { + log.Info("replay: raising seal blob cap to fit legacy compressed payload", + "fromBlobs", sealBlobCap, "toBlobs", needed, + "compressedBytes", len(compressedPayload)) + } + sealBlobCap = needed + } + } + + if len(compressedPayload) > sealBlobCap*blob.MaxBlobBytesSize { + return nil, common.Hash{}, sealBlobCap, fmt.Errorf( + "compressed batch size %d exceeds capacity for %d blobs (%d bytes)", + len(compressedPayload), sealBlobCap, sealBlobCap*blob.MaxBlobBytesSize, + ) + } + batchDataHash = bc.batchData.DataHash() - return compressedPayload, batchDataHash, nil + return compressedPayload, batchDataHash, sealBlobCap, nil } // createBatchHeader creates BatchHeader func (bc *BatchCache) createBatchHeader(dataHash common.Hash, sidecar *ethtypes.BlobTxSidecar, sequencerSetVerifyHash common.Hash, blockTimestamp uint64) BatchHeaderBytes { - blobHashes := []common.Hash{EmptyVersionedHash} + blobHashes := []common.Hash{blob.EmptyVersionedHash} if sidecar != nil && len(sidecar.Blobs) > 0 { blobHashes = sidecar.BlobHashes() } @@ -790,6 +920,14 @@ func (bc *BatchCache) createBatchHeader(dataHash common.Hash, sidecar *ethtypes. BatchHeaderV0: batchHeaderV0, LastBlockNumber: bc.lastPackedBlockHeight, } + // V2 is activated: use V1-format header (257 bytes) with version byte 2. + // Store keccak256(concat all blob hashes) at offset 57 as the aggregated blob hash. + if bc.isBatchV2Upgraded(blockTimestamp) { + batchHeaderV1.BlobVersionedHash = aggregateBlobHashes(blobHashes) + h := batchHeaderV1.Bytes() + h[0] = BatchHeaderVersion2 + return h + } return batchHeaderV1.Bytes() } @@ -839,6 +977,39 @@ func isL1MessageTxType(tx *ethtypes.Transaction) bool { return tx.Type() == ethtypes.L1MessageTxType } +// aggregateBlobHashes computes keccak256 of the concatenation of all blob hash bytes. +func aggregateBlobHashes(hashes []common.Hash) common.Hash { + var concat []byte + for _, h := range hashes { + concat = append(concat, h[:]...) + } + return crypto.Keccak256Hash(concat) +} + +// effectiveMaxBlobCount returns the allowed blob count for the given block timestamp. +// V2 multi-blob is only permitted when isBatchV2Upgraded returns true; otherwise cap at 1. +func (bc *BatchCache) effectiveMaxBlobCount(blockTimestamp uint64) int { + if bc.isBatchV2Upgraded(blockTimestamp) { + return bc.maxBlobCount + } + return 1 +} + +// sealEffectiveBlobCount is the blob count used for sealing. +// Live packing uses effectiveMaxBlobCount (max_blob_count flag). +// Replaying an L1-committed batch after V2 multi-blob uses replayProtocolMaxBlobs (6), independent of +// max_blob_count and without L1 log queries; handleBatchSealing tightens from compressed size (still ≤6). +func (bc *BatchCache) sealEffectiveBlobCount(blockTimestamp uint64, replayCommittedBatchIndex *uint64) int { + base := bc.effectiveMaxBlobCount(blockTimestamp) + if replayCommittedBatchIndex == nil { + return base + } + if !bc.isBatchV2Upgraded(blockTimestamp) { + return base + } + return replayProtocolMaxBlobs +} + // buildBlockContext builds BlockContext from block header (60 bytes) // Format: Number(8) || Timestamp(8) || BaseFee(32) || GasLimit(8) || numTxs(2) || numL1Messages(2) func buildBlockContext(header *ethtypes.Header, txsNum, l1MsgNum int) []byte { @@ -871,7 +1042,14 @@ func buildBlockContext(header *ethtypes.Header, txsNum, l1MsgNum int) []byte { func (bc *BatchCache) assembleBatchHeaderFromL2Blocks( startBlockNum, endBlockNum uint64, + replayCommittedBatchIndex *uint64, ) (*BatchHeaderBytes, error) { + // Fresh accumulation for this chain batch; a failed prior SealBatch must not double-pack blocks. + bc.mu.Lock() + bc.batchData = NewBatchData() + bc.ClearCurrent() + bc.mu.Unlock() + ctx := context.Background() callOpts := &bind.CallOpts{ Context: ctx, @@ -879,7 +1057,7 @@ func (bc *BatchCache) assembleBatchHeaderFromL2Blocks( // Fetch blocks from L2 client in the specified range and accumulate to batch for blockNum := startBlockNum; blockNum <= endBlockNum; blockNum++ { callOpts.BlockNumber = new(big.Int).SetUint64(blockNum) - root, err := bc.l2Caller.GetTreeRoot(callOpts) + root, err := bc.l2Gov.GetTreeRoot(callOpts) if err != nil { return nil, fmt.Errorf("failed to get withdraw root at block %d: %w", blockNum, err) } @@ -896,7 +1074,7 @@ func (bc *BatchCache) assembleBatchHeaderFromL2Blocks( } } - sequencerSet, _, err := bc.l2Caller.GetSequencerSetBytes(callOpts) + sequencerSet, _, err := bc.l2Gov.GetSequencerSetBytes(callOpts) if err != nil { return nil, fmt.Errorf("failed to get sequencer set verify hash at block %d: %w", callOpts.BlockNumber.Uint64(), err) } @@ -908,7 +1086,7 @@ func (bc *BatchCache) assembleBatchHeaderFromL2Blocks( blockTimestamp := lastBlock.Time() // Seal batch and generate batchHeader - batchIndex, batchHeader, reachedExpectedSize, err := bc.SealBatch(sequencerSet, blockTimestamp) + batchIndex, batchHeader, reachedExpectedSize, err := bc.SealBatch(sequencerSet, blockTimestamp, replayCommittedBatchIndex) if err != nil { return nil, fmt.Errorf("failed to seal batch: %w", err) } @@ -937,11 +1115,12 @@ func (bc *BatchCache) assembleUnFinalizeBatchHeaderFromL2Blocks() error { return fmt.Errorf("failed to get start block %d: %w", startBlockNum, err) } startBlockTime := startBlock.Time() + progressState := batchPackProgressState{} // Fetch blocks from L2 client in the specified range and accumulate to batch for blockNum := startBlockNum; blockNum <= endBlockNum; blockNum++ { callOpts.BlockNumber = new(big.Int).SetUint64(blockNum) - root, err := bc.l2Caller.GetTreeRoot(callOpts) + root, err := bc.l2Gov.GetTreeRoot(callOpts) if err != nil { return fmt.Errorf("failed to get withdraw root at block %d: %w", blockNum, err) } @@ -958,6 +1137,7 @@ func (bc *BatchCache) assembleUnFinalizeBatchHeaderFromL2Blocks() error { return fmt.Errorf("failed to get block %d: %w", blockNum, err) } nowBlockTime := nowBlock.Time() + bc.logBatchPackingProgress(startBlockNum, blockNum, startBlockTime, nowBlockTime, &progressState) // Check timeout: if elapsed time >= batchTimeOut, must seal batch immediately // This ensures batch is sealed before exceeding the maximum timeout configured in gov contract @@ -989,6 +1169,7 @@ func (bc *BatchCache) assembleUnFinalizeBatchHeaderFromL2Blocks() error { return fmt.Errorf("failed to get start block %d: %w", startBlockNum, err) } startBlockTime = startBlock.Time() + progressState = batchPackProgressState{} index, err := bc.parentBatchHeader.BatchIndex() if err != nil { return err @@ -1005,7 +1186,7 @@ func (bc *BatchCache) assembleUnFinalizeBatchHeaderFromL2Blocks() error { } func (bc *BatchCache) SealBatchAndCheck(callOpts *bind.CallOpts, ci *big.Int) (common.Hash, bool, uint64, error) { - sequencerSetBytes, _, err := bc.l2Caller.GetSequencerSetBytes(callOpts) + sequencerSetBytes, _, err := bc.l2Gov.GetSequencerSetBytes(callOpts) if err != nil { return common.Hash{}, false, 0, err } @@ -1015,7 +1196,7 @@ func (bc *BatchCache) SealBatchAndCheck(callOpts *bind.CallOpts, ci *big.Int) (c } blockTimestamp := lastBlock.Time() // Seal batch and generate batchHeader - batchIndex, batchHeaderBytes, reachedExpectedSize, err := bc.SealBatch(sequencerSetBytes, blockTimestamp) + batchIndex, batchHeaderBytes, reachedExpectedSize, err := bc.SealBatch(sequencerSetBytes, blockTimestamp, nil) if err != nil { return common.Hash{}, false, 0, fmt.Errorf("failed to seal batch: %w", err) } @@ -1078,19 +1259,40 @@ func (bc *BatchCache) Delete(batchIndex uint64) error { } // logSealedBatch logs the details of the sealed batch for debugging purposes. -func (bc *BatchCache) logSealedBatch(batchHeader BatchHeaderBytes, batchHash common.Hash, blockCount uint16) { - log.Info("Sealed batch header", "batchHash", batchHash.Hex()) +func (bc *BatchCache) logSealedBatch(batchHeader BatchHeaderBytes, batchHash common.Hash, blockCount uint16, blobCount int) { + version, err := batchHeader.Version() + if err != nil { + version = 0 + } + blobCommitHash, blobErr := batchHeader.BlobCommitHash() + if blobErr != nil { + log.Warn("Sealed batch: blob commit hash unavailable", "batchHash", batchHash.Hex(), "version", version, "err", blobErr) + } + log.Info("Sealed batch header", + "batchHash", batchHash.Hex(), + "version", version, + "blobCommitHash", blobCommitHash.Hex(), + "blobCount", blobCount, + ) batchIndex, _ := batchHeader.BatchIndex() l1MessagePopped, _ := batchHeader.L1MessagePopped() totalL1MessagePopped, _ := batchHeader.TotalL1MessagePopped() dataHash, _ := batchHeader.DataHash() parentBatchHash, _ := batchHeader.ParentBatchHash() - log.Info(fmt.Sprintf("===batchIndex: %d \n===L1MessagePopped: %d \n===TotalL1MessagePopped: %d \n===dataHash: %x \n===blockCount: %d \n===ParentBatchHash: %x \n", + blobFieldLabel := "BlobVersionedHash" + if version >= BatchHeaderVersion2 { + blobFieldLabel = "BlobHashesHash" + } + log.Info(fmt.Sprintf("===version: %d \n===batchIndex: %d \n===L1MessagePopped: %d \n===TotalL1MessagePopped: %d \n===dataHash: %x \n===%s: %x \n===blockCount: %d \n===blobCount: %d \n===ParentBatchHash: %x \n", + version, batchIndex, l1MessagePopped, totalL1MessagePopped, dataHash, + blobFieldLabel, + blobCommitHash, blockCount, + blobCount, parentBatchHash)) } @@ -1144,11 +1346,12 @@ func (bc *BatchCache) AssembleCurrentBatchHeader() error { return fmt.Errorf("failed to get start block %d: %w", startBlockNum, err) } startBlockTime := startBlock.Time() + progressState := batchPackProgressState{} // Fetch blocks from L2 client in the specified range and accumulate to batch for blockNum := currentBlockNum + 1; blockNum <= endBlockNum; blockNum++ { callOpts.BlockNumber = new(big.Int).SetUint64(blockNum) - root, err := bc.l2Caller.GetTreeRoot(callOpts) + root, err := bc.l2Gov.GetTreeRoot(callOpts) if err != nil { return fmt.Errorf("failed to get withdraw root at block %d: %w", blockNum, err) } @@ -1165,6 +1368,7 @@ func (bc *BatchCache) AssembleCurrentBatchHeader() error { return fmt.Errorf("failed to get block %d: %w", blockNum, err) } nowBlockTime := nowBlock.Time() + bc.logBatchPackingProgress(startBlockNum, blockNum, startBlockTime, nowBlockTime, &progressState) // Check timeout: if elapsed time >= batchTimeOut, must seal batch immediately // This ensures batch is sealed before exceeding the maximum timeout configured in gov contract @@ -1182,7 +1386,7 @@ func (bc *BatchCache) AssembleCurrentBatchHeader() error { // check ensures batch is sealed before exceeding the maximum timeout if exceeded || (bc.blockInterval > 0 && (blockNum-startBlockNum+1) == bc.blockInterval) || timeout { log.Info("block exceeds limit", "start", startBlockNum, "to", blockNum, "exceeded", exceeded, "timeout", timeout) - sequencerSetBytes, _, err := bc.l2Caller.GetSequencerSetBytes(callOpts) + sequencerSetBytes, _, err := bc.l2Gov.GetSequencerSetBytes(callOpts) if err != nil { return fmt.Errorf("failed to get sequencer set verify hash at block %d: %w", callOpts.BlockNumber.Uint64(), err) } @@ -1191,7 +1395,7 @@ func (bc *BatchCache) AssembleCurrentBatchHeader() error { return fmt.Errorf("failed to get last block %d: %w", bc.lastPackedBlockHeight, err) } blockTimestamp := lastBlock.Time() - batchIndex, _, _, err := bc.SealBatch(sequencerSetBytes, blockTimestamp) + batchIndex, _, _, err := bc.SealBatch(sequencerSetBytes, blockTimestamp, nil) if err != nil { return fmt.Errorf("failed to seal batch: %w", err) } @@ -1205,6 +1409,7 @@ func (bc *BatchCache) AssembleCurrentBatchHeader() error { return fmt.Errorf("failed to get start block %d: %w", startBlockNum, err) } startBlockTime = startBlock.Time() + progressState = batchPackProgressState{} } // Pack current block (confirm and append to batch) @@ -1215,6 +1420,97 @@ func (bc *BatchCache) AssembleCurrentBatchHeader() error { return nil } +func (bc *BatchCache) logBatchPackingProgress(startBlockNum, currentBlockNum, startBlockTime, currentBlockTime uint64, state *batchPackProgressState) { + if state == nil || currentBlockNum < startBlockNum { + return + } + + elapsedTime := uint64(0) + if currentBlockTime >= startBlockTime { + elapsedTime = currentBlockTime - startBlockTime + } + + packedBlocks := currentBlockNum - startBlockNum + 1 + effectiveBlobCount := bc.effectiveMaxBlobCount(currentBlockTime) + totalBlobCapacity := uint64(effectiveBlobCount * blob.MaxBlobBytesSize) + payloadBytes := uint64(0) + if totalBlobCapacity > 0 { + payloadBytes = bc.estimatedBatchPayloadBytesWithCurrent(currentBlockTime) + } + + timePercent := uint64(0) + if bc.batchTimeOut > 0 { + timePercent = progressPercent(elapsedTime, bc.batchTimeOut) + } + + blockPercent := uint64(0) + if bc.blockInterval > 0 { + blockPercent = progressPercent(packedBlocks, bc.blockInterval) + } + + blobPercent := uint64(0) + if totalBlobCapacity > 0 { + blobPercent = progressPercent(payloadBytes, totalBlobCapacity) + } + + overallPercent := maxUint64(timePercent, blockPercent, blobPercent) + // Throttle progress logs to reduce noisy output. + overallStep := (overallPercent / batchProgressLogStepPercent) * batchProgressLogStepPercent + if overallStep <= state.lastLoggedOverallPercent { + return + } + state.lastLoggedOverallPercent = overallStep + + log.Info("Batch packing progress", + "loadedBlockHeight", currentBlockNum, + "overallPercent", overallPercent, + "timePercent", timePercent, + "blockPercent", blockPercent, + "blobPercent", blobPercent, + ) +} + +func (bc *BatchCache) estimatedBatchPayloadBytesWithCurrent(blockTimestamp uint64) uint64 { + bc.mu.RLock() + defer bc.mu.RUnlock() + + var ( + existingBlockContextLen int + existingTxPayloadLen int + ) + if bc.batchData != nil { + existingBlockContextLen = len(bc.batchData.blockContexts) + existingTxPayloadLen = len(bc.batchData.txsPayload) + } + + if bc.isBatchUpgraded(blockTimestamp) { + return uint64(existingBlockContextLen + len(bc.currentBlockContext) + existingTxPayloadLen + len(bc.currentTxsPayload)) + } + + return uint64(existingTxPayloadLen + len(bc.currentTxsPayload)) +} + +func progressPercent(current, total uint64) uint64 { + if total == 0 { + return 0 + } + p := current * 100 / total + if p > 100 { + return 100 + } + return p +} + +func maxUint64(values ...uint64) uint64 { + var max uint64 + for _, v := range values { + if v > max { + max = v + } + } + return max +} + func (bc *BatchCache) DeleteBatchStorageAndInitFromRollup() error { // should delete invalid batch data and batch header bytes err := bc.batchStorage.DeleteAllSealedBatches() diff --git a/common/batch/batch_cache_genesis_header_test.go b/common/batch/batch_cache_genesis_header_test.go new file mode 100644 index 000000000..2b984e8f3 --- /dev/null +++ b/common/batch/batch_cache_genesis_header_test.go @@ -0,0 +1,129 @@ +package batch + +import ( + "context" + "fmt" + "sync" + "testing" + "time" + + "github.com/morph-l2/go-ethereum/common/hexutil" + "github.com/morph-l2/go-ethereum/log" + "github.com/stretchr/testify/require" +) + +var ( + // Fill this with hex-encoded batch header bytes, e.g. "0x00....". + // This test will use it as the genesis parent header to initialize cache. + globalGenesisBatchHeaderHex = "0x00000000000000000000000000000000000000000000000000d81a073a4abd227068a2a334f4a41b3abba26144dc866a78ed28e2ae90f86f5a010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c4440140000000000000000000000000000000000000000000000000000000000000000290233e7a85533655c301d3e1043f03acd5427c73d1bbcbf8784db3f3974327f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + globalGenesisBatchHeader *BatchHeaderBytes + globalGenesisBatchHeaderErr error + globalGenesisBatchHeaderOnce sync.Once + + // Global overrides for cache batch config in tests (instead of updateBatchConfigFromGov). + globalBatchTimeoutForTest uint64 = 10000000 + globalBlockIntervalForTest uint64 = 10000 +) + +func ensureGlobalGenesisBatchHeader() error { + globalGenesisBatchHeaderOnce.Do(func() { + if globalGenesisBatchHeaderHex == "" { + globalGenesisBatchHeaderErr = fmt.Errorf("globalGenesisBatchHeaderHex is empty") + return + } + raw, err := hexutil.Decode(globalGenesisBatchHeaderHex) + if err != nil { + globalGenesisBatchHeaderErr = fmt.Errorf("decode globalGenesisBatchHeaderHex failed: %w", err) + return + } + header := BatchHeaderBytes(raw) + if err := header.validate(); err != nil { + globalGenesisBatchHeaderErr = fmt.Errorf("invalid global genesis batch header: %w", err) + return + } + globalGenesisBatchHeader = &header + }) + return globalGenesisBatchHeaderErr +} + +// initCacheWithGlobalGenesisHeader initializes cache base fields from the +// globally cached genesis batch header, instead of loading through Init(). +func initCacheWithGlobalGenesisHeader(cache *BatchCache) error { + if err := ensureGlobalGenesisBatchHeader(); err != nil { + return err + } + if globalGenesisBatchHeader == nil { + return ErrKeyNotFound + } + // Use global test knobs instead of querying gov config from chain. + cache.batchTimeOut = globalBatchTimeoutForTest + cache.blockInterval = globalBlockIntervalForTest + headerCopy := make(BatchHeaderBytes, len(*globalGenesisBatchHeader)) + copy(headerCopy, *globalGenesisBatchHeader) + cache.parentBatchHeader = &headerCopy + + prevStateRoot, err := cache.parentBatchHeader.PostStateRoot() + if err != nil { + return err + } + cache.prevStateRoot = prevStateRoot + + totalL1MessagePopped, err := cache.parentBatchHeader.TotalL1MessagePopped() + if err != nil { + return err + } + cache.totalL1MessagePopped = totalL1MessagePopped + + lastPackedBlockHeight, err := cache.parentBatchHeader.LastBlockNumber() + if err != nil { + lastPackedBlockHeight = 0 + } + cache.lastPackedBlockHeight = lastPackedBlockHeight + cache.currentBlockNumber = lastPackedBlockHeight + cache.initDone = true + + return nil +} + +func TestBatchCacheInitWithGlobalGenesisHeader(t *testing.T) { + testDB := openTestKV(t) + a := func(uint64) bool { return true } + cache := NewBatchCache(nil, a, 3, l1Client, &SingleL2Client{C: l2Client}, rollupContract, l2Gov, testDB) + + var batchCacheSyncMu sync.Mutex + done := make(chan error, 1) + go func() { + batchCacheSyncMu.Lock() + defer batchCacheSyncMu.Unlock() + for { + if err := initCacheWithGlobalGenesisHeader(cache); err != nil { + log.Error("init with global genesis header failed, wait for next try", "error", err) + time.Sleep(3 * time.Second) + continue + } + done <- nil + return + } + }() + + select { + case err := <-done: + require.NoError(t, err) + case <-time.After(20 * time.Second): + t.Fatal("timeout waiting for cache init with global genesis header") + } + + require.True(t, cache.initDone) + require.NotNil(t, cache.parentBatchHeader) + version, err := cache.parentBatchHeader.Version() + require.NoError(t, err) + require.Equal(t, uint8(BatchHeaderVersion0), version) + require.Equal(t, cache.lastPackedBlockHeight, cache.currentBlockNumber) + _, err = cache.l2Clients.BlockNumber(context.Background()) + require.NoError(t, err) + + batchCacheSyncMu.Lock() + err = cache.AssembleCurrentBatchHeader() + batchCacheSyncMu.Unlock() + require.NoError(t, err) +} diff --git a/tx-submitter/batch/batch_cache_test.go b/common/batch/batch_cache_test.go similarity index 54% rename from tx-submitter/batch/batch_cache_test.go rename to common/batch/batch_cache_test.go index a15977295..3965fa4aa 100644 --- a/tx-submitter/batch/batch_cache_test.go +++ b/common/batch/batch_cache_test.go @@ -3,16 +3,11 @@ package batch import ( "os" "os/signal" - "path/filepath" "sync" "testing" "time" "morph-l2/bindings/bindings" - "morph-l2/tx-submitter/db" - "morph-l2/tx-submitter/iface" - "morph-l2/tx-submitter/types" - "morph-l2/tx-submitter/utils" "github.com/morph-l2/go-ethereum/log" "github.com/stretchr/testify/require" @@ -24,28 +19,15 @@ func init() { if err != nil { panic(err) } - l2Caller, err = types.NewL2Caller([]iface.L2Client{l2Client}) + l2Gov, err = NewL2Gov(l2Client) if err != nil { panic(err) } } -// setupTestDB creates a temporary database for testing -func setupTestDB(t *testing.T) *db.Db { - testDir := filepath.Join(t.TempDir(), "testleveldb") - os.RemoveAll(testDir) - t.Cleanup(func() { - os.RemoveAll(testDir) - }) - - testDB, err := db.New(testDir) - require.NoError(t, err) - return testDB -} - func TestBatchCacheInitServer(t *testing.T) { - testDB := setupTestDB(t) - cache := NewBatchCache(nil, l1Client, []iface.L2Client{l2Client}, rollupContract, l2Caller, testDB) + testDB := openTestKV(t) + cache := NewBatchCache(nil, nil, 2, l1Client, &SingleL2Client{C: l2Client}, rollupContract, l2Gov, testDB) var batchCacheSyncMu sync.Mutex @@ -62,7 +44,7 @@ func TestBatchCacheInitServer(t *testing.T) { } }() - go utils.Loop(cache.ctx, 5*time.Second, func() { + go testLoop(cache.ctx, 5*time.Second, func() { batchCacheSyncMu.Lock() defer batchCacheSyncMu.Unlock() err := cache.AssembleCurrentBatchHeader() @@ -71,24 +53,21 @@ func TestBatchCacheInitServer(t *testing.T) { } }) - // Catch CTRL-C to ensure a graceful shutdown. interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt) - - // Wait until the interrupt signal is received from an OS signal. <-interrupt } func TestBatchCacheInit(t *testing.T) { - testDB := setupTestDB(t) - cache := NewBatchCache(nil, l1Client, []iface.L2Client{l2Client}, rollupContract, l2Caller, testDB) + testDB := openTestKV(t) + cache := NewBatchCache(nil, nil, 2, l1Client, &SingleL2Client{C: l2Client}, rollupContract, l2Gov, testDB) err := cache.InitAndSyncFromRollup() require.NoError(t, err) } func TestBatchCacheInitByBlockRange(t *testing.T) { - testDB := setupTestDB(t) - cache := NewBatchCache(nil, l1Client, []iface.L2Client{l2Client}, rollupContract, l2Caller, testDB) + testDB := openTestKV(t) + cache := NewBatchCache(nil, nil, 2, l1Client, &SingleL2Client{C: l2Client}, rollupContract, l2Gov, testDB) err := cache.InitFromRollupByRange() require.NoError(t, err) } diff --git a/tx-submitter/batch/batch_data.go b/common/batch/batch_data.go similarity index 86% rename from tx-submitter/batch/batch_data.go rename to common/batch/batch_data.go index b28e2c65f..d5ac89624 100644 --- a/tx-submitter/batch/batch_data.go +++ b/common/batch/batch_data.go @@ -4,15 +4,10 @@ import ( "encoding/binary" "fmt" - "morph-l2/node/zstd" - "morph-l2/tx-submitter/types" - "github.com/morph-l2/go-ethereum/common" "github.com/morph-l2/go-ethereum/crypto" -) -var ( - EmptyVersionedHash = common.HexToHash("0x010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014") + "morph-l2/common/blob" ) type BatchData struct { @@ -95,7 +90,7 @@ func (cks *BatchData) DataHashV2() (common.Hash, error) { lastBlockContext := cks.blockContexts[len(cks.blockContexts)-60:] // Parse block height - height, err := types.HeightFromBlockContextBytes(lastBlockContext) + height, err := HeightFromBlockContextBytes(lastBlockContext) if err != nil { return common.Hash{}, fmt.Errorf("failed to parse blockContext: context length=%d, lastBlockContext=%x, err=%w", len(cks.blockContexts), lastBlockContext, err) @@ -108,8 +103,8 @@ func (cks *BatchData) DataHashV2() (common.Hash, error) { func (cks *BatchData) calculateHash(height uint64) common.Hash { // Preallocate memory for efficiency hashData := make([]byte, 8+2+len(cks.l1TxHashes)) // 8 bytes for height, 2 bytes for l1TxNum - copy(hashData[:8], types.Uint64ToBigEndianBytes(height)) - copy(hashData[8:10], types.Uint16ToBigEndianBytes(cks.l1TxNum)) + copy(hashData[:8], Uint64ToBigEndianBytes(height)) + copy(hashData[8:10], Uint16ToBigEndianBytes(cks.l1TxNum)) copy(hashData[10:], cks.l1TxHashes) return crypto.Keccak256Hash(hashData) @@ -126,16 +121,17 @@ func (cks *BatchData) TxsPayloadV2() []byte { func (cks *BatchData) BlockNum() uint16 { return cks.blockNum } -func (cks *BatchData) EstimateCompressedSizeWithNewPayload(txPayload []byte) (bool, error) { +func (cks *BatchData) EstimateCompressedSizeWithNewPayload(txPayload []byte, maxBlobCount int) (bool, error) { + limit := maxBlobCount * blob.MaxBlobBytesSize blobBytes := append(cks.txsPayload, txPayload...) - if len(blobBytes) <= MaxBlobBytesSize { + if len(blobBytes) <= limit { return false, nil } - compressed, err := zstd.CompressBatchBytes(blobBytes) + compressed, err := blob.CompressBatchBytes(blobBytes) if err != nil { return false, err } - return len(compressed) > MaxBlobBytesSize, nil + return len(compressed) > limit, nil } func (cks *BatchData) combinePayloads(newBlockContext, newTxPayload []byte) []byte { @@ -150,15 +146,16 @@ func (cks *BatchData) combinePayloads(newBlockContext, newTxPayload []byte) []by // WillExceedCompressedSizeLimit checks if the size of the combined block contexts // and transaction payloads (after compression) exceeds the maximum allowed size. -func (cks *BatchData) WillExceedCompressedSizeLimit(newBlockContext, newTxPayload []byte) (bool, error) { +func (cks *BatchData) WillExceedCompressedSizeLimit(newBlockContext, newTxPayload []byte, maxBlobCount int) (bool, error) { + limit := maxBlobCount * blob.MaxBlobBytesSize // Combine the existing and new block contexts and transaction payloads combinedBytes := cks.combinePayloads(newBlockContext, newTxPayload) - if len(combinedBytes) <= MaxBlobBytesSize { + if len(combinedBytes) <= limit { return false, nil } - compressed, err := zstd.CompressBatchBytes(combinedBytes) + compressed, err := blob.CompressBatchBytes(combinedBytes) if err != nil { return false, fmt.Errorf("compression failed: %w", err) } - return len(compressed) > MaxBlobBytesSize, nil + return len(compressed) > limit, nil } diff --git a/tx-submitter/batch/batch_header.go b/common/batch/batch_header.go similarity index 75% rename from tx-submitter/batch/batch_header.go rename to common/batch/batch_header.go index 81d38c691..71faaf9fd 100644 --- a/tx-submitter/batch/batch_header.go +++ b/common/batch/batch_header.go @@ -16,9 +16,15 @@ type ( const ( expectedLengthV0 = 249 expectedLengthV1 = 257 + // V2 reuses the V1 wire format (257 bytes). The only semantic + // difference is that the 32-byte field at offset 57 stores + // keccak256(blobhash(0) || ... || blobhash(N-1)) instead of a + // single blob versioned hash. + expectedLengthV2 = 257 BatchHeaderVersion0 = 0 BatchHeaderVersion1 = 1 + BatchHeaderVersion2 = 2 ) var ( @@ -42,6 +48,10 @@ func (b BatchHeaderBytes) validate() error { if len(b) != expectedLengthV1 { return ErrInvalidBatchHeaderLength } + case BatchHeaderVersion2: + if len(b) != expectedLengthV2 { + return ErrInvalidBatchHeaderLength + } default: return ErrInvalidBatchHeaderVersion } @@ -94,13 +104,48 @@ func (b BatchHeaderBytes) DataHash() (common.Hash, error) { return common.BytesToHash(b[25:57]), nil } +// BlobVersionedHash returns the EIP-4844 blob versioned hash recorded at +// offset [57:89]. This is only meaningful for V0/V1 batches, where the field +// holds the single blob's versioned hash. For V2 batches the same offset +// holds an aggregated hash; callers must use BlobHashesHash instead. func (b BatchHeaderBytes) BlobVersionedHash() (common.Hash, error) { if err := b.validate(); err != nil { return common.Hash{}, err } + version, _ := b.Version() + if version >= BatchHeaderVersion2 { + return common.Hash{}, errors.New("BlobVersionedHash is not available for V2+; use BlobHashesHash") + } return common.BytesToHash(b[57:89]), nil } +// BlobHashesHash returns the aggregated blob hash recorded at offset [57:89] +// for V2+ batches, defined as keccak256(blobhash(0) || ... || blobhash(N-1)). +// V0/V1 batches do not aggregate and will return an error. +func (b BatchHeaderBytes) BlobHashesHash() (common.Hash, error) { + if err := b.validate(); err != nil { + return common.Hash{}, err + } + version, _ := b.Version() + if version < BatchHeaderVersion2 { + return common.Hash{}, errors.New("BlobHashesHash is only available for V2+; use BlobVersionedHash") + } + return common.BytesToHash(b[57:89]), nil +} + +// BlobCommitHash returns the blob-related 32-byte field at offset [57:89]: +// V0/V1 use BlobVersionedHash; V2+ use BlobHashesHash (same wire offset, different semantics). +func (b BatchHeaderBytes) BlobCommitHash() (common.Hash, error) { + version, err := b.Version() + if err != nil { + return common.Hash{}, err + } + if version >= BatchHeaderVersion2 { + return b.BlobHashesHash() + } + return b.BlobVersionedHash() +} + func (b BatchHeaderBytes) PrevStateRoot() (common.Hash, error) { if err := b.validate(); err != nil { return common.Hash{}, err diff --git a/common/batch/batch_header_test.go b/common/batch/batch_header_test.go new file mode 100644 index 000000000..7c3ee046a --- /dev/null +++ b/common/batch/batch_header_test.go @@ -0,0 +1,88 @@ +package batch + +import ( + "math/big" + "testing" + + "github.com/morph-l2/go-ethereum/common" + "github.com/stretchr/testify/require" + + "morph-l2/common/blob" +) + +// TestBatchHeaderV2 exercises the V2 header variant: it reuses the V1 wire +// layout (257 bytes) but the 32-byte field at offset 57 carries an aggregated +// blob hash (keccak256(blobhash(0)||...||blobhash(N-1))) rather than a single +// versioned hash. Parsing helpers must route callers accordingly. +func TestBatchHeaderV2(t *testing.T) { + aggregated := common.BigToHash(big.NewInt(0xABCDEF)) + + // Start from a V1 encoding (identical byte layout), then flip the version + // byte to V2. This matches the on-chain behavior where a V2 header is + // produced by tx-submitter with the aggregated hash stored at offset 57. + raw := BatchHeaderV1{ + BatchHeaderV0: BatchHeaderV0{ + BatchIndex: 42, + L1MessagePopped: 1, + TotalL1MessagePopped: 3, + DataHash: common.BigToHash(big.NewInt(0x11)), + BlobVersionedHash: aggregated, + PrevStateRoot: common.BigToHash(big.NewInt(0x22)), + PostStateRoot: common.BigToHash(big.NewInt(0x33)), + WithdrawalRoot: common.BigToHash(big.NewInt(0x44)), + SequencerSetVerifyHash: common.BigToHash(big.NewInt(0x55)), + ParentBatchHash: common.BigToHash(big.NewInt(0x66)), + }, + LastBlockNumber: 9_876, + }.Bytes() + raw[0] = BatchHeaderVersion2 + + version, err := raw.Version() + require.NoError(t, err) + require.EqualValues(t, BatchHeaderVersion2, version) + + batchIndex, err := raw.BatchIndex() + require.NoError(t, err) + require.EqualValues(t, 42, batchIndex) + + lastBlockNumber, err := raw.LastBlockNumber() + require.NoError(t, err) + require.EqualValues(t, 9_876, lastBlockNumber) + + // V2 headers must route callers to BlobHashesHash; the legacy accessor + // intentionally errors to prevent silent mis-use. + _, err = raw.BlobVersionedHash() + require.Error(t, err) + + aggHash, err := raw.BlobHashesHash() + require.NoError(t, err) + require.EqualValues(t, aggregated, aggHash) + + // Length check: a V2 header with the wrong length must fail validate(). + short := make(BatchHeaderBytes, expectedLengthV2-1) + short[0] = BatchHeaderVersion2 + _, err = short.BatchIndex() + require.ErrorIs(t, err, ErrInvalidBatchHeaderLength) +} + +// TestBlobHashesHashUnavailableForLegacy guards the inverse direction: V0 and +// V1 headers must reject BlobHashesHash so that callers reach for the correct +// accessor. +func TestBlobHashesHashUnavailableForLegacy(t *testing.T) { + v0 := BatchHeaderV0{ + BatchIndex: 1, + BlobVersionedHash: blob.EmptyVersionedHash, + }.Bytes() + _, err := v0.BlobHashesHash() + require.Error(t, err) + + v1 := BatchHeaderV1{ + BatchHeaderV0: BatchHeaderV0{ + BatchIndex: 2, + BlobVersionedHash: blob.EmptyVersionedHash, + }, + LastBlockNumber: 10, + }.Bytes() + _, err = v1.BlobHashesHash() + require.Error(t, err) +} diff --git a/tx-submitter/batch/batch_query.go b/common/batch/batch_query.go similarity index 100% rename from tx-submitter/batch/batch_query.go rename to common/batch/batch_query.go diff --git a/tx-submitter/batch/batch_restart_test.go b/common/batch/batch_restart_test.go similarity index 94% rename from tx-submitter/batch/batch_restart_test.go rename to common/batch/batch_restart_test.go index f4db2f47f..87cdf1393 100644 --- a/tx-submitter/batch/batch_restart_test.go +++ b/common/batch/batch_restart_test.go @@ -7,14 +7,9 @@ import ( "errors" "fmt" "math/big" - "os" - "path/filepath" "testing" "morph-l2/bindings/bindings" - "morph-l2/tx-submitter/db" - "morph-l2/tx-submitter/iface" - "morph-l2/tx-submitter/types" "github.com/morph-l2/go-ethereum/accounts/abi/bind" "github.com/morph-l2/go-ethereum/common" @@ -37,7 +32,7 @@ var ( rollupContract *bindings.Rollup - l2Caller *types.L2Caller + l2Gov *L2Gov ) func init() { @@ -46,22 +41,16 @@ func init() { if err != nil { panic(err) } - l2Caller, err = types.NewL2Caller([]iface.L2Client{l2Client}) + l2Gov, err = NewL2Gov(l2Client) if err != nil { panic(err) } } func Test_GetFinalizeBatchHeader(t *testing.T) { - testDir := filepath.Join(t.TempDir(), "testleveldb") - os.RemoveAll(testDir) - t.Cleanup(func() { - os.RemoveAll(testDir) - }) - testDB, err := db.New(testDir) - require.NoError(t, err) + testDB := openTestKV(t) - bc := NewBatchCache(nil, l1Client, []iface.L2Client{l2Client}, rollupContract, l2Caller, testDB) + bc := NewBatchCache(nil, nil, 2, l1Client, &SingleL2Client{C: l2Client}, rollupContract, l2Gov, testDB) headerBytes, err := bc.getLastFinalizeBatchHeaderFromRollupByIndex(0) require.NoError(t, err) t.Log("headerBytes", hex.EncodeToString(headerBytes.Bytes())) @@ -82,20 +71,14 @@ func Test_CommitBatchParse(t *testing.T) { } func TestBatchRestartInit(t *testing.T) { - testDir := filepath.Join(t.TempDir(), "testleveldb") - os.RemoveAll(testDir) - t.Cleanup(func() { - os.RemoveAll(testDir) - }) - testDB, err := db.New(testDir) - require.NoError(t, err) + testDB := openTestKV(t) - sequencerSetBytes, sequencerSetVerifyHash, err := l2Caller.GetSequencerSetBytes(nil) + sequencerSetBytes, sequencerSetVerifyHash, err := l2Gov.GetSequencerSetBytes(nil) require.NoError(t, err) t.Log("sequencer set verify hash", hex.EncodeToString(sequencerSetVerifyHash[:])) ci, fi := getInfosFromContract() t.Log("commit index", ci, " ", "finalize index", fi) - bc := NewBatchCache(nil, l1Client, []iface.L2Client{l2Client}, rollupContract, l2Caller, testDB) + bc := NewBatchCache(nil, nil, 2, l1Client, &SingleL2Client{C: l2Client}, rollupContract, l2Gov, testDB) startBlockNum, endBlockNum, err := getFirstUnFinalizeBatchBlockNumRange(fi) require.NoError(t, err) startBlockNum = new(big.Int).Add(startBlockNum, new(big.Int).SetUint64(1)) @@ -127,7 +110,7 @@ func TestBatchRestartInit(t *testing.T) { t.Logf("First unfinalize batch index: %d, block range: %d - %d", firstUnfinalizedIndex, startBlockNum.Uint64(), endBlockNum.Uint64()) // Fetch blocks from L2 client in this range and assemble batchHeader - assembledBatchHeader, err := assembleBatchHeaderFromL2Blocks(bc, startBlockNum.Uint64(), endBlockNum.Uint64(), sequencerSetBytes, l2Client, l2Caller) + assembledBatchHeader, err := assembleBatchHeaderFromL2Blocks(bc, startBlockNum.Uint64(), endBlockNum.Uint64(), sequencerSetBytes, l2Client, l2Gov) require.NoError(t, err, "failed to assemble batch header from L2 blocks") t.Log("assembled batch header success", hex.EncodeToString(assembledBatchHeader.Bytes())) // Verify the assembled batchHeader @@ -458,14 +441,14 @@ func assembleBatchHeaderFromL2Blocks( bc *BatchCache, startBlockNum, endBlockNum uint64, sequencerBytes []byte, - l2Client iface.L2Client, - l2Caller *types.L2Caller, + l2Client *ethclient.Client, + l2Gov L2GovCaller, ) (*BatchHeaderBytes, error) { ctx := context.Background() // Fetch blocks from L2 client in the specified range and accumulate to batch for blockNum := startBlockNum; blockNum <= endBlockNum; blockNum++ { - root, err := l2Caller.GetTreeRoot(&bind.CallOpts{ + root, err := l2Gov.GetTreeRoot(&bind.CallOpts{ Context: ctx, BlockNumber: new(big.Int).SetUint64(blockNum), }) @@ -495,7 +478,7 @@ func assembleBatchHeaderFromL2Blocks( blockTimestamp := lastBlock.Time() // Seal batch and generate batchHeader - batchIndex, batchHeaderBytes, _, err := bc.SealBatch(sequencerBytes, blockTimestamp) + batchIndex, batchHeaderBytes, _, err := bc.SealBatch(sequencerBytes, blockTimestamp, nil) if err != nil { return nil, fmt.Errorf("failed to seal batch: %w", err) } diff --git a/tx-submitter/batch/batch_storage.go b/common/batch/batch_storage.go similarity index 96% rename from tx-submitter/batch/batch_storage.go rename to common/batch/batch_storage.go index 1f7c1e0f7..a681bbee8 100644 --- a/tx-submitter/batch/batch_storage.go +++ b/common/batch/batch_storage.go @@ -8,10 +8,9 @@ import ( "fmt" "sync" - "morph-l2/tx-submitter/db" - "github.com/morph-l2/go-ethereum/eth" "github.com/morph-l2/go-ethereum/log" + ldberrors "github.com/syndtr/goleveldb/leveldb/errors" ) const ( @@ -23,12 +22,12 @@ const ( // BatchStorage handles persistence of sealed batches using JSON encoding type BatchStorage struct { - db db.Database + db SealedBatchKV mu sync.RWMutex } // NewBatchStorage creates a new BatchStorage instance -func NewBatchStorage(db db.Database) *BatchStorage { +func NewBatchStorage(db SealedBatchKV) *BatchStorage { return &BatchStorage{ db: db, } @@ -69,7 +68,7 @@ func (s *BatchStorage) LoadSealedBatch(batchIndex uint64) (*eth.RPCRollupBatch, key := encodeBatchKey(batchIndex) encoded, err := s.db.GetBytes(key) if err != nil { - if errors.Is(err, db.ErrKeyNotFound) { + if isKVNotFound(err) { return nil, fmt.Errorf("sealed batch %d not found", batchIndex) } return nil, fmt.Errorf("failed to get sealed batch %d: %w", batchIndex, err) @@ -92,7 +91,7 @@ func (s *BatchStorage) LoadAllSealedBatches() (map[uint64]*eth.RPCRollupBatch, [ indices, err := s.loadBatchIndices() s.mu.RUnlock() if err != nil { - if errors.Is(err, db.ErrKeyNotFound) { + if isKVNotFound(err) { // No batches stored yet return make(map[uint64]*eth.RPCRollupBatch), nil, nil } @@ -121,7 +120,7 @@ func (s *BatchStorage) LoadAllSealedBatchesAndHeader() (map[uint64]*eth.RPCRollu indices, err := s.loadBatchIndices() s.mu.RUnlock() if err != nil { - if errors.Is(err, db.ErrKeyNotFound) { + if isKVNotFound(err) { // No batches stored yet return make(map[uint64]*eth.RPCRollupBatch), make(map[uint64]*BatchHeaderBytes), nil, nil } @@ -206,7 +205,7 @@ func (s *BatchStorage) DeleteAllSealedBatches() error { indices, err := s.loadBatchIndices() s.mu.RUnlock() if err != nil { - if errors.Is(err, db.ErrKeyNotFound) { + if isKVNotFound(err) { // No batches stored yet return nil } @@ -244,7 +243,7 @@ func encodeBatchKey(batchIndex uint64) []byte { func (s *BatchStorage) updateBatchIndices(batchIndex uint64, add bool) error { indices, err := s.loadBatchIndices() if err != nil { - if errors.Is(err, db.ErrKeyNotFound) { + if isKVNotFound(err) { indices = []uint64{} } else { return err @@ -324,7 +323,7 @@ func (s *BatchStorage) LoadSealedBatchHeader(batchIndex uint64) (*BatchHeaderByt key := encodeBatchHeaderKey(batchIndex) headerBytes, err := s.db.GetBytes(key) if err != nil { - if errors.Is(err, db.ErrKeyNotFound) { + if isKVNotFound(err) { return nil, fmt.Errorf("sealed batch header %d not found", batchIndex) } return nil, fmt.Errorf("failed to get sealed batch header %d: %w", batchIndex, err) @@ -342,7 +341,7 @@ func (s *BatchStorage) LoadAllSealedBatchHeaders() (map[uint64]*BatchHeaderBytes indices, err := s.loadBatchIndices() s.mu.RUnlock() if err != nil { - if errors.Is(err, db.ErrKeyNotFound) { + if isKVNotFound(err) { // No batches stored yet return make(map[uint64]*BatchHeaderBytes), nil } @@ -384,3 +383,7 @@ func encodeBatchHeaderKey(batchIndex uint64) []byte { binary.BigEndian.PutUint64(key[len(SealedBatchHeaderKeyPrefix):], batchIndex) return key } + +func isKVNotFound(err error) bool { + return errors.Is(err, ErrKeyNotFound) || errors.Is(err, ldberrors.ErrNotFound) +} diff --git a/node/types/blob.go b/common/batch/blob.go similarity index 63% rename from node/types/blob.go rename to common/batch/blob.go index 49b158bc1..088e55a6f 100644 --- a/node/types/blob.go +++ b/common/batch/blob.go @@ -1,4 +1,4 @@ -package types +package batch import ( "bytes" @@ -6,6 +6,8 @@ import ( "fmt" "io" + "morph-l2/node/zstd" + eth "github.com/morph-l2/go-ethereum/core/types" "github.com/morph-l2/go-ethereum/crypto/kzg4844" "github.com/morph-l2/go-ethereum/rlp" @@ -13,6 +15,32 @@ import ( const MaxBlobBytesSize = 4096 * 31 +var ( + emptyBlob = new(kzg4844.Blob) + emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob) + emptyBlobProof, _ = kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit) +) + +// MakeBlobCanonical converts the raw blob data into the canonical blob representation of 4096 BLSFieldElements. +func MakeBlobCanonical(blobBytes []byte) (b *kzg4844.Blob, err error) { + if len(blobBytes) > MaxBlobBytesSize { + return nil, fmt.Errorf("data is too large for blob. len=%v", len(blobBytes)) + } + offset := 0 + b = new(kzg4844.Blob) + // encode (up to) 31 bytes of remaining input data at a time into the subsequent field element + for i := 0; i < 4096; i++ { + offset += copy(b[i*32+1:i*32+32], blobBytes[offset:]) + if offset == len(blobBytes) { + break + } + } + if offset < len(blobBytes) { + return nil, fmt.Errorf("failed to fit all data into blob. bytes remaining: %v", len(blobBytes)-offset) + } + return +} + func RetrieveBlobBytes(blob *kzg4844.Blob) ([]byte, error) { data := make([]byte, MaxBlobBytesSize) for i := 0; i < 4096; i++ { @@ -24,6 +52,67 @@ func RetrieveBlobBytes(blob *kzg4844.Blob) ([]byte, error) { return data, nil } +func makeBlobCommitment(bz []byte) (b kzg4844.Blob, c kzg4844.Commitment, err error) { + blob, err := MakeBlobCanonical(bz) + if err != nil { + return + } + b = *blob + c, err = kzg4844.BlobToCommitment(&b) + if err != nil { + return + } + return +} + +func MakeBlobTxSidecar(blobBytes []byte, maxBlobs int) (*eth.BlobTxSidecar, error) { + if len(blobBytes) == 0 { + return ð.BlobTxSidecar{ + Blobs: []kzg4844.Blob{*emptyBlob}, + Commitments: []kzg4844.Commitment{emptyBlobCommit}, + Proofs: []kzg4844.Proof{emptyBlobProof}, + }, nil + } + if maxBlobs <= 0 { + maxBlobs = 1 + } + if len(blobBytes) > maxBlobs*MaxBlobBytesSize { + return nil, fmt.Errorf("data size %d exceeds %d blobs capacity (%d bytes)", len(blobBytes), maxBlobs, maxBlobs*MaxBlobBytesSize) + } + blobCount := (len(blobBytes) + MaxBlobBytesSize - 1) / MaxBlobBytesSize + var ( + err error + blobs = make([]kzg4844.Blob, blobCount) + commitments = make([]kzg4844.Commitment, blobCount) + ) + for i := 0; i < blobCount; i++ { + start := i * MaxBlobBytesSize + end := start + MaxBlobBytesSize + if end > len(blobBytes) { + end = len(blobBytes) + } + blobs[i], commitments[i], err = makeBlobCommitment(blobBytes[start:end]) + if err != nil { + return nil, err + } + } + return ð.BlobTxSidecar{ + Blobs: blobs, + Commitments: commitments, + }, nil +} + +func CompressBatchBytes(batchBytes []byte) ([]byte, error) { + if len(batchBytes) == 0 { + return nil, nil + } + compressedBatchBytes, err := zstd.CompressBatchBytes(batchBytes) + if err != nil { + return nil, fmt.Errorf("failed to compress batch bytes, err: %w", err) + } + return compressedBatchBytes, nil +} + func DecodeTxsFromBytes(txsBytes []byte) (eth.Transactions, error) { reader := bytes.NewReader(txsBytes) txs := make(eth.Transactions, 0) diff --git a/tx-submitter/batch/commit_test.go b/common/batch/commit_test.go similarity index 81% rename from tx-submitter/batch/commit_test.go rename to common/batch/commit_test.go index 2acb26d37..c704b885f 100644 --- a/tx-submitter/batch/commit_test.go +++ b/common/batch/commit_test.go @@ -3,18 +3,14 @@ package batch import ( "context" "crypto/ecdsa" + "errors" "fmt" "math/big" - "os" - "path/filepath" "testing" "time" "morph-l2/bindings/bindings" - "morph-l2/tx-submitter/db" - "morph-l2/tx-submitter/iface" - "morph-l2/tx-submitter/types" - "morph-l2/tx-submitter/utils" + "morph-l2/common/blob" "github.com/holiman/uint256" "github.com/morph-l2/go-ethereum/common" @@ -27,19 +23,19 @@ import ( "github.com/stretchr/testify/require" ) -var pk = "" +var ( + pk = "" + errExceedFeeLimit = errors.New("exceed fee limit") +) func TestRollupWithProof(t *testing.T) { - testDir := filepath.Join(t.TempDir(), "testleveldb") - os.RemoveAll(testDir) - t.Cleanup(func() { - os.RemoveAll(testDir) - }) - testDB, err := db.New(testDir) - require.NoError(t, err) + if pk == "" { + t.Skip("pk is unset; provide a hex private key to run TestRollupWithProof") + } + testDB := openTestKV(t) - cache := NewBatchCache(nil, l1Client, []iface.L2Client{l2Client}, rollupContract, l2Caller, testDB) - err = cache.InitFromRollupByRange() + cache := NewBatchCache(nil, nil, 2, l1Client, &SingleL2Client{C: l2Client}, rollupContract, l2Gov, testDB) + err := cache.InitFromRollupByRange() require.NoError(t, err) privateKey, err := crypto.HexToECDSA(pk[2:]) @@ -90,7 +86,6 @@ func TestRollupWithProof(t *testing.T) { require.NoError(t, err) t.Log("receipt status", receipt.Status) t.Log("receipt", receipt) - } func sign(tx *ethtypes.Transaction, signer ethtypes.Signer, prv *ecdsa.PrivateKey) (*ethtypes.Transaction, error) { @@ -102,7 +97,7 @@ func sign(tx *ethtypes.Transaction, signer ethtypes.Signer, prv *ecdsa.PrivateKe } func createBlobTx(l1client *ethclient.Client, batch *eth.RPCRollupBatch, nonce, gas uint64, tip, gasFeeCap, blobFee *big.Int, calldata []byte, head *ethtypes.Header) (*ethtypes.Transaction, error) { - versionedHashes := types.BlobHashes(batch.Sidecar.Blobs, batch.Sidecar.Commitments) + versionedHashes := blob.BlobHashes(batch.Sidecar.Blobs, batch.Sidecar.Commitments) sidecar := ðtypes.BlobTxSidecar{ Blobs: batch.Sidecar.Blobs, Commitments: batch.Sidecar.Commitments, @@ -111,17 +106,17 @@ func createBlobTx(l1client *ethclient.Client, batch *eth.RPCRollupBatch, nonce, if err != nil { return nil, err } - switch types.DetermineBlobVersion(head, chainID.Uint64()) { + switch blob.DetermineBlobVersion(head, chainID.Uint64()) { case ethtypes.BlobSidecarVersion0: sidecar.Version = ethtypes.BlobSidecarVersion0 - proof, err := types.MakeBlobProof(sidecar.Blobs, sidecar.Commitments) + proof, err := blob.MakeBlobProof(sidecar.Blobs, sidecar.Commitments) if err != nil { return nil, fmt.Errorf("gen blob proof failed %v", err) } sidecar.Proofs = proof case ethtypes.BlobSidecarVersion1: sidecar.Version = ethtypes.BlobSidecarVersion1 - proof, err := types.MakeCellProof(sidecar.Blobs) + proof, err := blob.MakeCellProof(sidecar.Blobs) if err != nil { return nil, fmt.Errorf("gen cell proof failed %v", err) } @@ -172,7 +167,6 @@ func getGasTipAndCap(l1client *ethclient.Client) (*big.Int, *big.Int, *big.Int, gasFeeCap = new(big.Int).Set(tip) } - // calc blob fee cap var blobFee *big.Int if head.ExcessBlobGas != nil { id, err := l1client.ChainID(context.Background()) @@ -180,13 +174,12 @@ func getGasTipAndCap(l1client *ethclient.Client) (*big.Int, *big.Int, *big.Int, return nil, nil, nil, nil, err } log.Info("market blob fee info", "excess blob gas", *head.ExcessBlobGas) - blobConfig, exist := types.ChainConfigMap[id.Uint64()] + blobConfig, exist := blob.ChainConfigMap[id.Uint64()] if !exist { - blobConfig = types.DefaultBlobConfig + blobConfig = blob.DefaultBlobConfig } - blobFeeDenominator := types.GetBlobFeeDenominator(blobConfig, head.Time) + blobFeeDenominator := blob.GetBlobFeeDenominator(blobConfig, head.Time) blobFee = eip4844.CalcBlobFee(*head.ExcessBlobGas, blobFeeDenominator.Uint64()) - // Set to 3x to handle blob market congestion blobFee = new(big.Int).Mul(blobFee, big.NewInt(3)) } @@ -202,26 +195,22 @@ func buildSigInput(batch *eth.RPCRollupBatch) (*bindings.IRollupBatchSignatureIn return sigData, nil } -// send tx to l1 with business logic check -func sendTx(client iface.Client, txFeeLimit uint64, tx *ethtypes.Transaction) error { - // fee limit +func sendTx(client *ethclient.Client, txFeeLimit uint64, tx *ethtypes.Transaction) error { if txFeeLimit > 0 { var fee uint64 - // calc tx gas fee if tx.Type() == ethtypes.BlobTxType { blobFee := new(big.Int).Mul(tx.BlobGasFeeCap(), new(big.Int).SetUint64(tx.BlobGas())) txFee := new(big.Int).Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas())) totalFee := new(big.Int).Add(blobFee, txFee) if !totalFee.IsUint64() || totalFee.Uint64() > txFeeLimit { - return fmt.Errorf("%v:limit=%v,but got=%v", utils.ErrExceedFeeLimit, txFeeLimit, totalFee) + return fmt.Errorf("%v:limit=%v,but got=%v", errExceedFeeLimit, txFeeLimit, totalFee) } return client.SendTransaction(context.Background(), tx) - } else { - fee = tx.GasPrice().Uint64() * tx.Gas() } + fee = tx.GasPrice().Uint64() * tx.Gas() if fee > txFeeLimit { - return fmt.Errorf("%v:limit=%v,but got=%v", utils.ErrExceedFeeLimit, txFeeLimit, fee) + return fmt.Errorf("%v:limit=%v,but got=%v", errExceedFeeLimit, txFeeLimit, fee) } } diff --git a/common/batch/encoding.go b/common/batch/encoding.go new file mode 100644 index 000000000..a2ba1fc43 --- /dev/null +++ b/common/batch/encoding.go @@ -0,0 +1,25 @@ +package batch + +import ( + "encoding/binary" + "fmt" +) + +func Uint64ToBigEndianBytes(value uint64) []byte { + valueBytes := make([]byte, 8) + binary.BigEndian.PutUint64(valueBytes, value) + return valueBytes +} + +func Uint16ToBigEndianBytes(value uint16) []byte { + valueBytes := make([]byte, 2) + binary.BigEndian.PutUint16(valueBytes, value) + return valueBytes +} + +func HeightFromBlockContextBytes(blockContextBytes []byte) (uint64, error) { + if len(blockContextBytes) != 60 { + return 0, fmt.Errorf("wrong block context bytes length, input: %x", blockContextBytes) + } + return binary.BigEndian.Uint64(blockContextBytes[:8]), nil +} diff --git a/common/batch/helpers_test.go b/common/batch/helpers_test.go new file mode 100644 index 000000000..7a493dba3 --- /dev/null +++ b/common/batch/helpers_test.go @@ -0,0 +1,57 @@ +package batch + +import ( + "context" + "fmt" + "os" + "path/filepath" + "testing" + "time" + + "github.com/stretchr/testify/require" + "github.com/syndtr/goleveldb/leveldb" + ldberrors "github.com/syndtr/goleveldb/leveldb/errors" +) + +type testLevelDB struct { + db *leveldb.DB +} + +func openTestKV(t *testing.T) SealedBatchKV { + t.Helper() + dir := filepath.Join(t.TempDir(), "ldb") + _ = os.RemoveAll(dir) + db, err := leveldb.OpenFile(dir, nil) + require.NoError(t, err) + t.Cleanup(func() { _ = db.Close() }) + return &testLevelDB{db: db} +} + +func (d *testLevelDB) GetBytes(key []byte) ([]byte, error) { + v, err := d.db.Get(key, nil) + if err == ldberrors.ErrNotFound { + return nil, fmt.Errorf("%w", ErrKeyNotFound) + } + return v, err +} + +func (d *testLevelDB) PutBytes(key, val []byte) error { + return d.db.Put(key, val, nil) +} + +func (d *testLevelDB) Delete(key []byte) error { + return d.db.Delete(key, nil) +} + +func testLoop(ctx context.Context, d time.Duration, fn func()) { + ticker := time.NewTicker(d) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + fn() + } + } +} diff --git a/common/batch/interfaces.go b/common/batch/interfaces.go new file mode 100644 index 000000000..3051383b1 --- /dev/null +++ b/common/batch/interfaces.go @@ -0,0 +1,76 @@ +package batch + +import ( + "context" + "errors" + "math/big" + + "morph-l2/bindings/bindings" + + "github.com/morph-l2/go-ethereum/accounts/abi/bind" + "github.com/morph-l2/go-ethereum/common" + ethtypes "github.com/morph-l2/go-ethereum/core/types" +) + +// ErrKeyNotFound is returned by SealedBatchKV implementations when a key is absent. +var ErrKeyNotFound = errors.New("batch storage: key not found") + +// SealedBatchKV is a minimal key-value store used by BatchStorage. +type SealedBatchKV interface { + GetBytes(key []byte) ([]byte, error) + PutBytes(key, val []byte) error + Delete(key []byte) error +} + +// L1HeaderClient is the L1 RPC surface required to recover batch headers from events. +type L1HeaderClient interface { + BlockNumber(ctx context.Context) (uint64, error) + TransactionByHash(ctx context.Context, hash common.Hash) (*ethtypes.Transaction, bool, error) +} + +// L2MultiClient fans out read calls across multiple L2 endpoints (same role as tx-submitter iface.L2Clients). +type L2MultiClient interface { + BlockNumber(ctx context.Context) (uint64, error) + BlockByNumber(ctx context.Context, number *big.Int) (*ethtypes.Block, error) + Len() int +} + +// SingleL2Client adapts a single L2 RPC backend as L2MultiClient (Len is always 1). +type SingleL2Client struct { + C interface { + BlockNumber(ctx context.Context) (uint64, error) + BlockByNumber(ctx context.Context, number *big.Int) (*ethtypes.Block, error) + } +} + +func (s *SingleL2Client) BlockNumber(ctx context.Context) (uint64, error) { + return s.C.BlockNumber(ctx) +} + +func (s *SingleL2Client) BlockByNumber(ctx context.Context, number *big.Int) (*ethtypes.Block, error) { + return s.C.BlockByNumber(ctx, number) +} + +func (s *SingleL2Client) Len() int { return 1 } + +// RollupBatchReader is the rollup contract view BatchCache needs (subset of generated Rollup bindings). +type RollupBatchReader interface { + CommittedBatches(opts *bind.CallOpts, batchIndex *big.Int) ([32]byte, error) + LastCommittedBatchIndex(opts *bind.CallOpts) (*big.Int, error) + LastFinalizedBatchIndex(opts *bind.CallOpts) (*big.Int, error) + BatchDataStore(opts *bind.CallOpts, batchIndex *big.Int) (struct { + OriginTimestamp *big.Int + FinalizeTimestamp *big.Int + BlockNumber *big.Int + SignedSequencersBitmap *big.Int + }, error) + FilterFinalizeBatch(opts *bind.FilterOpts, batchIndex []*big.Int, batchHash [][32]byte) (*bindings.RollupFinalizeBatchIterator, error) +} + +// L2GovCaller reads batch-related Gov / bridge / sequencer data on L2. +type L2GovCaller interface { + BatchBlockInterval(opts *bind.CallOpts) (*big.Int, error) + BatchTimeout(opts *bind.CallOpts) (*big.Int, error) + GetTreeRoot(opts *bind.CallOpts) ([32]byte, error) + GetSequencerSetBytes(opts *bind.CallOpts) ([]byte, common.Hash, error) +} diff --git a/common/batch/l2_gov.go b/common/batch/l2_gov.go new file mode 100644 index 000000000..acfe0c0d0 --- /dev/null +++ b/common/batch/l2_gov.go @@ -0,0 +1,82 @@ +package batch + +import ( + "bytes" + "fmt" + "math/big" + + "morph-l2/bindings/bindings" + "morph-l2/bindings/predeploys" + + "github.com/morph-l2/go-ethereum/accounts/abi/bind" + "github.com/morph-l2/go-ethereum/common" + "github.com/morph-l2/go-ethereum/common/hexutil" + "github.com/morph-l2/go-ethereum/crypto" +) + +// L2Gov bundles read-only L2 contracts used when assembling rollup batches. +type L2Gov struct { + sequencerContract *bindings.SequencerCaller + l2MessagePasserContract *bindings.L2ToL1MessagePasserCaller + govContract *bindings.GovCaller +} + +// NewL2Gov builds an L2Gov using any ContractCaller (e.g. *ethclient.Client or a multi-client backend). +func NewL2Gov(backend bind.ContractCaller) (*L2Gov, error) { + if backend == nil { + return nil, fmt.Errorf("nil contract backend") + } + sequencerContract, err := bindings.NewSequencerCaller(predeploys.SequencerAddr, backend) + if err != nil { + return nil, err + } + l2MessagePasserContract, err := bindings.NewL2ToL1MessagePasserCaller(predeploys.L2ToL1MessagePasserAddr, backend) + if err != nil { + return nil, err + } + govContract, err := bindings.NewGovCaller(predeploys.GovAddr, backend) + if err != nil { + return nil, err + } + return &L2Gov{ + sequencerContract: sequencerContract, + l2MessagePasserContract: l2MessagePasserContract, + govContract: govContract, + }, nil +} + +// SequencerSetVerifyHash gets the sequencer set verify hash from the Sequencer contract. +func (c *L2Gov) SequencerSetVerifyHash(opts *bind.CallOpts) ([32]byte, error) { + return c.sequencerContract.SequencerSetVerifyHash(opts) +} + +// GetTreeRoot gets the tree root from the L2ToL1MessagePasser contract. +func (c *L2Gov) GetTreeRoot(opts *bind.CallOpts) ([32]byte, error) { + return c.l2MessagePasserContract.GetTreeRoot(opts) +} + +// BatchBlockInterval gets the batch block interval from the Gov contract. +func (c *L2Gov) BatchBlockInterval(opts *bind.CallOpts) (*big.Int, error) { + return c.govContract.BatchBlockInterval(opts) +} + +// BatchTimeout gets the batch timeout from the Gov contract. +func (c *L2Gov) BatchTimeout(opts *bind.CallOpts) (*big.Int, error) { + return c.govContract.BatchTimeout(opts) +} + +// GetSequencerSetBytes returns sequencer set bytes after hash consistency check. +func (c *L2Gov) GetSequencerSetBytes(opts *bind.CallOpts) ([]byte, common.Hash, error) { + hash, err := c.sequencerContract.SequencerSetVerifyHash(opts) + if err != nil { + return nil, common.Hash{}, err + } + setBytes, err := c.sequencerContract.GetSequencerSetBytes(opts) + if err != nil { + return nil, common.Hash{}, err + } + if bytes.Equal(hash[:], crypto.Keccak256Hash(setBytes).Bytes()) { + return setBytes, hash, nil + } + return nil, common.Hash{}, fmt.Errorf("sequencer set hash verify failed %v: %v", hexutil.Encode(setBytes), common.BytesToHash(hash[:]).String()) +} diff --git a/tx-submitter/types/blob_config.go b/common/blob/fee.go similarity index 50% rename from tx-submitter/types/blob_config.go rename to common/blob/fee.go index 70dc371a3..221e2138b 100644 --- a/tx-submitter/types/blob_config.go +++ b/common/blob/fee.go @@ -1,8 +1,13 @@ -package types +package blob import ( + "crypto/sha256" + "fmt" "math/big" + "github.com/morph-l2/go-ethereum/common" + ethtypes "github.com/morph-l2/go-ethereum/core/types" + "github.com/morph-l2/go-ethereum/crypto/kzg4844" "github.com/morph-l2/go-ethereum/log" ) @@ -42,7 +47,6 @@ type BlobConfig struct { UpdateFraction uint64 } -// Time determination methods (referencing go-ethereum logic). // IsCancun returns whether time is either equal to the Cancun fork time or greater. func (c *BlobFeeConfig) IsCancun(num *big.Int, time uint64) bool { return c.IsLondon(num) && isTimestampForked(c.CancunTime, time) @@ -91,19 +95,16 @@ func (c *BlobFeeConfig) IsLondon(num *big.Int) bool { // GetBlobFeeDenominator returns the corresponding UpdateFraction based on the time. func GetBlobFeeDenominator(blobFeeConfig *BlobFeeConfig, blockTime uint64) *big.Int { if blobFeeConfig == nil { - // If not configured, use default value. log.Warn("BlobFeeConfig not set, using default denominator", "default", DefaultOsakaBlobConfig) return new(big.Int).SetUint64(DefaultOsakaBlobConfig.UpdateFraction) } cfg := blobFeeConfig - londonBlock := cfg.LondonBlock // London block number for fork determination. + londonBlock := cfg.LondonBlock - // Check in priority order from high to low (BPO5 -> BPO4 -> ... -> Cancun). var blobConfig *BlobConfig - // Check BPO5 if cfg.BPO5Time != nil && cfg.IsBPO5(londonBlock, blockTime) && cfg.BPO5 != nil { blobConfig = cfg.BPO5 } else if cfg.BPO4Time != nil && cfg.IsBPO4(londonBlock, blockTime) && cfg.BPO4 != nil { @@ -135,9 +136,6 @@ func GetBlobFeeDenominator(blobFeeConfig *BlobFeeConfig, blockTime uint64) *big. return new(big.Int).SetUint64(blobConfig.UpdateFraction) } -// isBlockForked returns whether a fork scheduled at block s is active at the -// given head block. Whilst this method is the same as isTimestampForked, they -// are explicitly separate for clearer reading. func isBlockForked(s, head *big.Int) bool { if s == nil || head == nil { return false @@ -145,12 +143,168 @@ func isBlockForked(s, head *big.Int) bool { return s.Cmp(head) <= 0 } -// isTimestampForked returns whether a fork scheduled at timestamp s is active -// at the given head timestamp. Whilst this method is the same as isBlockForked, -// they are explicitly separate for clearer reading. func isTimestampForked(s *uint64, head uint64) bool { if s == nil { return false } return *s <= head } + +func newUint64(val uint64) *uint64 { return &val } + +var ( + DefaultCancunBlobConfig = &BlobConfig{ + UpdateFraction: 3338477, + } + DefaultPragueBlobConfig = &BlobConfig{ + UpdateFraction: 5007716, + } + DefaultOsakaBlobConfig = &BlobConfig{ + UpdateFraction: 5007716, + } + DefaultBPO1BlobConfig = &BlobConfig{ + UpdateFraction: 8346193, + } + DefaultBPO2BlobConfig = &BlobConfig{ + UpdateFraction: 11684671, + } + DefaultBPO3BlobConfig = &BlobConfig{ + UpdateFraction: 20609697, + } + DefaultBPO4BlobConfig = &BlobConfig{ + UpdateFraction: 13739630, + } +) + +var ( + MainnetChainConfig = &BlobFeeConfig{ + ChainID: big.NewInt(1), + LondonBlock: big.NewInt(12_965_000), + CancunTime: newUint64(1710338135), + PragueTime: newUint64(1746612311), + OsakaTime: newUint64(1764798551), + BPO1Time: newUint64(1765290071), + BPO2Time: newUint64(1767747671), + Cancun: DefaultCancunBlobConfig, + Prague: DefaultPragueBlobConfig, + Osaka: DefaultOsakaBlobConfig, + BPO1: DefaultBPO1BlobConfig, + BPO2: DefaultBPO2BlobConfig, + Default: DefaultOsakaBlobConfig, + } + + HoodiChainConfig = &BlobFeeConfig{ + ChainID: big.NewInt(560048), + LondonBlock: big.NewInt(0), + CancunTime: newUint64(0), + PragueTime: newUint64(1742999832), + OsakaTime: newUint64(1761677592), + BPO1Time: newUint64(1762365720), + BPO2Time: newUint64(1762955544), + Cancun: DefaultCancunBlobConfig, + Prague: DefaultPragueBlobConfig, + Osaka: DefaultOsakaBlobConfig, + BPO1: DefaultBPO1BlobConfig, + BPO2: DefaultBPO2BlobConfig, + Default: DefaultOsakaBlobConfig, + } + + DevnetChainConfig = &BlobFeeConfig{ + ChainID: big.NewInt(900), + LondonBlock: big.NewInt(0), + CancunTime: newUint64(0), + PragueTime: newUint64(1742999832), + OsakaTime: newUint64(1761677592), + BPO1Time: newUint64(1762365720), + BPO2Time: newUint64(1762955544), + Cancun: DefaultCancunBlobConfig, + Prague: DefaultPragueBlobConfig, + Osaka: DefaultOsakaBlobConfig, + BPO1: DefaultBPO1BlobConfig, + BPO2: DefaultBPO2BlobConfig, + Default: DefaultOsakaBlobConfig, + } +) + +// ChainBlobConfigs maps chain ID to blob fee configuration. +type ChainBlobConfigs map[uint64]*BlobFeeConfig + +var ( + DefaultBlobConfig = HoodiChainConfig + + ChainConfigMap = ChainBlobConfigs{ + 1: MainnetChainConfig, + 560048: HoodiChainConfig, + 900: DevnetChainConfig, + } +) + +// BlobHashes computes the blob hashes of the given blobs. +func BlobHashes(blobs []kzg4844.Blob, commitments []kzg4844.Commitment) []common.Hash { + hasher := sha256.New() + h := make([]common.Hash, len(commitments)) + for i := range commitments { + h[i] = kzg4844.CalcBlobHashV1(hasher, &commitments[i]) + } + return h +} + +// MakeBlobProof builds KZG proofs for blob transactions (sidecar v0). +func MakeBlobProof(blobs []kzg4844.Blob, commitment []kzg4844.Commitment) ([]kzg4844.Proof, error) { + if len(blobs) != len(commitment) { + return nil, fmt.Errorf("blob/commitment length mismatch: %d != %d", len(blobs), len(commitment)) + } + proofs := make([]kzg4844.Proof, len(blobs)) + for i := range blobs { + proof, err := kzg4844.ComputeBlobProof(&blobs[i], commitment[i]) + if err != nil { + return nil, err + } + proofs[i] = proof + } + return proofs, nil +} + +// MakeCellProof builds cell proofs for blob sidecar v1. +func MakeCellProof(blobs []kzg4844.Blob) ([]kzg4844.Proof, error) { + proofs := make([]kzg4844.Proof, 0, len(blobs)*kzg4844.CellProofsPerBlob) + for _, blob := range blobs { + cellProofs, err := kzg4844.ComputeCellProofs(&blob) + if err != nil { + return nil, err + } + proofs = append(proofs, cellProofs...) + } + return proofs, nil +} + +// DetermineBlobVersion selects blob sidecar version from header time and chain config. +func DetermineBlobVersion(head *ethtypes.Header, chainID uint64) byte { + if head == nil { + return ethtypes.BlobSidecarVersion0 + } + blobConfig, exist := ChainConfigMap[chainID] + if !exist { + blobConfig = DefaultBlobConfig + } + if blobConfig.OsakaTime != nil && blobConfig.IsOsaka(head.Number, head.Time) { + return ethtypes.BlobSidecarVersion1 + } + return ethtypes.BlobSidecarVersion0 +} + +// BlobSidecarVersionToV1 converts the BlobSidecar to version 1, attaching the cell proofs. +func BlobSidecarVersionToV1(sc *ethtypes.BlobTxSidecar) error { + if sc.Version == ethtypes.BlobSidecarVersion1 { + return nil + } + if sc.Version == ethtypes.BlobSidecarVersion0 { + proofs, err := MakeCellProof(sc.Blobs) + if err != nil { + return err + } + sc.Version = ethtypes.BlobSidecarVersion1 + sc.Proofs = proofs + } + return nil +} diff --git a/common/blob/payload.go b/common/blob/payload.go new file mode 100644 index 000000000..1b0485651 --- /dev/null +++ b/common/blob/payload.go @@ -0,0 +1,113 @@ +package blob + +import ( + "fmt" + + "morph-l2/node/zstd" + + "github.com/morph-l2/go-ethereum/common" + eth "github.com/morph-l2/go-ethereum/core/types" + "github.com/morph-l2/go-ethereum/crypto/kzg4844" +) + +const MaxBlobBytesSize = 4096 * 31 + +var ( + emptyBlob = new(kzg4844.Blob) + emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob) + emptyBlobProof, _ = kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit) +) + +// EmptyVersionedHash is the versioned hash of the canonical empty blob (all-zero payload). +var EmptyVersionedHash = common.HexToHash("0x010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014") + +// MakeBlobCanonical converts the raw blob data into the canonical blob representation of 4096 BLSFieldElements. +func MakeBlobCanonical(blobBytes []byte) (b *kzg4844.Blob, err error) { + if len(blobBytes) > MaxBlobBytesSize { + return nil, fmt.Errorf("data is too large for blob. len=%v", len(blobBytes)) + } + offset := 0 + b = new(kzg4844.Blob) + for i := 0; i < 4096; i++ { + offset += copy(b[i*32+1:i*32+32], blobBytes[offset:]) + if offset == len(blobBytes) { + break + } + } + if offset < len(blobBytes) { + return nil, fmt.Errorf("failed to fit all data into blob. bytes remaining: %v", len(blobBytes)-offset) + } + return +} + +func RetrieveBlobBytes(blob *kzg4844.Blob) ([]byte, error) { + data := make([]byte, MaxBlobBytesSize) + for i := 0; i < 4096; i++ { + if blob[i*32] != 0 { + return nil, fmt.Errorf("invalid blob, found non-zero high order byte %x of field element %d", blob[i*32], i) + } + copy(data[i*31:i*31+31], blob[i*32+1:i*32+32]) + } + return data, nil +} + +func makeBlobCommitment(bz []byte) (b kzg4844.Blob, c kzg4844.Commitment, err error) { + blob, err := MakeBlobCanonical(bz) + if err != nil { + return + } + b = *blob + c, err = kzg4844.BlobToCommitment(&b) + if err != nil { + return + } + return +} + +func MakeBlobTxSidecar(blobBytes []byte, maxBlobs int) (*eth.BlobTxSidecar, error) { + if len(blobBytes) == 0 { + return ð.BlobTxSidecar{ + Blobs: []kzg4844.Blob{*emptyBlob}, + Commitments: []kzg4844.Commitment{emptyBlobCommit}, + Proofs: []kzg4844.Proof{emptyBlobProof}, + }, nil + } + if maxBlobs <= 0 { + maxBlobs = 1 + } + if len(blobBytes) > maxBlobs*MaxBlobBytesSize { + return nil, fmt.Errorf("data size %d exceeds %d blobs capacity (%d bytes)", len(blobBytes), maxBlobs, maxBlobs*MaxBlobBytesSize) + } + blobCount := (len(blobBytes) + MaxBlobBytesSize - 1) / MaxBlobBytesSize + var ( + err error + blobs = make([]kzg4844.Blob, blobCount) + commitments = make([]kzg4844.Commitment, blobCount) + ) + for i := 0; i < blobCount; i++ { + start := i * MaxBlobBytesSize + end := start + MaxBlobBytesSize + if end > len(blobBytes) { + end = len(blobBytes) + } + blobs[i], commitments[i], err = makeBlobCommitment(blobBytes[start:end]) + if err != nil { + return nil, err + } + } + return ð.BlobTxSidecar{ + Blobs: blobs, + Commitments: commitments, + }, nil +} + +func CompressBatchBytes(batchBytes []byte) ([]byte, error) { + if len(batchBytes) == 0 { + return nil, nil + } + compressedBatchBytes, err := zstd.CompressBatchBytes(batchBytes) + if err != nil { + return nil, fmt.Errorf("failed to compress batch bytes, err: %w", err) + } + return compressedBatchBytes, nil +} diff --git a/common/go.mod b/common/go.mod new file mode 100644 index 000000000..7cee9aa04 --- /dev/null +++ b/common/go.mod @@ -0,0 +1,74 @@ +module morph-l2/common + +go 1.24.0 + +replace github.com/tendermint/tendermint => github.com/morph-l2/tendermint v0.3.7 + +require ( + github.com/holiman/uint256 v1.2.4 + github.com/morph-l2/go-ethereum v1.10.14-0.20260506071313-045be0fdc7ca + github.com/stretchr/testify v1.10.0 + github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a +) + +require ( + github.com/VictoriaMetrics/fastcache v1.12.2 // indirect + github.com/bits-and-blooms/bitset v1.20.0 // indirect + github.com/btcsuite/btcd v0.20.1-beta // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/consensys/bavard v0.1.27 // indirect + github.com/consensys/gnark-crypto v0.16.0 // indirect + github.com/crate-crypto/go-eth-kzg v1.4.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/deckarep/golang-set v1.8.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/edsrzf/mmap-go v1.1.0 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect + github.com/ethereum/go-ethereum v1.10.26 // indirect + github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/hashicorp/go-bexpr v0.1.13 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + github.com/huin/goupnp v1.3.0 // indirect + github.com/iden3/go-iden3-crypto v0.0.16 // indirect + github.com/jackpal/go-nat-pmp v1.0.2 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mitchellh/pointerstructure v1.2.1 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/tsdb v0.10.0 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/rjeczalik/notify v0.9.3 // indirect + github.com/rs/cors v1.11.0 // indirect + github.com/scroll-tech/zktrie v0.8.4 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/status-im/keycard-go v0.3.2 // indirect + github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe // indirect + github.com/tklauser/go-sysconf v0.3.13 // indirect + github.com/tklauser/numcpus v0.7.0 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + golang.org/x/crypto v0.41.0 // indirect + golang.org/x/net v0.43.0 // indirect + golang.org/x/sync v0.16.0 // indirect + golang.org/x/sys v0.35.0 // indirect + golang.org/x/text v0.28.0 // indirect + golang.org/x/time v0.12.0 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect + gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect + gopkg.in/urfave/cli.v1 v1.20.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + rsc.io/tmplfunc v0.0.3 // indirect +) diff --git a/common/go.sum b/common/go.sum new file mode 100644 index 000000000..7570e7331 --- /dev/null +++ b/common/go.sum @@ -0,0 +1,327 @@ +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= +github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU= +github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd/btcec/v2 v2.2.1 h1:xP60mv8fvp+0khmrN0zTdPC3cNm24rfeE6lh2R/Yv3E= +github.com/btcsuite/btcd/btcec/v2 v2.2.1/go.mod h1:9/CSmJxmuvqzX9Wh2fXMWToLOHhPd11lSPuIupwTkI8= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/consensys/bavard v0.1.27 h1:j6hKUrGAy/H+gpNrpLU3I26n1yc+VMGmd6ID5+gAhOs= +github.com/consensys/bavard v0.1.27/go.mod h1:k/zVjHHC4B+PQy1Pg7fgvG3ALicQw540Crag8qx+dZs= +github.com/consensys/gnark-crypto v0.16.0 h1:8Dl4eYmUWK9WmlP1Bj6je688gBRJCJbT8Mw4KoTAawo= +github.com/consensys/gnark-crypto v0.16.0/go.mod h1:Ke3j06ndtPTVvo++PhGNgvm+lgpLvzbcE2MqljY7diU= +github.com/crate-crypto/go-eth-kzg v1.4.0 h1:WzDGjHk4gFg6YzV0rJOAsTK4z3Qkz5jd4RE3DAvPFkg= +github.com/crate-crypto/go-eth-kzg v1.4.0/go.mod h1:J9/u5sWfznSObptgfa92Jq8rTswn6ahQWEuiLHOjCUI= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= +github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= +github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= +github.com/ethereum/c-kzg-4844/v2 v2.1.5 h1:aVtoLK5xwJ6c5RiqO8g8ptJ5KU+2Hdquf6G3aXiHh5s= +github.com/ethereum/c-kzg-4844/v2 v2.1.5/go.mod h1:u59hRTTah4Co6i9fDWtiCjTrblJv0UwsqZKCc0GfgUs= +github.com/ethereum/go-ethereum v1.10.26 h1:i/7d9RBBwiXCEuyduBQzJw/mKmnvzsN14jqBmytw72s= +github.com/ethereum/go-ethereum v1.10.26/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= +github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/hashicorp/go-bexpr v0.1.13 h1:HNwp7vZrMpRq8VZXj8VF90LbZpRjQQpim1oJF0DgSwg= +github.com/hashicorp/go-bexpr v0.1.13/go.mod h1:gN7hRKB3s7yT+YvTdnhZVLTENejvhlkZ8UE4YVBS+Q8= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= +github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= +github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/iden3/go-iden3-crypto v0.0.16 h1:zN867xiz6HgErXVIV/6WyteGcOukE9gybYTorBMEdsk= +github.com/iden3/go-iden3-crypto v0.0.16/go.mod h1:dLpM4vEPJ3nDHzhWFXDjzkn1qHoBeOT/3UEhXsEsP3E= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4= +github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.1 h1:ZhBBeX8tSlRpu/FFhXH4RC4OJzFlqsQhoHZAz4x7TIw= +github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/morph-l2/go-ethereum v1.10.14-0.20260506071313-045be0fdc7ca h1:ogHsgxvm1wzyNKYDSAsIi0PJZeu9VhQECSL91X/KTWI= +github.com/morph-l2/go-ethereum v1.10.14-0.20260506071313-045be0fdc7ca/go.mod h1:nkVzHjQWCOjvukQW8ittlwX+Xz9gmVHrP7mUi7zoHTs= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= +github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rjeczalik/notify v0.9.3 h1:6rJAzHTGKXGj76sbRgDiDcYj/HniypXmSJo1SWakZeY= +github.com/rjeczalik/notify v0.9.3/go.mod h1:gF3zSOrafR9DQEWSE8TjfI9NkooDxbyT4UgRGKZA0lc= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= +github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/scroll-tech/zktrie v0.8.4 h1:UagmnZ4Z3ITCk+aUq9NQZJNAwnWl4gSxsLb2Nl7IgRE= +github.com/scroll-tech/zktrie v0.8.4/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/status-im/keycard-go v0.3.2 h1:YusIF/bHx6YZis8UTOJrpZFnTs4IkRBdmJXqdiXkpFE= +github.com/status-im/keycard-go v0.3.2/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe h1:nbdqkIGOGfUAD54q1s2YBcBz/WcsxCO9HUQ4aGV5hUw= +github.com/supranational/blst v0.3.16-0.20250831170142-f48500c1fdbe/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= +github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= +github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4= +github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0= +github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4= +github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= +golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= +golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/contracts/contracts/l1/rollup/Rollup.sol b/contracts/contracts/l1/rollup/Rollup.sol index 5b6de82f2..14aae181b 100644 --- a/contracts/contracts/l1/rollup/Rollup.sol +++ b/contracts/contracts/l1/rollup/Rollup.sol @@ -5,6 +5,7 @@ import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Own import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; import {BatchHeaderCodecV0} from "../../libraries/codec/BatchHeaderCodecV0.sol"; import {BatchHeaderCodecV1} from "../../libraries/codec/BatchHeaderCodecV1.sol"; + import {IRollupVerifier} from "../../libraries/verifier/IRollupVerifier.sol"; import {IL1MessageQueue} from "./IL1MessageQueue.sol"; import {IRollup} from "./IRollup.sol"; @@ -247,7 +248,7 @@ contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable { require(batchDataInput.numL1Messages > 0, "l1msg delay"); } uint256 submitterBitmap = IL1Staking(l1StakingContract).getStakerBitmap(_msgSender()); - bytes32 _blobVersionedHash = (blobhash(0) == bytes32(0)) ? ZERO_VERSIONED_HASH : blobhash(0); + bytes32 _blobVersionedHash = _computeBlobVersionedHash(batchDataInput.version); _commitBatchWithBatchData(batchDataInput, batchSignatureInput, submitterBitmap, _blobVersionedHash); } @@ -281,7 +282,7 @@ contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable { uint256 submitterBitmap, bytes32 blobVersionedHash ) internal { - require(batchDataInput.version == 0 || batchDataInput.version == 1, "invalid version"); + require(batchDataInput.version <= 2, "invalid version"); require(batchDataInput.prevStateRoot != bytes32(0), "previous state root is zero"); require(batchDataInput.postStateRoot != bytes32(0), "new state root is zero"); @@ -318,11 +319,10 @@ contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable { assembly { _batchIndex := add(_batchIndex, 1) // increase batch index } - bytes32 _blobVersionedHash = blobVersionedHash; - { + // Determine header length: V0 = 249, V1/V2 = 257 uint256 _headerLength = BatchHeaderCodecV0.BATCH_HEADER_LENGTH; - if (batchDataInput.version == 1) { + if (batchDataInput.version >= 1) { _headerLength = BatchHeaderCodecV1.BATCH_HEADER_LENGTH; } assembly { @@ -330,25 +330,28 @@ contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable { mstore(0x40, add(_batchPtr, _headerLength)) } - // store entries, the order matters + // Store header fields (identical layout for all versions) BatchHeaderCodecV0.storeVersion(_batchPtr, batchDataInput.version); BatchHeaderCodecV0.storeBatchIndex(_batchPtr, _batchIndex); BatchHeaderCodecV0.storeL1MessagePopped(_batchPtr, batchDataInput.numL1Messages); BatchHeaderCodecV0.storeTotalL1MessagePopped(_batchPtr, _totalL1MessagesPoppedOverall); BatchHeaderCodecV0.storeDataHash(_batchPtr, dataHash); - BatchHeaderCodecV0.storeBlobVersionedHash(_batchPtr, _blobVersionedHash); + BatchHeaderCodecV0.storeBlobVersionedHash(_batchPtr, blobVersionedHash); BatchHeaderCodecV0.storePrevStateHash(_batchPtr, batchDataInput.prevStateRoot); BatchHeaderCodecV0.storePostStateHash(_batchPtr, batchDataInput.postStateRoot); BatchHeaderCodecV0.storeWithdrawRootHash(_batchPtr, batchDataInput.withdrawalRoot); - BatchHeaderCodecV0.storeSequencerSetVerifyHash(_batchPtr, keccak256(batchSignatureInput.sequencerSets)); + BatchHeaderCodecV0.storeSequencerSetVerifyHash( + _batchPtr, + keccak256(batchSignatureInput.sequencerSets) + ); BatchHeaderCodecV0.storeParentBatchHash(_batchPtr, _parentBatchHash); - // store last block number if version >= 1 if (batchDataInput.version >= 1) { BatchHeaderCodecV1.storeLastBlockNumber(_batchPtr, batchDataInput.lastBlockNumber); } + committedBatches[_batchIndex] = BatchHeaderCodecV0.computeBatchHash(_batchPtr, _headerLength); committedStateRoots[_batchIndex] = batchDataInput.postStateRoot; - batchBlobVersionedHashes[_batchIndex] = _blobVersionedHash; + batchBlobVersionedHashes[_batchIndex] = blobVersionedHash; uint256 proveRemainingTime = 0; if (inChallenge) { // Make the batch finalize time longer than the time required for the current challenge @@ -406,12 +409,12 @@ contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable { // check if the next batch has a stored blob hash (uint256 _batchPtr, ) = _loadBatchHeader(batchDataInput.parentBatchHeader); uint256 _nextBatchIndex = BatchHeaderCodecV0.getBatchIndex(_batchPtr) + 1; - bytes32 _blobVersionedHash = bytes32(0); + bytes32 _blobVersionedHash; if (batchBlobVersionedHashes[_nextBatchIndex] != bytes32(0)) { require(blobhash(0) == bytes32(0), "must not carry blob when using stored blob hash"); _blobVersionedHash = batchBlobVersionedHashes[_nextBatchIndex]; } else { - _blobVersionedHash = (blobhash(0) == bytes32(0)) ? ZERO_VERSIONED_HASH : blobhash(0); + _blobVersionedHash = _computeBlobVersionedHash(batchDataInput.version); } _commitBatchWithBatchData(batchDataInput, batchSignatureInput, 0, _blobVersionedHash); @@ -755,7 +758,11 @@ contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable { require(_batchProof.length > 0, "Invalid batch proof"); uint256 _batchIndex = BatchHeaderCodecV0.getBatchIndex(memPtr); - bytes32 _blobVersionedHash = BatchHeaderCodecV0.getBlobVersionedHash(memPtr); + + // All versions (V0, V1, V2) store the blob hash input at offset 57. + // For V2, this is the aggregated blob hash (keccak256 of all blob hashes concatenated), + // stored at commit time. For V0/V1, it is the single blob versioned hash. + bytes32 _blobHashInput = BatchHeaderCodecV0.getBlobVersionedHash(memPtr); bytes32 _publicInputHash = keccak256( abi.encodePacked( @@ -765,7 +772,7 @@ contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable { BatchHeaderCodecV0.getWithdrawRootHash(memPtr), BatchHeaderCodecV0.getSequencerSetVerifyHash(memPtr), BatchHeaderCodecV0.getDataHash(memPtr), - _blobVersionedHash + _blobHashInput ) ); @@ -861,7 +868,8 @@ contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable { uint256 _length; if (_version == 0) { (_memPtr, _length) = BatchHeaderCodecV0.loadAndValidate(_batchHeader); - } else if (_version == 1) { + } else if (_version == 1 || _version == 2) { + // V2 uses same 257-byte format as V1 (aggregated blob hash at offset 57) (_memPtr, _length) = BatchHeaderCodecV1.loadAndValidate(_batchHeader); } else { revert("Unsupported batch version"); @@ -907,6 +915,39 @@ contract Rollup is IRollup, OwnableUpgradeable, PausableUpgradeable { } } + /// @dev Compute the blob versioned hash for the current transaction. + /// V0/V1: blobhash(0), or ZERO_VERSIONED_HASH if no blob is attached. + /// At most one blob is allowed: extra blobs are ignored by this hash but + /// would still be delivered to L2 derivation, which concatenates all blobs. + /// V2: keccak256(blobhash(0) || ... || blobhash(N-1)), requires at least 1 blob. + function _computeBlobVersionedHash(uint256 _version) internal view returns (bytes32 _blobVersionedHash) { + if (_version == 2) { + uint256 _blobCount; + // Single assembly block: collect blob hashes, hash, and bump 0x40 before any + // Solidity code runs. Splitting assembly around `require` left scratch memory + // unreserved and allowed the compiler to overwrite it via mload(0x40). + assembly { + let scratchPtr := mload(0x40) + let i := 0 + for {} 1 {} { + let h := blobhash(i) + if iszero(h) { + break + } + mstore(add(scratchPtr, mul(i, 32)), h) + i := add(i, 1) + } + _blobCount := i + _blobVersionedHash := keccak256(scratchPtr, mul(i, 32)) + mstore(0x40, add(scratchPtr, mul(i, 32))) + } + require(_blobCount > 0, "V2 requires at least 1 blob"); + } else { + require(blobhash(1) == bytes32(0), "legacy batches support exactly 1 blob"); + _blobVersionedHash = (blobhash(0) == bytes32(0)) ? ZERO_VERSIONED_HASH : blobhash(0); + } + } + /// @dev Internal function to load L1 message hashes from the message queue. /// @param _ptr The memory offset to store the transaction hash. /// @param _numL1Messages The number of L1 messages to load. diff --git a/contracts/contracts/test/BlobVersionedHashLegacy.t.sol b/contracts/contracts/test/BlobVersionedHashLegacy.t.sol new file mode 100644 index 000000000..16f9fb998 --- /dev/null +++ b/contracts/contracts/test/BlobVersionedHashLegacy.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity =0.8.24; + +import "forge-std/Test.sol"; + +/// @dev Mirrors Rollup._computeBlobVersionedHash legacy branch (V0/V1) for isolated testing. +contract BlobVersionedHashLegacyHarness { + bytes32 internal constant ZERO_VERSIONED_HASH = + 0x010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014; + + function legacyBlobVersionedHash() external view returns (bytes32) { + require(blobhash(1) == bytes32(0), "legacy batches support exactly 1 blob"); + return (blobhash(0) == bytes32(0)) ? ZERO_VERSIONED_HASH : blobhash(0); + } +} + +contract BlobVersionedHashLegacyTest is Test { + function test_legacyBlobVersionedHash_noBlobs_returnsZeroSentinel() public { + BlobVersionedHashLegacyHarness h = new BlobVersionedHashLegacyHarness(); + bytes32 expected = + 0x010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014; + assertEq(h.legacyBlobVersionedHash(), expected); + } +} diff --git a/contracts/contracts/test/Rollup.t.sol b/contracts/contracts/test/Rollup.t.sol index 9d40569ed..dbcc95c1c 100644 --- a/contracts/contracts/test/Rollup.t.sol +++ b/contracts/contracts/test/Rollup.t.sol @@ -149,14 +149,14 @@ contract RollupCommitBatchWithProofTest is L1MessageBaseTest { } /// @notice Test: commitBatchWithProof reverts on version mismatch in consistency check - /// Note: Version 1 requires different header length, so this tests the "invalid version" error from _commitBatchWithBatchData + /// Note: Version 3+ is invalid, so this tests the "invalid version" error from _commitBatchWithBatchData function test_commitBatchWithProof_reverts_on_invalid_version() public { _mockMessageQueueStalled(); hevm.warp(block.timestamp + 7200); - - // Create batchDataInput with version 2 (invalid) + + // Create batchDataInput with version 3 (invalid, since V2 is now supported) IRollup.BatchDataInput memory batchDataInput = IRollup.BatchDataInput({ - version: 2, // Invalid version + version: 3, // Invalid version parentBatchHeader: batchHeader0, lastBlockNumber: 1, numL1Messages: 0, @@ -164,9 +164,9 @@ contract RollupCommitBatchWithProofTest is L1MessageBaseTest { postStateRoot: bytes32(uint256(2)), withdrawalRoot: getTreeRoot() }); - + bytes memory batchHeader1 = _createMatchingBatchHeader(1, 0, bytes32(uint256(1)), bytes32(uint256(2)), getTreeRoot()); - + hevm.prank(alice); hevm.expectRevert("invalid version"); rollup.commitBatchWithProof( @@ -176,6 +176,33 @@ contract RollupCommitBatchWithProofTest is L1MessageBaseTest { bytes("") ); } + + /// @notice Test: commitBatchWithProof with V2 requires blobs (reverts without blob in test env) + function test_commitBatchWithProof_v2_reverts_without_blob() public { + _mockMessageQueueStalled(); + hevm.warp(block.timestamp + 7200); + + IRollup.BatchDataInput memory batchDataInput = IRollup.BatchDataInput({ + version: 2, + parentBatchHeader: batchHeader0, + lastBlockNumber: 1, + numL1Messages: 0, + prevStateRoot: bytes32(uint256(1)), + postStateRoot: bytes32(uint256(2)), + withdrawalRoot: getTreeRoot() + }); + + bytes memory batchHeader1 = _createMatchingBatchHeader(1, 0, bytes32(uint256(1)), bytes32(uint256(2)), getTreeRoot()); + + hevm.prank(alice); + hevm.expectRevert("V2 requires at least 1 blob"); + rollup.commitBatchWithProof( + batchDataInput, + batchSignatureInput, + batchHeader1, + bytes("") + ); + } /// @notice Test: commitBatchWithProof reverts when paused function test_commitBatchWithProof_reverts_when_paused() public { @@ -920,10 +947,10 @@ contract RollupTest is L1MessageBaseTest { rollup.commitBatch(batchDataInput, batchSignatureInput); hevm.stopPrank(); - // invalid version, revert + // invalid version, revert (version 3+ is invalid; version 2 is now valid V2 multi-blob) hevm.startPrank(alice); hevm.expectRevert("invalid version"); - batchDataInput = IRollup.BatchDataInput(2, batchHeader0, 0, 0, stateRoot, stateRoot, getTreeRoot()); + batchDataInput = IRollup.BatchDataInput(3, batchHeader0, 0, 0, stateRoot, stateRoot, getTreeRoot()); rollup.commitBatch(batchDataInput, batchSignatureInput); hevm.stopPrank(); @@ -1440,4 +1467,282 @@ contract RollupCommitStateTest is L1MessageBaseTest { hevm.expectRevert("commitBatch requires no stored blob hash"); rollup.commitBatch(batchDataInput, batchSignatureInput); } + +} + +/// @dev Tests for Rollup V2 multi-blob batch header support (simplified: 257-byte header with aggregated blob hash). +contract RollupCommitBatchV2Test is L1MessageBaseTest { + bytes32 public stateRoot = bytes32(uint256(1)); + IRollup.BatchSignatureInput public batchSignatureInput; + bytes public batchHeader0; + bytes32 public batchHash0; + + function setUp() public virtual override { + super.setUp(); + + batchSignatureInput = IRollup.BatchSignatureInput( + uint256(0), + abi.encode(uint256(0), new address[](0), uint256(0), new address[](0), uint256(0), new address[](0)), + bytes("0x") + ); + + // Register staker + hevm.deal(alice, 5 * STAKING_VALUE); + Types.StakerInfo memory stakerInfo = ffi.generateStakerInfo(alice); + address[] memory addrs = new address[](1); + addrs[0] = alice; + hevm.prank(multisig); + l1Staking.updateWhitelist(addrs, new address[](0)); + hevm.prank(alice); + l1Staking.register{value: STAKING_VALUE}(stakerInfo.tmKey, stakerInfo.blsKey); + + // Import genesis batch (V0) + bytes memory _genesis = new bytes(249); + assembly { + let p := add(_genesis, 0x20) + mstore(add(p, 25), 1) // dataHash not zero + mstore(add(p, 57), 0x010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014) // ZERO_VERSIONED_HASH + mstore(add(p, 89), 0) // prevStateHash + mstore(add(p, 121), 1) // postStateHash + } + batchHeader0 = _genesis; + hevm.prank(multisig); + rollup.importGenesisBatch(batchHeader0); + batchHash0 = rollup.committedBatches(0); + } + + /// @dev Helper: build a valid V2 header (257 bytes, same as V1 format) with aggregated blob hash at offset 57. + /// @param aggregatedBlobHash keccak256(blobhash(0) || ... || blobhash(N-1)) — the aggregated hash to store. + /// @param lastBlockNumber The last block number in this batch. + function _buildV2Header( + bytes32 aggregatedBlobHash, + uint64 lastBlockNumber + ) internal pure returns (bytes memory header) { + header = new bytes(BatchHeaderCodecV1.BATCH_HEADER_LENGTH); // 257 bytes + assembly { + let p := add(header, 0x20) + mstore8(p, 2) // version = 2 + mstore(add(p, 1), shl(192, 1)) // batchIndex = 1 + // l1MessagePopped = 0, totalL1MessagePopped = 0 (already zero) + mstore(add(p, 25), 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef) // dataHash + mstore(add(p, 57), aggregatedBlobHash) // aggregated blob hash at offset 57 + mstore(add(p, 89), 0x0000000000000000000000000000000000000000000000000000000000000001) // prevStateHash + mstore(add(p, 121), 0x0000000000000000000000000000000000000000000000000000000000000002) // postStateHash + mstore(add(p, 153), 0x0000000000000000000000000000000000000000000000000000000000000003) // withdrawRootHash + mstore(add(p, 185), 0x0000000000000000000000000000000000000000000000000000000000000004) // seqSetVerifyHash + mstore(add(p, 217), 0x0000000000000000000000000000000000000000000000000000000000000005) // parentBatchHash + mstore(add(p, 249), shl(192, lastBlockNumber)) // lastBlockNumber + } + } + + /// @dev V2 header is 257 bytes (same as V1 format). + function test_v2Header_is_257_bytes() public { + bytes32 aggHash = keccak256(abi.encodePacked(bytes32(uint256(0x1111)))); + bytes memory header = _buildV2Header(aggHash, 100); + assertEq(header.length, 257); + } + + /// @dev V2 header shorter than 257 bytes reverts via V1 loadAndValidate. + function test_v2Header_reverts_tooShort() public { + bytes memory header = new bytes(256); + header[0] = bytes1(uint8(2)); // version = 2 + hevm.expectRevert("batch header length is incorrect"); + // Call _loadBatchHeader indirectly via revertBatch (passes through V1 loader for V2) + // We can't call _loadBatchHeader directly; use a function that calls it + hevm.prank(multisig); + rollup.revertBatch(header, 1); + } + + /*////////////////////////////////////////////////////////////// + Rollup Integration Tests + //////////////////////////////////////////////////////////////*/ + + /// @dev commitBatch with V2 requires at least 1 blob (reverts in test env where blobhash(0)=0). + function test_commitBatchV2_reverts_without_blob() public { + IRollup.BatchDataInput memory batchDataInput = IRollup.BatchDataInput({ + version: 2, + parentBatchHeader: batchHeader0, + lastBlockNumber: 1, + numL1Messages: 0, + prevStateRoot: stateRoot, + postStateRoot: bytes32(uint256(2)), + withdrawalRoot: getTreeRoot() + }); + + hevm.prank(alice); + hevm.expectRevert("V2 requires at least 1 blob"); + rollup.commitBatch(batchDataInput, batchSignatureInput); + } + + /// @dev V2 _loadBatchHeader accepts a valid 257-byte V2 header (uses V1 loader). + /// Tested indirectly: we build a V2 header and verify revertBatch can parse it. + function test_loadBatchHeaderV2_accepts_257_bytes() public { + // Build a V2 header with a known aggregated blob hash + bytes32 aggHash = keccak256(abi.encodePacked(bytes32(uint256(0x1111)), bytes32(uint256(0x2222)))); + bytes memory header = _buildV2Header(aggHash, 42); + + // 257 bytes, version=2 + assertEq(header.length, 257); + assertEq(uint8(header[0]), 2); // version = 2 + // aggregated hash stored at offset 57 + bytes32 storedHash; + assembly { + storedHash := mload(add(add(header, 0x20), 57)) + } + assertEq(storedHash, aggHash); + } + + /*////////////////////////////////////////////////////////////// + Multi-blob aggregated hash tests + //////////////////////////////////////////////////////////////*/ + + /// @dev V2 aggregated hash for N=1: keccak256(h0) — differs from h0 itself (V1 incompatibility). + function test_v2AggregatedHash_single_differs_from_raw() public { + bytes32 h0 = bytes32(uint256(0xBEEF)); + bytes32 aggHash = keccak256(abi.encodePacked(h0)); + assertTrue(aggHash != h0, "keccak(h0) must differ from h0"); + } + + /// @dev V2 aggregated hash for N=2: keccak256(h0 || h1). + function test_v2AggregatedHash_two_blobs() public { + bytes32 h0 = bytes32(uint256(0xAAAA)); + bytes32 h1 = bytes32(uint256(0xBBBB)); + bytes32 expected = keccak256(abi.encodePacked(h0, h1)); + + // Recompute with the same assembly logic used in _computeBlobVersionedHash + bytes32 computed; + assembly { + let ptr := mload(0x40) + mstore(ptr, h0) + mstore(add(ptr, 32), h1) + computed := keccak256(ptr, 64) + } + assertEq(computed, expected); + } + + /// @dev V2 aggregated hash for N=3: keccak256(h0 || h1 || h2). + function test_v2AggregatedHash_three_blobs() public { + bytes32 h0 = bytes32(uint256(0xAAAA)); + bytes32 h1 = bytes32(uint256(0xBBBB)); + bytes32 h2 = bytes32(uint256(0xCCCC)); + bytes32 expected = keccak256(abi.encodePacked(h0, h1, h2)); + + bytes32 computed; + assembly { + let ptr := mload(0x40) + mstore(ptr, h0) + mstore(add(ptr, 32), h1) + mstore(add(ptr, 64), h2) + computed := keccak256(ptr, 96) + } + assertEq(computed, expected); + } + + /// @dev V2 aggregated hash is order-sensitive: (h0,h1) != (h1,h0). + function test_v2AggregatedHash_order_sensitive() public { + bytes32 h0 = bytes32(uint256(0xAAAA)); + bytes32 h1 = bytes32(uint256(0xBBBB)); + bytes32 fwd = keccak256(abi.encodePacked(h0, h1)); + bytes32 rev = keccak256(abi.encodePacked(h1, h0)); + assertTrue(fwd != rev, "aggregated hash must be order-sensitive"); + } + + /*////////////////////////////////////////////////////////////// + _verifyProof public input hash tests + //////////////////////////////////////////////////////////////*/ + + /// @dev _verifyProof uses the 32-byte value at offset 57 (aggregated blob hash for V2) + /// as blobHashInput in publicInputHash. + /// Verified by: + /// 1. Showing publicInputHash with aggregated hash (V2) != publicInputHash with raw hash (V1) + /// 2. Confirming V2 header's offset 57 holds the aggregated hash + /// 3. Confirming publicInputHash derived from offset 57 equals the expected V2 value + function test_verifyProof_v2_publicInput_uses_aggregated_hash() public { + bytes32 prevStateRoot = bytes32(uint256(0x1)); + bytes32 postStateRoot = bytes32(uint256(0x2)); + bytes32 withdrawRoot = bytes32(uint256(0x3)); + bytes32 seqVerifyHash = bytes32(uint256(0x4)); + bytes32 dataHash = bytes32(uint256(0xDEAD)); + bytes32 h0 = bytes32(uint256(0xAAAA)); + bytes32 h1 = bytes32(uint256(0xBBBB)); + + // V2 aggregated hash: keccak256(h0 || h1) + bytes32 aggregatedHash = keccak256(abi.encodePacked(h0, h1)); + + // Expected V2 publicInputHash (Rollup._verifyProof reads offset 57 for all versions) + bytes32 v2PublicInput = keccak256(abi.encodePacked( + uint64(layer2ChainID), + prevStateRoot, postStateRoot, withdrawRoot, seqVerifyHash, dataHash, + aggregatedHash + )); + + // V1 would put h0 directly at offset 57 — must differ from V2 + bytes32 v1PublicInput = keccak256(abi.encodePacked( + uint64(layer2ChainID), + prevStateRoot, postStateRoot, withdrawRoot, seqVerifyHash, dataHash, + h0 + )); + assertTrue(v2PublicInput != v1PublicInput, "V2 publicInputHash must differ from V1"); + + // V2 single blob also differs from V1 (keccak(h0) != h0) + bytes32 v2SinglePublicInput = keccak256(abi.encodePacked( + uint64(layer2ChainID), + prevStateRoot, postStateRoot, withdrawRoot, seqVerifyHash, dataHash, + keccak256(abi.encodePacked(h0)) + )); + assertTrue(v2SinglePublicInput != v1PublicInput, "V2 single-blob publicInputHash must differ from V1"); + + // Confirm V2 header stores aggregated hash at offset 57 + bytes32 _batchHash0 = batchHash0; + bytes memory header = new bytes(BatchHeaderCodecV1.BATCH_HEADER_LENGTH); + assembly { + let p := add(header, 0x20) + mstore8(p, 2) + mstore(add(p, 1), shl(192, 1)) + mstore(add(p, 25), dataHash) + mstore(add(p, 57), aggregatedHash) + mstore(add(p, 89), prevStateRoot) + mstore(add(p, 121), postStateRoot) + mstore(add(p, 153), withdrawRoot) + mstore(add(p, 185), seqVerifyHash) + mstore(add(p, 217), _batchHash0) + mstore(add(p, 249), shl(192, 1)) + } + bytes32 offset57; + assembly { offset57 := mload(add(add(header, 0x20), 57)) } + assertEq(offset57, aggregatedHash, "offset 57 must hold aggregated hash"); + + // Confirm publicInputHash derived from offset 57 equals v2PublicInput + bytes32 derivedPublicInput = keccak256(abi.encodePacked( + uint64(layer2ChainID), + prevStateRoot, postStateRoot, withdrawRoot, seqVerifyHash, dataHash, + offset57 + )); + assertEq(derivedPublicInput, v2PublicInput, "publicInputHash from header must match expected"); + } + + /// @dev V2 single-blob publicInputHash != V1 single-blob publicInputHash (not backward-compatible). + function test_verifyProof_v2_single_blob_differs_from_v1() public { + bytes32 versioned_hash = bytes32(uint256(0xBEEF)); + + // V1: blob input = versioned_hash directly + bytes32 v1Input = keccak256( + abi.encodePacked( + uint64(layer2ChainID), + bytes32(0), bytes32(0), bytes32(0), bytes32(0), bytes32(0), + versioned_hash + ) + ); + + // V2: blob input = keccak256(versioned_hash) + bytes32 v2Input = keccak256( + abi.encodePacked( + uint64(layer2ChainID), + bytes32(0), bytes32(0), bytes32(0), bytes32(0), bytes32(0), + keccak256(abi.encodePacked(versioned_hash)) + ) + ); + + assertTrue(v1Input != v2Input, "V2 single-blob must differ from V1"); + } } diff --git a/contracts/src/deploy-config/holesky.ts b/contracts/src/deploy-config/holesky.ts index 11316b32e..353d9ced9 100644 --- a/contracts/src/deploy-config/holesky.ts +++ b/contracts/src/deploy-config/holesky.ts @@ -14,7 +14,7 @@ const config = { l2BaseFee: 0.1, // Gwei // verify contract config - programVkey: '0x00c4ea13863f7b423f53140f432d7147e48b8e31660420636931c0a72459c25c', + programVkey: '0x00f1b104202c89fe60d973cbf456a4e2e1ec1e7d63c61453b959dda153df798c', // rollup contract config // initialize config finalizationPeriodSeconds: 600, diff --git a/contracts/src/deploy-config/hoodi.ts b/contracts/src/deploy-config/hoodi.ts index 8f97970f4..d589f50a6 100644 --- a/contracts/src/deploy-config/hoodi.ts +++ b/contracts/src/deploy-config/hoodi.ts @@ -17,7 +17,7 @@ const config = { l2BaseFee: 0.1, // Gwei // verify contract config - programVkey: '0x00c4ea13863f7b423f53140f432d7147e48b8e31660420636931c0a72459c25c', + programVkey: '0x00f1b104202c89fe60d973cbf456a4e2e1ec1e7d63c61453b959dda153df798c', // rollup contract config // initialize config finalizationPeriodSeconds: 600, diff --git a/contracts/src/deploy-config/l1.ts b/contracts/src/deploy-config/l1.ts index f71e41eb3..285ca9c59 100644 --- a/contracts/src/deploy-config/l1.ts +++ b/contracts/src/deploy-config/l1.ts @@ -17,7 +17,7 @@ const config = { l2BaseFee: 0.1, // Gwei // verify contract config - programVkey: '0x00c4ea13863f7b423f53140f432d7147e48b8e31660420636931c0a72459c25c', + programVkey: '0x00f1b104202c89fe60d973cbf456a4e2e1ec1e7d63c61453b959dda153df798c', // rollup contract config // initialize config finalizationPeriodSeconds: 10, diff --git a/contracts/src/deploy-config/qanetl1.ts b/contracts/src/deploy-config/qanetl1.ts index ada3595fb..b0740d0b9 100644 --- a/contracts/src/deploy-config/qanetl1.ts +++ b/contracts/src/deploy-config/qanetl1.ts @@ -14,7 +14,7 @@ const config = { l2BaseFee: 0.1, // Gwei // verify contract config - programVkey: '0x00c4ea13863f7b423f53140f432d7147e48b8e31660420636931c0a72459c25c', + programVkey: '0x00f1b104202c89fe60d973cbf456a4e2e1ec1e7d63c61453b959dda153df798c', // rollup contract config // initialize config finalizationPeriodSeconds: 600, diff --git a/contracts/src/deploy-config/sepolia.ts b/contracts/src/deploy-config/sepolia.ts index be287026e..3657c5811 100644 --- a/contracts/src/deploy-config/sepolia.ts +++ b/contracts/src/deploy-config/sepolia.ts @@ -18,7 +18,7 @@ const config = { /** * ---to---legacy property */ - programVkey: '0x00c4ea13863f7b423f53140f432d7147e48b8e31660420636931c0a72459c25c', + programVkey: '0x00f1b104202c89fe60d973cbf456a4e2e1ec1e7d63c61453b959dda153df798c', rollupMinDeposit: 0.0001, rollupProofWindow: 86400, rollupGenesisBlockNumber: 0, diff --git a/contracts/src/deploy-config/testnetl1.ts b/contracts/src/deploy-config/testnetl1.ts index 31a6e5746..8e0c9786f 100644 --- a/contracts/src/deploy-config/testnetl1.ts +++ b/contracts/src/deploy-config/testnetl1.ts @@ -13,7 +13,7 @@ const config = { sequencerWindowSize: 200, channelTimeout: 120, - programVkey: '0x00c4ea13863f7b423f53140f432d7147e48b8e31660420636931c0a72459c25c', + programVkey: '0x00f1b104202c89fe60d973cbf456a4e2e1ec1e7d63c61453b959dda153df798c', rollupMinDeposit: 1, rollupProofWindow: 100, rollupGenesisBlockNumber: 0, diff --git a/gas-oracle/app/src/da_scalar/blob.rs b/gas-oracle/app/src/da_scalar/blob.rs index 18765cc17..dea157f3c 100644 --- a/gas-oracle/app/src/da_scalar/blob.rs +++ b/gas-oracle/app/src/da_scalar/blob.rs @@ -14,14 +14,14 @@ const MAX_BLOB_TX_PAYLOAD_SIZE: usize = 131072; // 131072 = 4096 * 32 = 1024 * 4 pub struct Blob(pub [u8; MAX_BLOB_TX_PAYLOAD_SIZE]); impl Blob { - pub fn get_origin_batch(&self) -> Result, BlobError> { - let compressed_data = self.get_compressed_batch()?; - decompress_batch(&compressed_data) - } - - pub fn get_compressed_batch(&self) -> Result, BlobError> { - // Decode blob, recovering BLS12-381 scalars. - let mut data = vec![0u8; MAX_BLOB_TX_PAYLOAD_SIZE]; + /// Extract the raw payload segment from a blob by removing the BLS12-381 field encoding, + /// without performing zstd decompression. + /// Under the new format, the concatenation of multiple blob segments forms the full zstd + /// payload. + pub fn get_payload_bytes(&self) -> Result, BlobError> { + // Decode blob and recover BLS12-381 scalars. + // Each field element is 32 bytes, with 31 bytes of usable payload. + let mut data = vec![0u8; 4096 * 31]; for i in 0..4096 { if self.0[i * 32] != 0 { return Err(BlobError::InvalidBlob(anyhow!(format!( @@ -32,12 +32,13 @@ impl Blob { } data[i * 31..i * 31 + 31].copy_from_slice(&self.0[i * 32 + 1..i * 32 + 32]); } - - // detect_zstd_compressed - Ok(Self::detect_zstd_compressed(data)?) + Ok(data) } - fn detect_zstd_compressed(decoded_blob: Vec) -> Result, BlobError> { + pub fn detect_zstd_compressed( + decoded_blob: Vec, + num_blobs: usize, + ) -> Result, BlobError> { // The format of zstd_compression is shown in the following link: // https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#frame_header let fcs_field_size = match parse_frame_header_descriptor(&decoded_blob) { @@ -74,13 +75,14 @@ impl Blob { // compressed_data = frame_header + frame_content_field_size + zstd_blocks let compressed_len = get_blocks_size(&decoded_blob, fcs_field_size)? + 1; - if compressed_len as usize > MAX_BLOB_TX_PAYLOAD_SIZE - 4096 { + let max_payload_size = num_blobs * (MAX_BLOB_TX_PAYLOAD_SIZE - 4096); + if compressed_len as usize > max_payload_size { return Err(BlobError::Error(anyhow!("oversized batch payload"))) } let compressed_batch = decoded_blob[..compressed_len].to_vec(); // check data - Self::check_data(&compressed_batch, &decoded_blob, fcs_field_size)?; + Self::check_data(&compressed_batch, &decoded_blob, fcs_field_size, num_blobs)?; Ok(compressed_batch) } @@ -89,6 +91,7 @@ impl Blob { compressed_data: &Vec, decoded_blob: &[u8], fcs_field_size: usize, + num_blobs: usize, ) -> Result<(), BlobError> { let origin_batch = decompress_batch(compressed_data)?; @@ -103,9 +106,11 @@ impl Blob { ))) } + let total_blob_payload = num_blobs as f32 * (MAX_BLOB_TX_PAYLOAD_SIZE - 4096) as f32; log::info!( - "check_blob_data, blob usage {:.3}, batch_compression_ratio: {:.3}", - compressed_data.len() as f32 / MAX_BLOB_TX_PAYLOAD_SIZE as f32, + "check_blob_data, num_blobs: {}, blob usage {:.3}, batch_compression_ratio: {:.3}", + num_blobs, + compressed_data.len() as f32 / total_blob_payload, orgin_content_size as f32 / compressed_data.len() as f32 ); Ok(()) @@ -146,12 +151,6 @@ fn parse_block_header( return Err("Compressed batch is too small to contain a valid block header".into()); } - // Make sure we have enough data to parse - if compressed_data.len() < 1 + fcs_field_size + 3 { - // 2 (minimum starting point) + 3 (block header size) - return Err("Compressed batch is too small to contain a valid block header".into()); - } - // Extract the 3-byte header // data_block_start_index = fcs_field_size + 1(frame block size); let header = &compressed_data[1 + fcs_field_size..1 + fcs_field_size + 3]; @@ -200,10 +199,11 @@ mod tests { let blob_bytes = load_zstd_blob(); let blob = Blob(blob_bytes); - let result = blob.get_compressed_batch(); - assert!(result.is_ok(), "{}", result.err().unwrap()); - - let compressed_batch: Vec = result.unwrap(); + // Under the new format, a single blob still uses the multi-blob decoding path + // (get_payload_bytes -> detect_zstd_compressed -> decompress_batch). + let payload = blob.get_payload_bytes().expect("get_payload_bytes failed"); + let compressed_batch = + Blob::detect_zstd_compressed(payload, 1).expect("detect_zstd_compressed failed"); assert_eq!(compressed_batch.len(), 60576); let origin_batch = super::decompress_batch(&compressed_batch).unwrap(); @@ -239,25 +239,19 @@ mod tests { encoded_bytes }; - let origin_batch = decompress_batch(&encoded_bytes).unwrap(); - println!( - "=======origin_batch_len: {:?}, batch_data_bytes_len: {:?}", - origin_batch.len(), - batch_data_bytes.len() - ); - - // Encode to blob + // Encode to blob under the new format: encode compressed bytes into BLS12-381 + // field elements in 31-byte groups. let mut blob_data = [0u8; MAX_BLOB_TX_PAYLOAD_SIZE]; for (i, &byte) in encoded_bytes.iter().enumerate() { blob_data[1 + (i % 31) + 32 * (i / 31)] = byte; } let blob = Blob(blob_data); - // Test compressed_batch from blob - let result = blob.get_compressed_batch(); - assert!(result.is_ok(), "{}", result.err().unwrap()); - - let compressed_batch: Vec = result.unwrap(); + // Under the new format, a single blob still uses the multi-blob decoding path + // (get_payload_bytes -> detect_zstd_compressed -> decompress_batch). + let payload = blob.get_payload_bytes().expect("get_payload_bytes failed"); + let compressed_batch = + Blob::detect_zstd_compressed(payload, 1).expect("detect_zstd_compressed failed"); println!("encoded_bytes_len: {:?}", encoded_bytes.len()); assert_eq!(compressed_batch.len(), encoded_bytes.len()); assert_eq!(compressed_batch, encoded_bytes); diff --git a/gas-oracle/app/src/da_scalar/calculate.rs b/gas-oracle/app/src/da_scalar/calculate.rs index 92b0e537e..7e7df970a 100644 --- a/gas-oracle/app/src/da_scalar/calculate.rs +++ b/gas-oracle/app/src/da_scalar/calculate.rs @@ -7,17 +7,23 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; use super::{ - blob::{kzg_to_versioned_hash, Blob}, + blob::{decompress_batch, kzg_to_versioned_hash, Blob}, error::ScalarError, typed_tx::TypedTransaction, MAX_BLOB_TX_PAYLOAD_SIZE, }; +/// Extract the full batch data from multiple blobs. +/// All blobs belong to the same batch: the batch is compressed as a whole, split into +/// multiple segments (each at most 4096 * 31 bytes), and then encoded into BLS12-381 +/// field elements stored in the blobs. +/// This function remains compatible with the single-blob case. pub(super) fn extract_tx_payload( indexed_hashes: Vec, sidecars: &[Value], -) -> Result>, ScalarError> { - let mut batch_bytes = Vec::>::new(); +) -> Result, ScalarError> { + let num_blobs = indexed_hashes.len(); + let mut combined_payload = Vec::::new(); for i_h in indexed_hashes { if let Some(sidecar) = sidecars.iter().find(|sidecar| { sidecar["index"].as_str().unwrap_or("1000").parse::().unwrap_or(1000) == i_h.index @@ -62,14 +68,15 @@ pub(super) fn extract_tx_payload( let blob_array: [u8; MAX_BLOB_TX_PAYLOAD_SIZE] = decoded_blob.try_into().unwrap(); let blob_struct = Blob(blob_array); - let origin_batch = blob_struct.get_origin_batch().map_err(|e| { + // Extract the raw payload segment by removing only the BLS12-381 encoding, + // without zstd decompression. + let payload_bytes = blob_struct.get_payload_bytes().map_err(|e| { ScalarError::CalculateError(anyhow!(format!( - "Failed to decode blob tx payload: {}", - e + "Failed to get payload bytes from blob, blob_hash: {:?}, err: {}", + i_h.hash, e ))) })?; - - batch_bytes.push(origin_batch); + combined_payload.extend_from_slice(&payload_bytes); } else { return Err(ScalarError::CalculateError(anyhow!(format!( "no blob in response matches desired index: {}", @@ -77,7 +84,21 @@ pub(super) fn extract_tx_payload( )))); } } - Ok(batch_bytes) + + // After concatenation, use detect_zstd_compressed to trim the valid compressed payload + // (excluding trailing zero padding), then decompress the batch as a whole. + let compressed_data = Blob::detect_zstd_compressed(combined_payload, num_blobs).map_err(|e| { + ScalarError::CalculateError(anyhow!(format!( + "Failed to detect zstd compressed data from combined blob payload: {}", + e + ))) + })?; + decompress_batch(&compressed_data).map_err(|e| { + ScalarError::CalculateError(anyhow!(format!( + "Failed to decompress combined blob payload: {}", + e + ))) + }) } pub fn extract_txn_count(origin_batch: &Vec, last_block_num: u64) -> Option { diff --git a/gas-oracle/app/src/da_scalar/l1_scalar.rs b/gas-oracle/app/src/da_scalar/l1_scalar.rs index 1f653915b..bbd6d8e7a 100644 --- a/gas-oracle/app/src/da_scalar/l1_scalar.rs +++ b/gas-oracle/app/src/da_scalar/l1_scalar.rs @@ -17,8 +17,8 @@ use crate::{ metrics::ORACLE_SERVICE_METRICS, signer::send_transaction, }; -use remote_signer_client::SignerClient; use ethers::{abi::AbiDecode, prelude::*, utils::hex}; +use remote_signer_client::SignerClient; use serde_json::Value; const PRECISION: u64 = 10u64.pow(9); @@ -218,7 +218,7 @@ impl ScalarUpdater { block_num: U64, ) -> Result<(u64, u64), ScalarError> { //Step1. get_data_from_blob - let (l2_data_len, l2_txn) = + let (l2_data_len, num_blobs, l2_txn) = self.get_data_from_blob(tx_hash, block_num).await.map_err(|e| { log::error!("get_data_from_blob error: {:#?}", e); e @@ -249,7 +249,7 @@ impl ScalarUpdater { let commit_scalar = (rollup_gas_used.as_u64() + self.finalize_batch_gas_used) * PRECISION / l2_txn.max(self.txn_per_batch); let blob_scalar = if l2_data_len > 0 { - MAX_BLOB_TX_PAYLOAD_SIZE as u64 * PRECISION / l2_data_len + num_blobs.max(1) * MAX_BLOB_TX_PAYLOAD_SIZE as u64 * PRECISION / l2_data_len } else { MAX_BLOB_SCALAR }; @@ -272,7 +272,7 @@ impl ScalarUpdater { &self, tx_hash: TxHash, block_num: U64, - ) -> Result<(u64, u64), ScalarError> { + ) -> Result<(u64, u64, u64), ScalarError> { let blob_tx = self .l1_provider .get_transaction(tx_hash) @@ -300,7 +300,7 @@ impl ScalarUpdater { let indexed_hashes = data_and_hashes_from_txs(&blob_block.transactions, &blob_tx); if indexed_hashes.is_empty() { log::info!("no blob in this batch, batch_tx_hash: {:#?}", tx_hash); - return Ok((0, 0)); + return Ok((0, 0, 0)); } // Waiting for the next L1 block to be produced. @@ -369,65 +369,25 @@ impl ScalarUpdater { )))); } - let tx_payloads = extract_tx_payload(indexed_hashes, sidecars)?; - let data_with_txn_count: Vec<(u64, u64)> = tx_payloads - .iter() - .map(|batch: &Vec| { - (batch.len() as u64, extract_txn_count(batch, last_block_num).unwrap_or_default()) - }) - .collect(); + // All blobs belong to the same batch: the batch is compressed as a whole, + // split into multiple segments across blobs, then reconstructed by concatenating + // the segments, trimming the valid compressed payload, and decompressing once. + // This also remains compatible with the single-blob case. + let num_blobs = indexed_hashes.len() as u64; + let origin_batch = extract_tx_payload(indexed_hashes, sidecars)?; - let (total_size, total_count) = data_with_txn_count - .iter() - .fold((0u64, 0u64), |acc, &(size, count)| (acc.0 + size, acc.1 + count)); + let batch_size = origin_batch.len() as u64; + let txn_count = extract_txn_count(&origin_batch, last_block_num).unwrap_or_default(); - Ok((total_size, total_count)) + Ok((batch_size, num_blobs, txn_count)) } } #[cfg(test)] mod tests { - use crate::da_scalar::blob::Blob; use super::*; - use std::{env::var, fs, path::Path, str::FromStr, sync::Arc}; - - #[test] - fn test_blob_data() { - let blob_data_path = Path::new("data/blob_with_context.data"); - let data = fs::read_to_string(blob_data_path).expect("Unable to read file"); - let hex_data: Vec = hex::decode(data.trim()).unwrap(); - - let mut blob_array = [0u8; 131072]; - blob_array.copy_from_slice(&hex_data); - - let blob_struct = Blob(blob_array); - let origin_batch = blob_struct - .get_origin_batch() - .map_err(|e| { - ScalarError::CalculateError(anyhow!(format!( - "Failed to decode blob tx payload: {}", - e - ))) - }) - .unwrap(); - - let mut tx_payloads: Vec> = vec![]; - tx_payloads.push(origin_batch); - - let data_with_txn_count: Vec<(u64, u64)> = tx_payloads - .iter() - .map(|batch: &Vec| { - (batch.len() as u64, extract_txn_count(batch, 328208).unwrap_or_default()) - }) - .collect(); - - let (total_size, total_count) = data_with_txn_count - .iter() - .fold((0u64, 0u64), |acc, &(size, count)| (acc.0 + size, acc.1 + count)); - - println!("total_size: {}, total_count: {}", total_size, total_count) - } + use std::{env::var, str::FromStr, sync::Arc}; #[tokio::test] #[ignore] @@ -464,7 +424,8 @@ mod tests { let l2_oracle_contract = GasPriceOracle::new(l2_oracle_address, l2_signer); - let ext_signer = SignerClient::new("appid", "privkey_pem", "address", "chain", "url").unwrap(); + let ext_signer = + SignerClient::new("appid", "privkey_pem", "address", "chain", "url").unwrap(); let mut overhead: ScalarUpdater = ScalarUpdater::new( l1_provider, l2_provider, diff --git a/go.work b/go.work index d29dbaad9..e64d53272 100644 --- a/go.work +++ b/go.work @@ -2,6 +2,7 @@ go 1.24.0 use ( ./bindings + ./common ./contracts ./node ./ops/l2-genesis diff --git a/go.work.sum b/go.work.sum index 46b23aaa0..210c2a1a1 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1290,6 +1290,7 @@ github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= github.com/yeya24/promlinter v0.2.0 h1:xFKDQ82orCU5jQujdaD8stOHiv8UN68BSdn2a8u8Y3o= github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA= +github.com/yuin/goldmark v1.2.1 h1:ruQGxdhGHe7FWOJPT0mKs5+pD2Xs1Bm/kdGlHO04FmM= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -1367,6 +1368,7 @@ golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0Y golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg= golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d h1:+W8Qf4iJtMGKkyAygcKohjxTk4JPsL9DpzApJ22m5Ic= golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= @@ -1381,6 +1383,7 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1460,6 +1463,7 @@ golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= +golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= diff --git a/node/derivation/batch_info.go b/node/derivation/batch_info.go index d795092b8..d9616634b 100644 --- a/node/derivation/batch_info.go +++ b/node/derivation/batch_info.go @@ -1,10 +1,8 @@ package derivation import ( - "bytes" "encoding/binary" "fmt" - "io" "math/big" "github.com/morph-l2/go-ethereum/common" @@ -13,6 +11,7 @@ import ( geth "github.com/morph-l2/go-ethereum/eth" "github.com/morph-l2/go-ethereum/eth/catalyst" + commonbatch "morph-l2/common/batch" "morph-l2/node/types" "morph-l2/node/zstd" ) @@ -83,7 +82,7 @@ func (bi *BatchInfo) ParseBatch(batch geth.RPCRollupBatch) error { if len(batch.Sidecar.Blobs) == 0 { return fmt.Errorf("blobs length can not be zero") } - parentBatchHeader := types.BatchHeaderBytes(batch.ParentBatchHeader) + parentBatchHeader := commonbatch.BatchHeaderBytes(batch.ParentBatchHeader) parentBatchIndex, err := parentBatchHeader.BatchIndex() if err != nil { return fmt.Errorf("decode batch header index error:%v", err) @@ -98,8 +97,27 @@ func (bi *BatchInfo) ParseBatch(batch geth.RPCRollupBatch) error { bi.withdrawalRoot = batch.WithdrawRoot bi.version = uint64(batch.Version) tq := newTxQueue() - var rawBlockContexts hexutil.Bytes - var txsData []byte + + // Multi-blob batches (V2+) are produced by zstd-compressing the entire + // batch payload as a single stream and then splitting the compressed + // bytes across N blobs in submission order. To recover the payload we + // must concatenate all blob bodies first and decompress once; per-blob + // decompression would fail on the second blob since it is not a + // standalone zstd stream. + compressed := make([]byte, 0, len(batch.Sidecar.Blobs)*commonbatch.MaxBlobBytesSize) + for i := range batch.Sidecar.Blobs { + blobCopy := batch.Sidecar.Blobs[i] + blobData, err := commonbatch.RetrieveBlobBytes(&blobCopy) + if err != nil { + return err + } + compressed = append(compressed, blobData...) + } + batchBytes, err := zstd.DecompressBatchBytes(compressed) + if err != nil { + return fmt.Errorf("decompress batch bytes error:%v", err) + } + var blockCount uint64 if batch.Version > 0 { parentVersion, err := parentBatchHeader.Version() @@ -107,68 +125,63 @@ func (bi *BatchInfo) ParseBatch(batch geth.RPCRollupBatch) error { return fmt.Errorf("decode batch header version error:%v", err) } if parentVersion == 0 { - blobData, err := types.RetrieveBlobBytes(&batch.Sidecar.Blobs[0]) - if err != nil { - return err - } - batchBytes, err := zstd.DecompressBatchBytes(blobData) - if err != nil { - return fmt.Errorf("decompress batch bytes error:%v", err) + // V0 -> V1+ transition: parent header carries no LastBlockNumber, + // so derive blockCount from the first block context embedded at + // the start of the decompressed batch. + if len(batchBytes) < 60 { + return fmt.Errorf("decompressed batch too short for start block context: have %d, need 60", len(batchBytes)) } var startBlock BlockContext if err := startBlock.Decode(batchBytes[:60]); err != nil { return fmt.Errorf("decode chunk block context error:%v", err) } + // Guard against uint64 underflow for malformed batches whose + // LastBlockNumber is below the decoded start block. + if batch.LastBlockNumber < startBlock.Number { + return fmt.Errorf("invalid batch: lastBlockNumber %d < start block %d", batch.LastBlockNumber, startBlock.Number) + } blockCount = batch.LastBlockNumber - startBlock.Number + 1 } else { parentBatchBlock, err := parentBatchHeader.LastBlockNumber() if err != nil { return fmt.Errorf("decode batch header lastBlockNumber error:%v", err) } - blockCount = batch.LastBlockNumber - parentBatchBlock - } - - } - // If BlockContexts is not nil, the block context should not be included in the blob. - // Therefore, the required length must be zero. - length := blockCount * 60 - for _, blob := range batch.Sidecar.Blobs { - blobCopy := blob - blobData, err := types.RetrieveBlobBytes(&blobCopy) - if err != nil { - return err - } - batchBytes, err := zstd.DecompressBatchBytes(blobData) - if err != nil { - return err - } - reader := bytes.NewReader(batchBytes) - if batch.BlockContexts == nil { - if len(batchBytes) < int(length) { - rawBlockContexts = append(rawBlockContexts, batchBytes...) - length -= uint64(len(batchBytes)) - reader.Reset(nil) - } else { - bcBytes := make([]byte, length) - _, err = reader.Read(bcBytes) - if err != nil { - return fmt.Errorf("read block context error:%s", err.Error()) - } - rawBlockContexts = append(rawBlockContexts, bcBytes...) - length = 0 + // Guard against uint64 underflow for malformed batches whose + // LastBlockNumber is below the parent's lastBlockNumber. + if batch.LastBlockNumber < parentBatchBlock { + return fmt.Errorf("invalid batch: lastBlockNumber %d < parent lastBlockNumber %d", batch.LastBlockNumber, parentBatchBlock) } + blockCount = batch.LastBlockNumber - parentBatchBlock } - data, err := io.ReadAll(reader) - if err != nil { - return fmt.Errorf("read txBytes error:%s", err.Error()) - } - txsData = append(txsData, data...) } + + var rawBlockContexts hexutil.Bytes + var txsData []byte if batch.BlockContexts != nil { + // Block contexts come from calldata; the entire decompressed stream + // is tx payload data. ABI-decoded `bytes` can be a non-nil zero/short + // slice, so guard the 2-byte block-count prefix read explicitly. + if len(batch.BlockContexts) < 2 { + return fmt.Errorf("calldata block contexts too short for block count prefix: have %d, need 2", len(batch.BlockContexts)) + } blockCount = uint64(binary.BigEndian.Uint16(batch.BlockContexts[:2])) + if uint64(len(batch.BlockContexts)) < 2+60*blockCount { + return fmt.Errorf("calldata block contexts too short: have %d, need %d", len(batch.BlockContexts), 2+60*blockCount) + } rawBlockContexts = batch.BlockContexts[2 : 60*blockCount+2] + txsData = batchBytes + } else { + // Block contexts are at the head of the decompressed stream, + // immediately followed by the tx payload bytes. + bcLen := blockCount * 60 + if uint64(len(batchBytes)) < bcLen { + return fmt.Errorf("decompressed batch too short for block contexts: have %d, need %d", len(batchBytes), bcLen) + } + rawBlockContexts = batchBytes[:bcLen] + txsData = batchBytes[bcLen:] } - data, err := types.DecodeTxsFromBytes(txsData) + + data, err := commonbatch.DecodeTxsFromBytes(txsData) if err != nil { return err } diff --git a/node/derivation/batch_info_test.go b/node/derivation/batch_info_test.go new file mode 100644 index 000000000..416aafbdc --- /dev/null +++ b/node/derivation/batch_info_test.go @@ -0,0 +1,226 @@ +package derivation + +import ( + "crypto/rand" + "math/big" + "testing" + + "github.com/morph-l2/go-ethereum/common" + eth "github.com/morph-l2/go-ethereum/core/types" + "github.com/morph-l2/go-ethereum/crypto/kzg4844" + geth "github.com/morph-l2/go-ethereum/eth" + "github.com/stretchr/testify/require" + + commonbatch "morph-l2/common/batch" + "morph-l2/common/blob" + "morph-l2/node/types" + "morph-l2/node/zstd" +) + +// buildBlockContexts returns the concatenated 60-byte encoding of `count` +// sequential, tx-empty blocks starting at `startBlock`. The produced layout +// matches what tx-submitter places at the head of a V1/V2 batch payload. +func buildBlockContexts(startBlock uint64, count int) []byte { + buf := make([]byte, 0, count*60) + for i := 0; i < count; i++ { + wb := &types.WrappedBlock{ + Number: startBlock + uint64(i), + Timestamp: 1_700_000_000 + uint64(i)*6, + BaseFee: big.NewInt(1_000_000_000), + GasLimit: 30_000_000, + } + buf = append(buf, wb.BlockContextBytes(0, 0)...) + } + return buf +} + +// buildV1ParentHeader encodes a minimal V1 parent header whose LastBlockNumber +// is one below `nextStartBlock`, so that ParseBatch can derive blockCount via +// the (batch.LastBlockNumber - parent.LastBlockNumber) path. +func buildV1ParentHeader(parentIndex, nextStartBlock uint64) []byte { + return commonbatch.BatchHeaderV1{ + BatchHeaderV0: commonbatch.BatchHeaderV0{ + BatchIndex: parentIndex, + BlobVersionedHash: blob.EmptyVersionedHash, + }, + LastBlockNumber: nextStartBlock - 1, + }.Bytes() +} + +// splitCompressedIntoBlobs mirrors the tx-submitter strategy of compressing +// the entire payload as a single zstd stream and then slicing the compressed +// bytes into MaxBlobBytesSize chunks, each packed into a canonical blob. +func splitCompressedIntoBlobs(t *testing.T, compressed []byte) []kzg4844.Blob { + t.Helper() + var blobs []kzg4844.Blob + for offset := 0; offset < len(compressed); offset += commonbatch.MaxBlobBytesSize { + end := offset + commonbatch.MaxBlobBytesSize + if end > len(compressed) { + end = len(compressed) + } + blob, err := commonbatch.MakeBlobCanonical(compressed[offset:end]) + require.NoError(t, err) + blobs = append(blobs, *blob) + } + if len(blobs) == 0 { + // An empty payload still requires at least one (empty) blob so that + // downstream consumers can iterate. Production submitters never emit + // an empty batch, but the helper should remain total. + blobs = append(blobs, kzg4844.Blob{}) + } + return blobs +} + +// TestParseBatchSingleBlob covers the backward-compatible path where a V1 +// batch fits in a single blob. It guards against regressions in the recent +// "concatenate then decompress" refactor: the single-blob flow must still +// yield the same block contexts it did before multi-blob support landed. +func TestParseBatchSingleBlob(t *testing.T) { + const ( + parentIndex = 99 + startBlock = 1_000 + blockCount = 5 + ) + + blockCtx := buildBlockContexts(startBlock, blockCount) + payload := append(blockCtx, 0x00) // empty tx stream terminator + + compressed, err := zstd.CompressBatchBytes(payload) + require.NoError(t, err) + require.LessOrEqual(t, len(compressed), commonbatch.MaxBlobBytesSize, + "single-blob test expects compressed payload to fit in one blob") + + blobs := splitCompressedIntoBlobs(t, compressed) + require.Len(t, blobs, 1) + + batch := geth.RPCRollupBatch{ + Version: 1, + ParentBatchHeader: buildV1ParentHeader(parentIndex, startBlock), + LastBlockNumber: startBlock + blockCount - 1, + Sidecar: eth.BlobTxSidecar{Blobs: blobs}, + } + + var bi BatchInfo + require.NoError(t, bi.ParseBatch(batch)) + + require.EqualValues(t, parentIndex+1, bi.batchIndex) + require.EqualValues(t, startBlock, bi.FirstBlockNumber()) + require.EqualValues(t, startBlock+blockCount-1, bi.LastBlockNumber()) + require.Len(t, bi.blockContexts, blockCount) + for i, bc := range bi.blockContexts { + require.EqualValues(t, uint64(startBlock+i), bc.Number, + "block %d number mismatch", i) + } +} + +// TestParseBatchMultiBlob is the core multi-blob regression: it forces the +// compressed payload to exceed a single blob's capacity and verifies that +// ParseBatch reconstructs the decompressed stream by concatenating all blob +// bodies before running zstd.Decompress. A naive per-blob decompression loop +// would fail on blob[1] since it is mid-zstd-frame data, so a successful +// parse here proves the concatenation path is wired correctly. +// +// Compression-resistant random bytes are appended after the block-context +// header (past the tx terminator) purely to inflate the compressed size; the +// tx decoder stops at the first 0x00 byte and trailing random bytes are never +// interpreted as transactions. +func TestParseBatchMultiBlob(t *testing.T) { + const ( + parentIndex = 123 + startBlock = 2_000 + blockCount = 8 + ) + + blockCtx := buildBlockContexts(startBlock, blockCount) + + // 1 byte tx terminator + ~1.2x blob capacity of incompressible noise to + // guarantee the zstd output straddles a blob boundary. + padLen := commonbatch.MaxBlobBytesSize + commonbatch.MaxBlobBytesSize/5 + pad := make([]byte, padLen) + _, err := rand.Read(pad) + require.NoError(t, err) + + payload := make([]byte, 0, len(blockCtx)+1+padLen) + payload = append(payload, blockCtx...) + payload = append(payload, 0x00) + payload = append(payload, pad...) + + compressed, err := zstd.CompressBatchBytes(payload) + require.NoError(t, err) + require.Greater(t, len(compressed), commonbatch.MaxBlobBytesSize, + "multi-blob test requires compressed payload to overflow a single blob") + + blobs := splitCompressedIntoBlobs(t, compressed) + require.GreaterOrEqual(t, len(blobs), 2, "expected at least 2 blobs for multi-blob path") + + batch := geth.RPCRollupBatch{ + Version: 2, + ParentBatchHeader: buildV1ParentHeader(parentIndex, startBlock), + LastBlockNumber: startBlock + blockCount - 1, + PrevStateRoot: common.BigToHash(big.NewInt(1)), + PostStateRoot: common.BigToHash(big.NewInt(2)), + WithdrawRoot: common.BigToHash(big.NewInt(3)), + Sidecar: eth.BlobTxSidecar{Blobs: blobs}, + } + + var bi BatchInfo + require.NoError(t, bi.ParseBatch(batch)) + + require.EqualValues(t, parentIndex+1, bi.batchIndex) + require.EqualValues(t, 2, bi.version) + require.EqualValues(t, startBlock, bi.FirstBlockNumber()) + require.EqualValues(t, startBlock+blockCount-1, bi.LastBlockNumber()) + require.Len(t, bi.blockContexts, blockCount) + for i, bc := range bi.blockContexts { + require.EqualValues(t, uint64(startBlock+i), bc.Number, + "block %d number mismatch", i) + require.EqualValues(t, 1_700_000_000+uint64(i)*6, bc.Timestamp, + "block %d timestamp mismatch", i) + } + require.EqualValues(t, batch.PostStateRoot, bi.root) + require.EqualValues(t, batch.WithdrawRoot, bi.withdrawalRoot) +} + +// TestParseBatchMultiBlobConcatDecompressInvariant directly exercises the +// low-level invariant that multi-blob ParseBatch relies on: the compressed +// stream can only be recovered by concatenating blob bodies in submission +// order and decompressing once. Per-blob decompression must fail on any +// non-initial blob, and reordering blobs must corrupt the decompressed +// output. Keeping this explicit protects the invariant even if ParseBatch is +// later refactored to hide the concatenation step. +func TestParseBatchMultiBlobConcatDecompressInvariant(t *testing.T) { + pad := make([]byte, commonbatch.MaxBlobBytesSize+commonbatch.MaxBlobBytesSize/5) + _, err := rand.Read(pad) + require.NoError(t, err) + + compressed, err := zstd.CompressBatchBytes(pad) + require.NoError(t, err) + require.Greater(t, len(compressed), commonbatch.MaxBlobBytesSize) + + blobs := splitCompressedIntoBlobs(t, compressed) + require.GreaterOrEqual(t, len(blobs), 2) + + // In-order concatenation round-trips. + var concat []byte + for i := range blobs { + body, err := commonbatch.RetrieveBlobBytes(&blobs[i]) + require.NoError(t, err) + concat = append(concat, body...) + } + decoded, err := zstd.DecompressBatchBytes(concat) + require.NoError(t, err) + require.Equal(t, pad, decoded) + + // Reversing blob order must corrupt the stream; decompression should + // either error or yield a different payload. + var reversed []byte + for i := len(blobs) - 1; i >= 0; i-- { + body, err := commonbatch.RetrieveBlobBytes(&blobs[i]) + require.NoError(t, err) + reversed = append(reversed, body...) + } + if out, err := zstd.DecompressBatchBytes(reversed); err == nil { + require.NotEqual(t, pad, out, + "reversed-blob decompression unexpectedly matched payload") + } +} diff --git a/node/derivation/beacon.go b/node/derivation/beacon.go index 50bd0802a..ac663241f 100644 --- a/node/derivation/beacon.go +++ b/node/derivation/beacon.go @@ -159,8 +159,29 @@ func KZGToVersionedHash(commitment kzg4844.Commitment) (out common.Hash) { return out } -func VerifyBlobProof(blob *Blob, commitment kzg4844.Commitment, proof kzg4844.Proof) error { - return kzg4844.VerifyBlobProof(blob.KZGBlob(), commitment, proof) +// verifyBlob authenticates a blob against the L1-signed versioned blob hash +// by recomputing the KZG commitment locally and checking +// +// KZGToVersionedHash(BlobToCommitment(blob)) == expectedHash +// +// We deliberately do NOT verify a beacon-supplied kzg_proof. After +// EIP-7594 (PeerDAS / Osaka) the beacon /eth/v1/beacon/blob_sidecars +// endpoint's kzg_proof field is no longer guaranteed to be a legacy +// single-blob proof across forks/clients, and the new +// /eth/v1/beacon/blobs endpoint does not return proofs at all. The +// commitment round-trip gives us the same security property +// (blob bytes -> commitment -> versioned hash matches the L1-signed +// hash) without depending on those fields. +func verifyBlob(blob *Blob, expectedHash common.Hash) error { + commitment, err := kzg4844.BlobToCommitment(blob.KZGBlob()) + if err != nil { + return fmt.Errorf("cannot compute KZG commitment for blob: %w", err) + } + got := KZGToVersionedHash(commitment) + if got != expectedHash { + return fmt.Errorf("recomputed blob hash %s does not match expected %s", got.Hex(), expectedHash.Hex()) + } + return nil } // dataAndHashesFromTxs extracts calldata and datahashes from the input transactions and returns them. It diff --git a/node/derivation/derivation.go b/node/derivation/derivation.go index d5bf58681..05c4606b6 100644 --- a/node/derivation/derivation.go +++ b/node/derivation/derivation.go @@ -338,49 +338,64 @@ func (d *Derivation) fetchRollupDataByTxHash(txHash common.Hash, blockNumber uin return nil, fmt.Errorf("failed to get blobs, continuing processing:%v", err) } if len(blobSidecars) > 0 { - // Create blob sidecar - var blobTxSidecar eth.BlobTxSidecar - matchedCount := 0 - - // Match blobs + // Index beacon sidecars by their KZG-derived versioned hash so we + // can assemble the local sidecar in the exact order the L1 tx + // declared its blobs. Multi-blob batches are decoded by + // concatenating blob bodies in tx order; any reordering here + // would corrupt the resulting zstd stream. The map key is + // derived from the beacon-supplied commitment; verifyBlob below + // re-derives the same hash from the actual blob bytes, so a + // malicious beacon cannot forge an entry by lying about the + // commitment. + byHash := make(map[common.Hash]*BlobSidecar, len(blobSidecars)) for _, sidecar := range blobSidecars { var commitment kzg4844.Commitment copy(commitment[:], sidecar.KZGCommitment[:]) - versionedHash := KZGToVersionedHash(commitment) - - for _, expectedHash := range blobHashes { - if bytes.Equal(versionedHash[:], expectedHash[:]) { - matchedCount++ - d.logger.Info("Found matching blob", "index", sidecar.Index, "hash", versionedHash.Hex()) - - // Decode and process blob data - var blob Blob - b, err := hexutil.Decode(sidecar.Blob) - if err != nil { - d.logger.Error("Failed to decode blob data", "error", err) - continue - } - copy(blob[:], b) - - // Verify blob - //if err := VerifyBlobProof(&blob, commitment, kzg4844.Proof(sidecar.KZGProof)); err != nil { - // d.logger.Error("Blob verification failed", "error", err) - // continue - //} - - // Add to sidecar - blobTxSidecar.Blobs = append(blobTxSidecar.Blobs, *blob.KZGBlob()) - blobTxSidecar.Commitments = append(blobTxSidecar.Commitments, commitment) - blobTxSidecar.Proofs = append(blobTxSidecar.Proofs, kzg4844.Proof(sidecar.KZGProof)) - break - } - } + byHash[KZGToVersionedHash(commitment)] = sidecar } - d.logger.Info("Blob matching results", "matched", matchedCount, "expected", len(blobHashes)) - if matchedCount == 0 { - return nil, fmt.Errorf("no matching versionedHash was found") + // Downstream (ParseBatch) only consumes Sidecar.Blobs and + // Sidecar.Commitments; Proofs is intentionally left empty to + // avoid an extra ~O(n) KZG op per blob per batch on every + // sync. If a future consumer needs Proofs, compute them + // lazily there or call kzg4844.ComputeBlobProof here. + var blobTxSidecar eth.BlobTxSidecar + for i, expectedHash := range blobHashes { + sidecar, ok := byHash[expectedHash] + if !ok { + return nil, fmt.Errorf("blob %d (hash=%s) not found in beacon sidecars", i, expectedHash.Hex()) + } + + b, err := hexutil.Decode(sidecar.Blob) + if err != nil { + return nil, fmt.Errorf("failed to decode blob %d: %w", i, err) + } + // Reject malformed beacon responses up front. copy(blob[:], b) + // silently: + // - zero-pads when len(b) < BlobSize (tail of the + // zero-initialized array stays zero) + // - truncates when len(b) > BlobSize (extra bytes dropped) + // Either case would otherwise surface later as a confusing + // blob-hash mismatch instead of a clear length error. + if len(b) != BlobSize { + return nil, fmt.Errorf("blob %d: unexpected length %d (want %d, hash=%s)", i, len(b), BlobSize, expectedHash.Hex()) + } + var blob Blob + copy(blob[:], b) + + if err := verifyBlob(&blob, expectedHash); err != nil { + return nil, fmt.Errorf("blob %d: %w", i, err) + } + + var commitment kzg4844.Commitment + copy(commitment[:], sidecar.KZGCommitment[:]) + + d.logger.Info("Matched blob", "txOrder", i, "beaconIndex", sidecar.Index, "hash", expectedHash.Hex()) + blobTxSidecar.Blobs = append(blobTxSidecar.Blobs, *blob.KZGBlob()) + blobTxSidecar.Commitments = append(blobTxSidecar.Commitments, commitment) } + + d.logger.Info("Blob matching results", "matched", len(blobTxSidecar.Blobs), "expected", len(blobHashes)) batch.Sidecar = blobTxSidecar } else { return nil, fmt.Errorf("not matched blob,txHash:%v,blockNumber:%v", txHash, blockNumber) diff --git a/node/types/batch_header.go b/node/types/batch_header.go index 1616d8962..c9dba67ca 100644 --- a/node/types/batch_header.go +++ b/node/types/batch_header.go @@ -1,5 +1,21 @@ package types +// DEPRECATED: this file is a duplicate of morph-l2/common/batch's +// batch_header.go and is kept alive only because tx-submitter/utils/utils.go +// still imports BatchHeaderBytes from here. node/types cannot be turned into +// a thin shim re-exporting common/batch because that would close an import +// cycle: common/batch already depends on tx-submitter/db (via BatchCache), +// which depends on tx-submitter/utils, which would then depend back on +// common/batch. +// +// Cleanup path (out of scope for this PR; should be done by the tx-submitter +// owners alongside moving BatchCache out of common/batch): +// 1. Move common/batch/batch_cache.go, batch_storage.go, batch_query.go +// down to tx-submitter/batch/, so common/batch becomes a true leaf +// (depends on nothing under tx-submitter/). +// 2. Switch tx-submitter/utils/utils.go to import morph-l2/common/batch. +// 3. Delete this file. + import ( "encoding/binary" "errors" @@ -15,9 +31,15 @@ type ( const ( expectedLengthV0 = 249 expectedLengthV1 = 257 + // V2 reuses the V1 wire format (257 bytes). The only semantic + // difference is that the 32-byte field at offset 57 stores + // keccak256(blobhash(0) || ... || blobhash(N-1)) instead of a + // single blob versioned hash. + expectedLengthV2 = 257 BatchHeaderVersion0 = 0 BatchHeaderVersion1 = 1 + BatchHeaderVersion2 = 2 ) var ( @@ -41,6 +63,10 @@ func (b BatchHeaderBytes) validate() error { if len(b) != expectedLengthV1 { return ErrInvalidBatchHeaderLength } + case BatchHeaderVersion2: + if len(b) != expectedLengthV2 { + return ErrInvalidBatchHeaderLength + } default: return ErrInvalidBatchHeaderVersion } @@ -93,10 +119,32 @@ func (b BatchHeaderBytes) DataHash() (common.Hash, error) { return common.BytesToHash(b[25:57]), nil } +// BlobVersionedHash returns the EIP-4844 blob versioned hash recorded at +// offset [57:89]. This is only meaningful for V0/V1 batches, where the field +// holds the single blob's versioned hash. For V2 batches the same offset +// holds an aggregated hash; callers must use BlobHashesHash instead. func (b BatchHeaderBytes) BlobVersionedHash() (common.Hash, error) { if err := b.validate(); err != nil { return common.Hash{}, err } + version, _ := b.Version() + if version >= BatchHeaderVersion2 { + return common.Hash{}, errors.New("BlobVersionedHash is not available for V2+; use BlobHashesHash") + } + return common.BytesToHash(b[57:89]), nil +} + +// BlobHashesHash returns the aggregated blob hash recorded at offset [57:89] +// for V2+ batches, defined as keccak256(blobhash(0) || ... || blobhash(N-1)). +// V0/V1 batches do not aggregate and will return an error. +func (b BatchHeaderBytes) BlobHashesHash() (common.Hash, error) { + if err := b.validate(); err != nil { + return common.Hash{}, err + } + version, _ := b.Version() + if version < BatchHeaderVersion2 { + return common.Hash{}, errors.New("BlobHashesHash is only available for V2+; use BlobVersionedHash") + } return common.BytesToHash(b[57:89]), nil } diff --git a/ops/docker/docker-compose-4nodes.yml b/ops/docker/docker-compose-4nodes.yml index 83d4f8b9e..8a97f0e09 100644 --- a/ops/docker/docker-compose-4nodes.yml +++ b/ops/docker/docker-compose-4nodes.yml @@ -482,7 +482,7 @@ services: - TX_SUBMITTER_MIN_BLOCK=50 - TX_SUBMITTER_FINALIZE=true - TX_SUBMITTER_MAX_FINALIZE_NUM=100 - - TX_SUBMITTER_PRIORITY_ROLLUP=false + - TX_SUBMITTER_PRIORITY_ROLLUP=true - TX_SUBMITTER_SEAL_BATCH=true - TX_SUBMITTER_METRICS_SERVER_ENABLE=false - TX_SUBMITTER_METRICS_HOSTNAME=0.0.0.0 @@ -494,9 +494,12 @@ services: - TX_SUBMITTER_LOG_COMPRESS=true - TX_SUBMITTER_L1_STAKING_ADDRESS=${MORPH_L1STAKING:-0x5fc8d32690cc91d4c39d9d3abcbd16989f875707} - TX_SUBMITTER_L1_STAKING_DEPLOYED_BLOCKNUM=0 + - TX_SUBMITTER_SEAL_BATCH=true + - TX_SUBMITTER_BATCH_V2_UPGRADE_TIME=1777533291 tx-submitter-1: container_name: tx-submitter-1 + profiles: ["multi-submitter"] depends_on: node-1: condition: service_started @@ -540,6 +543,7 @@ services: tx-submitter-2: container_name: tx-submitter-2 + profiles: ["multi-submitter"] depends_on: node-2: condition: service_started @@ -583,6 +587,7 @@ services: tx-submitter-3: container_name: tx-submitter-3 + profiles: ["multi-submitter"] depends_on: node-3: condition: service_started diff --git a/ops/docker/layer1/configs/values.env.template b/ops/docker/layer1/configs/values.env.template index 52a3ed168..6adca9511 100644 --- a/ops/docker/layer1/configs/values.env.template +++ b/ops/docker/layer1/configs/values.env.template @@ -48,8 +48,13 @@ export VIEW_FREEZE_CUTOFF_BPS=7500 export INCLUSION_LIST_SUBMISSION_DUE_BPS=6667 export PROPOSER_INCLUSION_LIST_CUTOFF_BPS=9167 export DATA_COLUMN_SIDECAR_SUBNET_COUNT=128 -export SAMPLES_PER_SLOT=8 -export CUSTODY_REQUIREMENT=4 +# Single-node devnet: every node IS the entire network, so it must +# custody all 128 columns and sample all 128 each slot. Without this, +# only CUSTODY_REQUIREMENT (default 4) columns are persisted, which is +# never enough to reconstruct blobs (need 64/128) and any historical +# blob retrieval (e.g. validator re-deriving from L1 genesis) fails. +export SAMPLES_PER_SLOT=128 +export CUSTODY_REQUIREMENT=128 export MAX_BLOBS_PER_BLOCK_ELECTRA=9 export TARGET_BLOBS_PER_BLOCK_ELECTRA=6 export MAX_REQUEST_BLOCKS_DENEB=128 @@ -81,5 +86,9 @@ export BPO_5_EPOCH=18446744073709551615 export BPO_5_MAX_BLOBS=0 export BPO_5_TARGET_BLOBS=0 export BPO_5_BASE_FEE_UPDATE_FRACTION=0 -export MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS=4096 +# Bumped from spec default 4096 (~27h on a 3s-slot/8-slot-per-epoch +# minimal preset) to ~30 days, so a freshly reset validator can always +# re-derive from L1 genesis without hitting "0 data columns found" +# pruning errors. 110000 epochs * 24s/epoch ≈ 30.5 days. +export MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS=110000 export MIN_EPOCHS_FOR_BLOCK_REQUESTS=33024 diff --git a/ops/l2-genesis/deploy-config/devnet-deploy-config.json b/ops/l2-genesis/deploy-config/devnet-deploy-config.json index 46923a4b4..7b8200198 100644 --- a/ops/l2-genesis/deploy-config/devnet-deploy-config.json +++ b/ops/l2-genesis/deploy-config/devnet-deploy-config.json @@ -15,7 +15,7 @@ "gasPriceOracleScalar": 1000000000, "gasPriceOracleOwner": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "govVotingDuration": 1000, - "govBatchBlockInterval": 20, + "govBatchBlockInterval": 200, "govBatchTimeout": 600, "govRollupEpoch": 100, "recordOracleAddress": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", diff --git a/oracle/oracle/batch.go b/oracle/oracle/batch.go index 8e1eb9c23..df61159a6 100644 --- a/oracle/oracle/batch.go +++ b/oracle/oracle/batch.go @@ -9,8 +9,8 @@ import ( "time" "morph-l2/bindings/bindings" + commonbatch "morph-l2/common/batch" "morph-l2/node/derivation" - nodetypes "morph-l2/node/types" "morph-l2/oracle/backoff" "github.com/morph-l2/go-ethereum/accounts/abi/bind" @@ -163,7 +163,7 @@ func (o *Oracle) getBatchSubmissionByLogs(rLogs []types.Log, recordBatchSubmissi PostStateRoot: common.BytesToHash(rollupBatchData.PostStateRoot[:]), WithdrawRoot: common.BytesToHash(rollupBatchData.WithdrawalRoot[:]), } - parentBatchHeader := nodetypes.BatchHeaderBytes(batch.ParentBatchHeader) + parentBatchHeader := commonbatch.BatchHeaderBytes(batch.ParentBatchHeader) parentVersion, err := parentBatchHeader.Version() if err != nil { return fmt.Errorf("decode parent batch version error:%v", err) diff --git a/prover/Cargo.lock b/prover/Cargo.lock index bd4bc850a..9651be8bc 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -4344,8 +4344,8 @@ dependencies = [ [[package]] name = "morph-chainspec" -version = "0.1.0" -source = "git+https://github.com/morph-l2/morph-reth.git?branch=release/0.1.x#af311e3f0d7f1f1e56ddac780d40e96526b193e2" +version = "0.2.0" +source = "git+https://github.com/morph-l2/morph-reth.git?tag=v0.2.0#7d75856a219f5e86916b79a718d2b846b0149a43" dependencies = [ "alloy-chains", "alloy-consensus", @@ -4359,15 +4359,15 @@ dependencies = [ "morph-primitives", "reth-chainspec", "reth-network-peers", - "reth-primitives-traits", + "reth-primitives-traits 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", "serde", "serde_json", ] [[package]] name = "morph-primitives" -version = "0.1.0" -source = "git+https://github.com/morph-l2/morph-reth.git?branch=release/0.1.x#af311e3f0d7f1f1e56ddac780d40e96526b193e2" +version = "0.2.0" +source = "git+https://github.com/morph-l2/morph-reth.git?tag=v0.2.0#7d75856a219f5e86916b79a718d2b846b0149a43" dependencies = [ "alloy-consensus", "alloy-eips", @@ -4375,7 +4375,7 @@ dependencies = [ "alloy-rlp", "alloy-serde", "reth-ethereum-primitives", - "reth-primitives-traits", + "reth-primitives-traits 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", "serde", ] @@ -4404,14 +4404,13 @@ dependencies = [ [[package]] name = "morph-revm" -version = "0.1.0" -source = "git+https://github.com/morph-l2/morph-reth.git?branch=release/0.1.x#af311e3f0d7f1f1e56ddac780d40e96526b193e2" +version = "0.2.0" +source = "git+https://github.com/morph-l2/morph-reth.git?tag=v0.2.0#7d75856a219f5e86916b79a718d2b846b0149a43" dependencies = [ "alloy-consensus", "alloy-eips", "alloy-evm", "alloy-primitives", - "alloy-rlp", "alloy-sol-types", "auto_impl", "derive_more 2.1.0", @@ -5856,8 +5855,8 @@ dependencies = [ "log", "prover-mpt", "prover-primitives", - "reth-primitives-traits", - "reth-storage-errors", + "reth-primitives-traits 1.10.0 (git+https://github.com/paradigmxyz/reth?tag=v1.10.0)", + "reth-storage-errors 1.10.0 (git+https://github.com/paradigmxyz/reth?tag=v1.10.0)", "reth-trie", "revm", "serde", @@ -6237,7 +6236,7 @@ dependencies = [ [[package]] name = "reth-chainspec" version = "1.10.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.0#b25f32a977b489f9b84254c7811a2a5a25a81369" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" dependencies = [ "alloy-chains", "alloy-consensus", @@ -6250,14 +6249,14 @@ dependencies = [ "derive_more 2.1.0", "reth-ethereum-forks", "reth-network-peers", - "reth-primitives-traits", + "reth-primitives-traits 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", "serde_json", ] [[package]] name = "reth-codecs" version = "1.10.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.0#b25f32a977b489f9b84254c7811a2a5a25a81369" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" dependencies = [ "alloy-consensus", "alloy-eips", @@ -6275,7 +6274,7 @@ dependencies = [ [[package]] name = "reth-codecs-derive" version = "1.10.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.0#b25f32a977b489f9b84254c7811a2a5a25a81369" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" dependencies = [ "proc-macro2", "quote", @@ -6285,19 +6284,19 @@ dependencies = [ [[package]] name = "reth-db-models" version = "1.10.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.0#b25f32a977b489f9b84254c7811a2a5a25a81369" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" dependencies = [ "alloy-eips", "alloy-primitives", "bytes", - "reth-primitives-traits", + "reth-primitives-traits 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", "serde", ] [[package]] name = "reth-ethereum-forks" version = "1.10.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.0#b25f32a977b489f9b84254c7811a2a5a25a81369" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" dependencies = [ "alloy-eip2124", "alloy-hardforks", @@ -6310,7 +6309,7 @@ dependencies = [ [[package]] name = "reth-ethereum-primitives" version = "1.10.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.0#b25f32a977b489f9b84254c7811a2a5a25a81369" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" dependencies = [ "alloy-consensus", "alloy-eips", @@ -6319,7 +6318,7 @@ dependencies = [ "alloy-rpc-types-eth", "alloy-serde", "reth-codecs", - "reth-primitives-traits", + "reth-primitives-traits 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", "reth-zstd-compressors", "serde", "serde_with", @@ -6328,7 +6327,7 @@ dependencies = [ [[package]] name = "reth-evm" version = "1.10.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.0#b25f32a977b489f9b84254c7811a2a5a25a81369" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" dependencies = [ "alloy-consensus", "alloy-eips", @@ -6338,12 +6337,12 @@ dependencies = [ "derive_more 2.1.0", "futures-util", "rayon", - "reth-execution-errors", + "reth-execution-errors 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", "reth-execution-types", - "reth-primitives-traits", + "reth-primitives-traits 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", "reth-storage-api", - "reth-storage-errors", - "reth-trie-common", + "reth-storage-errors 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", + "reth-trie-common 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", "revm", ] @@ -6356,14 +6355,27 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "nybbles", - "reth-storage-errors", + "reth-storage-errors 1.10.0 (git+https://github.com/paradigmxyz/reth?tag=v1.10.0)", + "thiserror 2.0.17", +] + +[[package]] +name = "reth-execution-errors" +version = "1.10.0" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" +dependencies = [ + "alloy-evm", + "alloy-primitives", + "alloy-rlp", + "nybbles", + "reth-storage-errors 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", "thiserror 2.0.17", ] [[package]] name = "reth-execution-types" version = "1.10.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.0#b25f32a977b489f9b84254c7811a2a5a25a81369" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" dependencies = [ "alloy-consensus", "alloy-eips", @@ -6371,8 +6383,8 @@ dependencies = [ "alloy-primitives", "derive_more 2.1.0", "reth-ethereum-primitives", - "reth-primitives-traits", - "reth-trie-common", + "reth-primitives-traits 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", + "reth-trie-common 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", "revm", "serde", "serde_with", @@ -6381,7 +6393,7 @@ dependencies = [ [[package]] name = "reth-network-peers" version = "1.10.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.0#b25f32a977b489f9b84254c7811a2a5a25a81369" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -6395,6 +6407,27 @@ dependencies = [ name = "reth-primitives-traits" version = "1.10.0" source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.0#b25f32a977b489f9b84254c7811a2a5a25a81369" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-genesis", + "alloy-primitives", + "alloy-rlp", + "alloy-trie", + "auto_impl", + "bytes", + "derive_more 2.1.0", + "once_cell", + "revm-bytecode", + "revm-primitives", + "revm-state", + "thiserror 2.0.17", +] + +[[package]] +name = "reth-primitives-traits" +version = "1.10.0" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" dependencies = [ "alloy-consensus", "alloy-eips", @@ -6422,6 +6455,17 @@ dependencies = [ name = "reth-prune-types" version = "1.10.0" source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.0#b25f32a977b489f9b84254c7811a2a5a25a81369" +dependencies = [ + "alloy-primitives", + "derive_more 2.1.0", + "strum", + "thiserror 2.0.17", +] + +[[package]] +name = "reth-prune-types" +version = "1.10.0" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" dependencies = [ "alloy-primitives", "derive_more 2.1.0", @@ -6434,10 +6478,19 @@ dependencies = [ name = "reth-stages-types" version = "1.10.0" source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.0#b25f32a977b489f9b84254c7811a2a5a25a81369" +dependencies = [ + "alloy-primitives", + "reth-trie-common 1.10.0 (git+https://github.com/paradigmxyz/reth?tag=v1.10.0)", +] + +[[package]] +name = "reth-stages-types" +version = "1.10.0" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" dependencies = [ "alloy-primitives", "bytes", - "reth-trie-common", + "reth-trie-common 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", "serde", ] @@ -6453,10 +6506,22 @@ dependencies = [ "strum", ] +[[package]] +name = "reth-static-file-types" +version = "1.10.0" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" +dependencies = [ + "alloy-primitives", + "derive_more 2.1.0", + "fixed-map", + "serde", + "strum", +] + [[package]] name = "reth-storage-api" version = "1.10.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.0#b25f32a977b489f9b84254c7811a2a5a25a81369" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" dependencies = [ "alloy-consensus", "alloy-eips", @@ -6467,11 +6532,11 @@ dependencies = [ "reth-db-models", "reth-ethereum-primitives", "reth-execution-types", - "reth-primitives-traits", - "reth-prune-types", - "reth-stages-types", - "reth-storage-errors", - "reth-trie-common", + "reth-primitives-traits 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", + "reth-prune-types 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", + "reth-stages-types 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", + "reth-storage-errors 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", + "reth-trie-common 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", "revm-database", "serde_json", ] @@ -6485,9 +6550,25 @@ dependencies = [ "alloy-primitives", "alloy-rlp", "derive_more 2.1.0", - "reth-primitives-traits", - "reth-prune-types", - "reth-static-file-types", + "reth-primitives-traits 1.10.0 (git+https://github.com/paradigmxyz/reth?tag=v1.10.0)", + "reth-prune-types 1.10.0 (git+https://github.com/paradigmxyz/reth?tag=v1.10.0)", + "reth-static-file-types 1.10.0 (git+https://github.com/paradigmxyz/reth?tag=v1.10.0)", + "revm-database-interface", + "thiserror 2.0.17", +] + +[[package]] +name = "reth-storage-errors" +version = "1.10.0" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "derive_more 2.1.0", + "reth-primitives-traits 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", + "reth-prune-types 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", + "reth-static-file-types 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", "revm-database-interface", "thiserror 2.0.17", ] @@ -6504,11 +6585,11 @@ dependencies = [ "alloy-trie", "auto_impl", "itertools 0.14.0", - "reth-execution-errors", - "reth-primitives-traits", - "reth-stages-types", - "reth-storage-errors", - "reth-trie-common", + "reth-execution-errors 1.10.0 (git+https://github.com/paradigmxyz/reth?tag=v1.10.0)", + "reth-primitives-traits 1.10.0 (git+https://github.com/paradigmxyz/reth?tag=v1.10.0)", + "reth-stages-types 1.10.0 (git+https://github.com/paradigmxyz/reth?tag=v1.10.0)", + "reth-storage-errors 1.10.0 (git+https://github.com/paradigmxyz/reth?tag=v1.10.0)", + "reth-trie-common 1.10.0 (git+https://github.com/paradigmxyz/reth?tag=v1.10.0)", "reth-trie-sparse", "revm-database", "tracing", @@ -6518,6 +6599,23 @@ dependencies = [ name = "reth-trie-common" version = "1.10.0" source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.0#b25f32a977b489f9b84254c7811a2a5a25a81369" +dependencies = [ + "alloy-consensus", + "alloy-primitives", + "alloy-rlp", + "alloy-trie", + "derive_more 2.1.0", + "itertools 0.14.0", + "nybbles", + "rayon", + "reth-primitives-traits 1.10.0 (git+https://github.com/paradigmxyz/reth?tag=v1.10.0)", + "revm-database", +] + +[[package]] +name = "reth-trie-common" +version = "1.10.0" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -6530,8 +6628,7 @@ dependencies = [ "derive_more 2.1.0", "itertools 0.14.0", "nybbles", - "rayon", - "reth-primitives-traits", + "reth-primitives-traits 1.10.0 (git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e)", "revm-database", "serde", "serde_with", @@ -6546,9 +6643,9 @@ dependencies = [ "alloy-rlp", "alloy-trie", "auto_impl", - "reth-execution-errors", - "reth-primitives-traits", - "reth-trie-common", + "reth-execution-errors 1.10.0 (git+https://github.com/paradigmxyz/reth?tag=v1.10.0)", + "reth-primitives-traits 1.10.0 (git+https://github.com/paradigmxyz/reth?tag=v1.10.0)", + "reth-trie-common 1.10.0 (git+https://github.com/paradigmxyz/reth?tag=v1.10.0)", "smallvec", "tracing", ] @@ -6556,7 +6653,7 @@ dependencies = [ [[package]] name = "reth-zstd-compressors" version = "1.10.0" -source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.0#b25f32a977b489f9b84254c7811a2a5a25a81369" +source = "git+https://github.com/morph-l2/reth?rev=1dd722773844d1a3c50a691dc09f6cdf8e6bd00e#1dd722773844d1a3c50a691dc09f6cdf8e6bd00e" dependencies = [ "zstd", ] diff --git a/prover/Cargo.toml b/prover/Cargo.toml index bb1da3bf4..5795ea7fd 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -19,7 +19,7 @@ resolver = "2" [workspace.package] version = "2.0.0" edition = "2021" -rust-version = "1.75" +rust-version = "1.91.0" authors = ["developers"] license = "MIT OR Apache-2.0" homepage = "https://github.com/morph-l2/morph/tree/main/prover" @@ -120,9 +120,9 @@ revm = { version = "33.1.0", features = [ reth-primitives-traits = { git = "https://github.com/paradigmxyz/reth", tag = "v1.10.0", default-features = false } reth-storage-errors = { git = "https://github.com/paradigmxyz/reth", tag = "v1.10.0", default-features = false } reth-trie = { git = "https://github.com/paradigmxyz/reth", tag = "v1.10.0", default-features = false } -morph-revm = { git = "https://github.com/morph-l2/morph-reth.git", branch = "release/0.1.x" } -morph-primitives = { git = "https://github.com/morph-l2/morph-reth.git", branch = "release/0.1.x" } -morph-chainspec = { git = "https://github.com/morph-l2/morph-reth.git", branch = "release/0.1.x" } +morph-revm = { git = "https://github.com/morph-l2/morph-reth.git", tag = "v0.2.0" } +morph-primitives = { git = "https://github.com/morph-l2/morph-reth.git", tag = "v0.2.0" } +morph-chainspec = { git = "https://github.com/morph-l2/morph-reth.git", tag = "v0.2.0" } # ZK / SP1 diff --git a/prover/README.md b/prover/README.md index c3099f839..8c463ea25 100644 --- a/prover/README.md +++ b/prover/README.md @@ -23,6 +23,7 @@ cargo prove build ``` or use docker(reproducible compilation): ```sh +cd bin/client cargo prove build --docker --tag v6.2.0 ``` diff --git a/prover/bin/challenge/Cargo.lock b/prover/bin/challenge/Cargo.lock index 21e66f02f..5067ebf7e 100644 --- a/prover/bin/challenge/Cargo.lock +++ b/prover/bin/challenge/Cargo.lock @@ -122,7 +122,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.117", ] [[package]] @@ -688,9 +688,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.9" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", ] @@ -1018,7 +1018,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn 2.0.39", + "syn 2.0.117", "toml", "walkdir", ] @@ -1036,7 +1036,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.39", + "syn 2.0.117", ] [[package]] @@ -1062,7 +1062,7 @@ dependencies = [ "serde", "serde_json", "strum", - "syn 2.0.39", + "syn 2.0.117", "tempfile", "thiserror", "tiny-keccak", @@ -1365,7 +1365,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.117", ] [[package]] @@ -2051,6 +2051,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "num-conv" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" + [[package]] name = "num-integer" version = "0.1.45" @@ -2110,7 +2116,7 @@ dependencies = [ "proc-macro-crate 2.0.0", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.117", ] [[package]] @@ -2321,7 +2327,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.117", ] [[package]] @@ -2359,7 +2365,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.117", ] [[package]] @@ -2426,7 +2432,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" dependencies = [ "proc-macro2", - "syn 2.0.39", + "syn 2.0.117", ] [[package]] @@ -2488,9 +2494,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -2549,9 +2555,9 @@ checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" [[package]] name = "quote" -version = "1.0.33" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -2997,22 +3003,32 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.192" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.117", ] [[package]] @@ -3225,7 +3241,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.39", + "syn 2.0.117", ] [[package]] @@ -3267,9 +3283,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -3359,35 +3375,37 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.117", ] [[package]] name = "time" -version = "0.3.30" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ + "num-conv", "time-core", ] @@ -3442,7 +3460,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.117", ] [[package]] @@ -3627,7 +3645,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.117", ] [[package]] @@ -3835,7 +3853,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.117", "wasm-bindgen-shared", ] @@ -3869,7 +3887,7 @@ checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.117", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/prover/bin/challenge/rust-toolchain b/prover/bin/challenge/rust-toolchain deleted file mode 100644 index f1d81c421..000000000 --- a/prover/bin/challenge/rust-toolchain +++ /dev/null @@ -1 +0,0 @@ -nightly-2023-12-03 \ No newline at end of file diff --git a/prover/bin/challenge/src/handler.rs b/prover/bin/challenge/src/handler.rs index 44763205f..36eac035f 100644 --- a/prover/bin/challenge/src/handler.rs +++ b/prover/bin/challenge/src/handler.rs @@ -413,7 +413,7 @@ struct BatchInfo { l1_message_popped: u64, total_l1_message_popped: u64, data_hash: [u8; 32], - blob_versioned_hash: [u8; 32], + blob_hashes: Vec<[u8; 32]>, prev_state_root: [u8; 32], post_state_root: [u8; 32], withdrawal_root: [u8; 32], @@ -490,8 +490,11 @@ impl BatchInfo { log::debug!("batch_header_ex len: {:#?}", batch_header_ex.len()); self.data_hash = batch_header_ex.get(0..32).unwrap_or_default().try_into().unwrap_or_default(); - self.blob_versioned_hash = batch_header_ex.get(32..64).unwrap_or_default().try_into().unwrap_or_default(); self.sequencer_set_verify_hash = batch_header_ex.get(64..96).unwrap_or_default().try_into().unwrap_or_default(); + + // All versions: single hash at [32..64] (aggregated for V2, versioned for V0/V1) + let hash: [u8; 32] = batch_header_ex.get(32..64).unwrap_or_default().try_into().unwrap_or_default(); + self.blob_hashes = vec![hash]; self } @@ -502,7 +505,8 @@ impl BatchInfo { batch_header.extend_from_slice(&self.l1_message_popped.to_be_bytes()); batch_header.extend_from_slice(&self.total_l1_message_popped.to_be_bytes()); batch_header.extend_from_slice(&self.data_hash); - batch_header.extend_from_slice(&self.blob_versioned_hash); + // blob hash at offset 57 (same position for all versions; aggregated for V2) + batch_header.extend_from_slice(self.blob_hashes.first().unwrap_or(&[0u8; 32])); batch_header.extend_from_slice(&self.prev_state_root); batch_header.extend_from_slice(&self.post_state_root); batch_header.extend_from_slice(&self.withdrawal_root); diff --git a/prover/bin/client/elf/verifier-client b/prover/bin/client/elf/verifier-client index bad44d5e6..0e0a8f434 100755 Binary files a/prover/bin/client/elf/verifier-client and b/prover/bin/client/elf/verifier-client differ diff --git a/prover/bin/host/src/execute.rs b/prover/bin/host/src/execute.rs index ccc3b1692..67ca4c210 100644 --- a/prover/bin/host/src/execute.rs +++ b/prover/bin/host/src/execute.rs @@ -1,7 +1,7 @@ use alloy_provider::DynProvider; use prover_executor_client::{types::input::ExecutorInput, EVMVerifier}; use prover_executor_host::{ - blob::{get_blob_info_from_blocks, get_blob_info_from_traces}, + blob::{get_blob_infos_from_blocks, get_blob_infos_from_traces}, execute::HostExecutor, trace::trace_to_input, utils::{assemble_block_input, query_block, HostExecutorOutput}, @@ -29,6 +29,7 @@ pub async fn execute_batch( end_block: u64, provider: &DynProvider, use_rpc_db: bool, + batch_version: u8, ) -> Result { assert!( end_block >= start_block, @@ -49,15 +50,20 @@ pub async fn execute_batch( } ExecutorInput { block_inputs: block_inputs.clone(), - blob_info: get_blob_info_from_blocks( + blob_infos: get_blob_infos_from_blocks( &block_inputs.iter().map(|input| input.current_block.clone()).collect::>(), )?, + batch_version, } } else { // Use sequencer's trace rpc. let traces = &mut get_block_traces(batch_index, start_block, end_block, provider).await?; let blocks_inputs = traces.iter().map(trace_to_input).collect::>(); - ExecutorInput { block_inputs: blocks_inputs, blob_info: get_blob_info_from_traces(traces)? } + ExecutorInput { + block_inputs: blocks_inputs, + blob_infos: get_blob_infos_from_traces(traces)?, + batch_version, + } }; Ok(executor_input) diff --git a/prover/bin/host/src/main.rs b/prover/bin/host/src/main.rs index 21fcf10e8..a45f6b25a 100644 --- a/prover/bin/host/src/main.rs +++ b/prover/bin/host/src/main.rs @@ -4,7 +4,7 @@ use alloy_provider::{Provider, ProviderBuilder}; use clap::Parser; use morph_prove::{execute::execute_batch, utils::command_args::parse_u64_auto_radix, BatchProver}; use prover_executor_client::types::input::ExecutorInput; -use prover_executor_host::{blob::get_blob_info_from_traces, trace::trace_to_input}; +use prover_executor_host::{blob::get_blob_infos_from_traces, trace::trace_to_input}; use prover_primitives::types::BlockTrace; /// The arguments for the command. @@ -32,6 +32,9 @@ struct Args { /// Whether to save input. #[clap(long)] save_input: bool, + /// Batch header version (0/1 = V0/V1, 2 = V2 multi-blob). + #[clap(long = "batch-version", default_value_t = 0)] + batch_version: u8, } #[tokio::main] @@ -45,14 +48,17 @@ async fn main() { let mut input = if args.use_rpc_db { // Use RPC to fetch state. let provider = ProviderBuilder::new().connect_http(args.rpc.parse().unwrap()).erased(); - execute_batch(1, args.start_block, args.end_block, &provider, true).await.unwrap() + execute_batch(1, args.start_block, args.end_block, &provider, true, args.batch_version) + .await + .unwrap() } else { // Use local traces file. let block_traces = &mut load_trace(&args.block_path); let blocks_inputs = block_traces.iter().map(trace_to_input).collect::>(); ExecutorInput { block_inputs: blocks_inputs, - blob_info: get_blob_info_from_traces(block_traces).unwrap(), + blob_infos: get_blob_infos_from_traces(block_traces).unwrap(), + batch_version: args.batch_version, } }; if args.save_input { diff --git a/prover/bin/server/src/queue.rs b/prover/bin/server/src/queue.rs index af1c3f2dc..219a50e69 100644 --- a/prover/bin/server/src/queue.rs +++ b/prover/bin/server/src/queue.rs @@ -7,6 +7,7 @@ use std::{ }; use crate::{PROVER_L2_RPC, PROVER_PROOF_DIR, PROVER_USE_RPC_DB, PROVE_RESULT, PROVE_TIME}; +use alloy_primitives::Keccak256; use alloy_provider::{DynProvider, Provider, ProviderBuilder}; use morph_prove::{evm::EvmProofFixture, execute::execute_batch, BatchProver, DefaultClient}; use prover_executor_client::{types::input::ExecutorInput, BlobVerifier, EVMVerifier}; @@ -23,6 +24,12 @@ pub struct ProveRequest { pub end_block: u64, pub rpc: String, pub shadow: Option, + #[serde(default = "default_batch_version")] + pub batch_version: u8, +} + +fn default_batch_version() -> u8 { + 2 } /// The prover that processes prove requests from a queue. @@ -50,7 +57,7 @@ impl Prover { tokio::time::sleep(Duration::from_millis(12000)).await; // Step1. Get request from queue - let (batch_index, start_block, end_block, shadow) = match self + let (batch_index, start_block, end_block, shadow, batch_version) = match self .prove_queue .lock() .await @@ -58,17 +65,19 @@ impl Prover { { Some(req) => { log::info!( - "received prove request, batch index = {:#?}, blocks len = {:#?}, start_block = {:#?}, shadow = {:#?}", + "received prove request, batch index = {:#?}, blocks len = {:#?}, start_block = {:#?}, shadow = {:#?}, batch_version = {}", req.batch_index, req.end_block - req.start_block + 1, req.start_block, req.shadow, + req.batch_version, ); ( req.batch_index, req.start_block, req.end_block, req.shadow.unwrap_or_default(), + req.batch_version, ) } None => { @@ -78,19 +87,26 @@ impl Prover { }; // Step2. Generate ExecutorInput - let mut input = - match gen_client_input(batch_index, start_block, end_block, &self.provider).await { - Ok(input) => input, - Err(e) => { - log::error!( - "Generate ExecutorInput error for batch-{:?}, error: {:?}", - batch_index, - e - ); - PROVE_RESULT.set(2); - continue; - } - }; + let mut input = match gen_client_input( + batch_index, + start_block, + end_block, + &self.provider, + batch_version, + ) + .await + { + Ok(input) => input, + Err(e) => { + log::error!( + "Generate ExecutorInput error for batch-{:?}, error: {:?}", + batch_index, + e + ); + PROVE_RESULT.set(2); + continue; + } + }; // Step3. Generate evm proof log::info!("Generate evm proof"); @@ -123,10 +139,18 @@ async fn gen_client_input( start_block: u64, end_block: u64, provider: &DynProvider, + batch_version: u8, ) -> Result { // Step1. Get ExecutorInput - let executor_input = - execute_batch(batch_index, start_block, end_block, provider, *PROVER_USE_RPC_DB).await?; + let executor_input = execute_batch( + batch_index, + start_block, + end_block, + provider, + *PROVER_USE_RPC_DB, + batch_version, + ) + .await?; let proof_dir = PathBuf::from(PROVER_PROOF_DIR.to_string()).join(format!("batch_{batch_index}")); std::fs::create_dir_all(&proof_dir).expect("failed to create proof path"); @@ -136,15 +160,24 @@ async fn gen_client_input( // Step3. Save batch header or error info. if let Ok(batch_info) = verify_result { - let (versioned_hash, _) = BlobVerifier::verify(&executor_input.blob_info)?; - // Save batch_header - // | batch_data_hash | versioned_hash | sequencer_root | - // |-----------------|----------------|----------------| - // | bytes32 | bytes32 | bytes32 | + let (versioned_hashes, _) = BlobVerifier::verify_blobs(&executor_input.blob_infos)?; + // Compute the blob input for the batch header: + // V2: blobHashesHash = keccak256(hash[0] || ... || hash[N-1]) + // V0/V1: just the single versioned hash + let blob_input = if batch_version >= 2 { + let mut blob_hasher = Keccak256::new(); + for h in &versioned_hashes { + blob_hasher.update(h.as_slice()); + } + blob_hasher.finalize() + } else { + versioned_hashes[0] + }; + // Save batch_header_ex (uniform for all versions): + // | data_hash(32) | blob_input(32) | seqSetVerifyHash(32) | (96 bytes) let mut batch_header: Vec = Vec::with_capacity(96); batch_header.extend_from_slice(&batch_info.data_hash().0); - batch_header.extend_from_slice(&versioned_hash.0); - batch_header.extend_from_slice(&batch_info.sequencer_root().0); + batch_header.extend_from_slice(&blob_input.0); batch_header.extend_from_slice(&batch_info.sequencer_root().0); let mut batch_file = File::create(proof_dir.join("batch_header.data"))?; batch_file.write_all(&batch_header[..]).expect("failed to batch_header"); diff --git a/prover/bin/shadow-prove/contracts/README.md b/prover/bin/shadow-prove/contracts/README.md index 562289d20..fd66db068 100644 --- a/prover/bin/shadow-prove/contracts/README.md +++ b/prover/bin/shadow-prove/contracts/README.md @@ -16,7 +16,7 @@ forge build EvmVerifier: ``` -forge create --broadcast --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 --rpc-url http://localhost:8545 src/libs/EvmVerifier.sol:EvmVerifier --constructor-args 0x00940d658cf507217304ec5f7ca5558e2e0fd67881485f604b63588c31a8792f +forge create --broadcast --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 --rpc-url http://localhost:8545 src/libs/EvmVerifier.sol:EvmVerifier --constructor-args 0x00f1b104202c89fe60d973cbf456a4e2e1ec1e7d63c61453b959dda153df798c ``` ShadowRollup diff --git a/prover/bin/shadow-prove/src/execute.rs b/prover/bin/shadow-prove/src/execute.rs index a35276ee9..1a5142e6e 100644 --- a/prover/bin/shadow-prove/src/execute.rs +++ b/prover/bin/shadow-prove/src/execute.rs @@ -7,7 +7,7 @@ use prover_executor_client::{ verify, }; use prover_executor_host::{ - blob::{get_blob_info_from_blocks, get_blob_info_from_traces}, + blob::{get_blob_infos_from_blocks, get_blob_infos_from_traces}, execute::HostExecutor, trace::trace_to_input, utils::{assemble_block_input, query_block, HostExecutorOutput}, @@ -44,6 +44,7 @@ pub async fn execute( pub async fn try_execute_batch( batch: &BatchInfo, provider: &DynProvider, + batch_version: u8, ) -> Result { let client_input = if *SHADOW_EXECUTE_USE_RPC_DB { let start_block = batch.start_block; @@ -61,9 +62,10 @@ pub async fn try_execute_batch( ExecutorInput { block_inputs: blocks_inputs.clone(), - blob_info: get_blob_info_from_blocks( + blob_infos: get_blob_infos_from_blocks( &blocks_inputs.iter().map(|input| input.current_block.clone()).collect::>(), )?, + batch_version, } } else { // Use sequencer's trace rpc. @@ -71,7 +73,11 @@ pub async fn try_execute_batch( &mut get_block_traces(batch.batch_index, batch.start_block, batch.end_block, provider) .await?; let blocks_inputs = traces.iter().map(trace_to_input).collect::>(); - ExecutorInput { block_inputs: blocks_inputs, blob_info: get_blob_info_from_traces(traces)? } + ExecutorInput { + block_inputs: blocks_inputs, + blob_infos: get_blob_infos_from_traces(traces)?, + batch_version, + } }; verify(client_input.clone()).context("native execution failed") @@ -156,6 +162,7 @@ mod tests { try_execute_batch( &BatchInfo { batch_index: 1, start_block: 53, end_block: 54, total_txn: 1 }, &provider, + 0, ) .await .unwrap(); diff --git a/prover/bin/shadow-prove/src/main.rs b/prover/bin/shadow-prove/src/main.rs index 71487806a..a6cf82946 100644 --- a/prover/bin/shadow-prove/src/main.rs +++ b/prover/bin/shadow-prove/src/main.rs @@ -75,16 +75,18 @@ async fn main() { if *SHADOW_EXECUTE { log::info!(">Start shadow execute batch: {:#?}", batch_info.batch_index); // Execute batch - let offchain_batch_pi = match try_execute_batch(&batch_info, &l2_provider).await { - Ok(pi) => { - // Update the latest processed batch index - pi - } - Err(e) => { - log::error!("execute_batch error: {:?}", e); - continue; - } - }; + let batch_version = batch_header.first().copied().unwrap_or(0); + let offchain_batch_pi = + match try_execute_batch(&batch_info, &l2_provider, batch_version).await { + Ok(pi) => { + // Update the latest processed batch index + pi + } + Err(e) => { + log::error!("execute_batch error: {:?}", e); + continue; + } + }; let onchain_batch_pi = batch_syncer_exec.calc_batch_pi(chain_id, &batch_header).unwrap_or_default(); if offchain_batch_pi != onchain_batch_pi { @@ -317,7 +319,9 @@ async fn test_shadow() { let (batch_info, batch_header) = batch_syncer.get_specified_batch(batch_num).await.unwrap().unwrap(); - let offchain_batch_pi = try_execute_batch(&batch_info, &l2_provider).await.unwrap(); + let batch_version = batch_header.first().copied().unwrap_or(0); + let offchain_batch_pi = + try_execute_batch(&batch_info, &l2_provider, batch_version).await.unwrap(); let onchain_batch_pi = batch_syncer.calc_batch_pi(chain_id, &batch_header).unwrap_or_default(); if offchain_batch_pi != onchain_batch_pi { diff --git a/prover/bin/shadow-prove/src/shadow_prove.rs b/prover/bin/shadow-prove/src/shadow_prove.rs index ca42e5b13..ad53a2e76 100644 --- a/prover/bin/shadow-prove/src/shadow_prove.rs +++ b/prover/bin/shadow-prove/src/shadow_prove.rs @@ -20,6 +20,8 @@ pub struct ProveRequest { pub end_block: u64, pub rpc: String, pub shadow: bool, + #[serde(default)] + pub batch_version: u8, } #[derive(Serialize, Deserialize, Debug)] @@ -122,6 +124,7 @@ where break; } } + let batch_version = prove_info.batch_header.first().copied().unwrap_or(0); // Request the proverServer to prove. let request = ProveRequest { @@ -130,6 +133,7 @@ where end_block: prove_info.batch_info.end_block, rpc: l2_rpc.to_owned(), shadow: false, + batch_version, }; let rt = tokio::task::spawn_blocking(move || { util::call_prover(serde_json::to_string(&request).unwrap(), "/prove_batch") diff --git a/prover/bin/shadow-prove/src/shadow_rollup.rs b/prover/bin/shadow-prove/src/shadow_rollup.rs index a862ed49e..df1f7292c 100644 --- a/prover/bin/shadow-prove/src/shadow_rollup.rs +++ b/prover/bin/shadow-prove/src/shadow_rollup.rs @@ -447,21 +447,32 @@ where chain_id: u64, batch_header: &Bytes, ) -> Result { + // `version` is read only for logging here. Unlike the V2/non-V2 split in `lib.rs` + // (where the prover dispatches different blob-decoding paths), the public-input + // formula is uniform across versions: offset 57 holds the blob input field + // (versioned hash for V0/V1, aggregated hash for V2), and the on-chain verifier + // uses the same layout. Versioned routing happens earlier via the `batch_version` + // request parameter; nothing in this function needs to branch on it. + let version = batch_header.first().copied().unwrap_or(0); + let prev_state_root: &[u8] = batch_header.get(89..121).unwrap_or_default(); let post_state_root: &[u8] = batch_header.get(121..153).unwrap_or_default(); let withdrawal_root: &[u8] = batch_header.get(153..185).unwrap_or_default(); let data_hash: &[u8] = batch_header.get(25..57).unwrap_or_default(); - let blob_versioned_hash: &[u8] = batch_header.get(57..89).unwrap_or_default(); let sequencer_set_verify_hash: &[u8] = batch_header.get(185..217).unwrap_or_default(); + // All versions: blob input at offset 57 (aggregated hash for V2, versioned hash for V0/V1) + let blob_input: &[u8] = batch_header.get(57..89).unwrap_or_default(); + log::info!( - "calc_batch_pi, prevStateRoot = {:?}, postStateRoot = {:?}, withdrawalRoot = {:?}, - dataHash = {:?}, blobVersionedHash = {:?}, sequencerSetVerifyHash = {:?}", + "calc_batch_pi, version = {}, prevStateRoot = {:?}, postStateRoot = {:?}, withdrawalRoot = {:?}, + dataHash = {:?}, blobInput = {:?}, sequencerSetVerifyHash = {:?}", + version, hex::encode_prefixed(prev_state_root), hex::encode_prefixed(post_state_root), hex::encode_prefixed(withdrawal_root), hex::encode_prefixed(data_hash), - hex::encode_prefixed(blob_versioned_hash), + hex::encode_prefixed(blob_input), hex::encode_prefixed(sequencer_set_verify_hash), ); let mut hasher = Keccak256::new(); @@ -471,7 +482,7 @@ where hasher.update(withdrawal_root); hasher.update(sequencer_set_verify_hash); hasher.update(data_hash); - hasher.update(blob_versioned_hash); + hasher.update(blob_input); Ok(hasher.finalize()) } } diff --git a/prover/bin/shadow-prove/src/util.rs b/prover/bin/shadow-prove/src/util.rs index c84e05480..4858f7e3b 100644 --- a/prover/bin/shadow-prove/src/util.rs +++ b/prover/bin/shadow-prove/src/util.rs @@ -61,6 +61,7 @@ async fn test_call_prover() { end_block: 107, rpc: "http://localhost:3030".to_string(), shadow: true, + batch_version: 0, }; let rt = tokio::task::spawn_blocking(move || { diff --git a/prover/contracts/README.md b/prover/contracts/README.md index e143085e2..1e97783f6 100644 --- a/prover/contracts/README.md +++ b/prover/contracts/README.md @@ -17,5 +17,5 @@ $ forge test ### Deploy ``` -forge create --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 --rpc-url http://localhost:8545 prover/contracts/src/EvmVerifier.sol:EvmVerifier --constructor-args 0x00940d658cf507217304ec5f7ca5558e2e0fd67881485f604b63588c31a8792f +forge create --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 --rpc-url http://localhost:8545 prover/contracts/src/EvmVerifier.sol:EvmVerifier --constructor-args 0x00f1b104202c89fe60d973cbf456a4e2e1ec1e7d63c61453b959dda153df798c ``` \ No newline at end of file diff --git a/prover/crates/executor/client/src/lib.rs b/prover/crates/executor/client/src/lib.rs index aeb2595db..7524e1e6f 100644 --- a/prover/crates/executor/client/src/lib.rs +++ b/prover/crates/executor/client/src/lib.rs @@ -10,7 +10,7 @@ pub const EVM_VERIFY: &str = "evm verify"; pub fn verify(input: ExecutorInput) -> Result { // Verify DA - let (versioned_hash, batch_data_from_blob) = BlobVerifier::verify(&input.blob_info)?; + let (versioned_hashes, batch_data_from_blob) = BlobVerifier::verify_blobs(&input.blob_infos)?; let batch_data_from_blocks = get_blob_data_from_blocks( &input.block_inputs.iter().map(|input| input.current_block.clone()).collect::>(), ); @@ -21,19 +21,39 @@ pub fn verify(input: ExecutorInput) -> Result { // Verify EVM exec. let batch_info = profile_report!(EVM_VERIFY, { EVMVerifier::verify(input.block_inputs) })?; - // Calc public input hash. + // Calc public input hash based on version. #[cfg(not(target_os = "zkvm"))] log::info!( "cacl pi hash, prevStateRoot = {:?}, postStateRoot = {:?}, withdrawalRoot = {:?}, - dataHash = {:?}, blobVersionedHash = {:?}, sequencerSetVerifyHash = {:?}", + dataHash = {:?}, blobVersionedHashes = {:?}, sequencerSetVerifyHash = {:?}, batch_version = {}", hex::encode(batch_info.prev_state_root().as_slice()), hex::encode(batch_info.post_state_root().as_slice()), hex::encode(batch_info.withdraw_root().as_slice()), hex::encode(batch_info.data_hash().as_slice()), - hex::encode(versioned_hash.as_slice()), + versioned_hashes.iter().map(|h| hex::encode(h.as_slice())).collect::>(), hex::encode(batch_info.sequencer_root().as_slice()), + input.batch_version, ); - let public_input_hash = batch_info.public_input_hash(&versioned_hash); + let public_input_hash = match input.batch_version { + 0 | 1 => { + if versioned_hashes.is_empty() { + return Err(anyhow::anyhow!( + "batch version {} requires exactly 1 versioned hash, got 0", + input.batch_version + )); + } + batch_info.public_input_hash(&versioned_hashes[0]) + } + 2 => { + if versioned_hashes.is_empty() { + return Err(anyhow::anyhow!("batch version 2 requires at least 1 versioned hash")); + } + batch_info.public_input_hash_v2(&versioned_hashes) + } + v => { + return Err(anyhow::anyhow!("unsupported batch version: {}", v)); + } + }; #[cfg(not(target_os = "zkvm"))] log::info!("public input hash: {public_input_hash:?}"); Ok(B256::from_slice(public_input_hash.as_slice())) diff --git a/prover/crates/executor/client/src/types/batch.rs b/prover/crates/executor/client/src/types/batch.rs index 1f4f50ce5..5cb7b7c9a 100644 --- a/prover/crates/executor/client/src/types/batch.rs +++ b/prover/crates/executor/client/src/types/batch.rs @@ -77,11 +77,42 @@ impl BatchInfo { hasher.finalize() } + /// V2 public input hash: uses keccak256(hash[0] || ... || hash[N-1]) as blob input + pub fn public_input_hash_v2(&self, blob_hashes: &[B256]) -> B256 { + let mut blob_hasher = Keccak256::new(); + for h in blob_hashes { + blob_hasher.update(h.as_slice()); + } + let blob_hashes_hash: B256 = blob_hasher.finalize(); + + let mut hasher = Keccak256::new(); + hasher.update(self.chain_id.to_be_bytes()); + hasher.update(self.prev_state_root.as_slice()); + hasher.update(self.post_state_root.as_slice()); + hasher.update(self.withdraw_root.unwrap().as_slice()); + hasher.update(self.sequencer_root.unwrap().as_slice()); + hasher.update(self.data_hash.as_slice()); + hasher.update(blob_hashes_hash.as_slice()); + hasher.finalize() + } + /// Chain ID of this chunk pub fn chain_id(&self) -> u64 { self.chain_id } + #[cfg(test)] + fn test_instance(chain_id: u64) -> Self { + BatchInfo { + chain_id, + prev_state_root: B256::ZERO, + post_state_root: B256::ZERO, + withdraw_root: Some(B256::ZERO), + sequencer_root: Some(B256::ZERO), + data_hash: B256::ZERO, + } + } + /// State root before this chunk pub fn prev_state_root(&self) -> B256 { self.prev_state_root @@ -107,3 +138,118 @@ impl BatchInfo { self.data_hash } } + +#[cfg(test)] +mod tests { + use super::*; + use alloy_primitives::keccak256; + + // LAYER_2_CHAIN_ID used in Rollup.sol test environment + const TEST_CHAIN_ID: u64 = 53077; + + fn make_hash(val: u64) -> B256 { + let mut b = [0u8; 32]; + b[24..].copy_from_slice(&val.to_be_bytes()); + B256::from(b) + } + + /// V2 aggregated hash for a single blob: keccak256(h0) != h0 (not backward-compatible with V1). + #[test] + fn test_public_input_hash_v2_single_blob_differs_from_v1() { + let batch = BatchInfo::test_instance(TEST_CHAIN_ID); + let h0 = make_hash(0xBEEF); + + let v1_hash = batch.public_input_hash(&h0); + let v2_hash = batch.public_input_hash_v2(&[h0]); + + assert_ne!(v1_hash, v2_hash, "V2 single-blob must differ from V1"); + } + + /// V2 aggregated hash for two blobs: keccak256(h0 || h1) matches contract formula. + #[test] + fn test_public_input_hash_v2_two_blobs_matches_contract() { + let batch = BatchInfo::test_instance(TEST_CHAIN_ID); + let h0 = make_hash(0xAAAA); + let h1 = make_hash(0xBBBB); + + // Replicate contract formula: aggregatedBlobHash = keccak256(h0 || h1) + let mut concat = [0u8; 64]; + concat[..32].copy_from_slice(h0.as_slice()); + concat[32..].copy_from_slice(h1.as_slice()); + let aggregated = keccak256(&concat); + + // V2 public input uses aggregated as blob input + let mut hasher = Keccak256::new(); + hasher.update(TEST_CHAIN_ID.to_be_bytes()); + hasher.update(B256::ZERO.as_slice()); // prev_state_root + hasher.update(B256::ZERO.as_slice()); // post_state_root + hasher.update(B256::ZERO.as_slice()); // withdraw_root + hasher.update(B256::ZERO.as_slice()); // sequencer_root + hasher.update(B256::ZERO.as_slice()); // data_hash + hasher.update(aggregated.as_slice()); + let expected: B256 = hasher.finalize(); + + let result = batch.public_input_hash_v2(&[h0, h1]); + assert_eq!(result, expected, "V2 two-blob hash must match contract formula"); + } + + /// V2 aggregated hash for three blobs: keccak256(h0 || h1 || h2). + #[test] + fn test_public_input_hash_v2_three_blobs() { + let batch = BatchInfo::test_instance(TEST_CHAIN_ID); + let h0 = make_hash(0xAAAA); + let h1 = make_hash(0xBBBB); + let h2 = make_hash(0xCCCC); + + let mut concat = [0u8; 96]; + concat[..32].copy_from_slice(h0.as_slice()); + concat[32..64].copy_from_slice(h1.as_slice()); + concat[64..].copy_from_slice(h2.as_slice()); + let aggregated = keccak256(&concat); + + let mut hasher = Keccak256::new(); + hasher.update(TEST_CHAIN_ID.to_be_bytes()); + hasher.update(B256::ZERO.as_slice()); + hasher.update(B256::ZERO.as_slice()); + hasher.update(B256::ZERO.as_slice()); + hasher.update(B256::ZERO.as_slice()); + hasher.update(B256::ZERO.as_slice()); + hasher.update(aggregated.as_slice()); + let expected: B256 = hasher.finalize(); + + let result = batch.public_input_hash_v2(&[h0, h1, h2]); + assert_eq!(result, expected, "V2 three-blob hash must match contract formula"); + } + + /// V2 aggregated hash is order-sensitive: (h0,h1) != (h1,h0). + #[test] + fn test_public_input_hash_v2_order_sensitive() { + let batch = BatchInfo::test_instance(TEST_CHAIN_ID); + let h0 = make_hash(0xAAAA); + let h1 = make_hash(0xBBBB); + + let fwd = batch.public_input_hash_v2(&[h0, h1]); + let rev = batch.public_input_hash_v2(&[h1, h0]); + assert_ne!(fwd, rev, "V2 aggregated hash must be order-sensitive"); + } + + /// V2 and V1 produce the same result only when blob_hashes_hash accidentally equals + /// the raw versioned hash — which should never happen in practice. + /// This test confirms the structural difference by construction. + #[test] + fn test_public_input_hash_v2_vs_v1_structural_difference() { + let batch = BatchInfo::test_instance(TEST_CHAIN_ID); + let h0 = make_hash(0x1234); + + // V1: uses h0 directly as blob input + let v1 = batch.public_input_hash(&h0); + // V2: uses keccak256(h0) as blob input — structurally different + let v2 = batch.public_input_hash_v2(&[h0]); + assert_ne!(v1, v2); + + // Confirm: if we manually pass keccak256(h0) into V1, it matches V2 + let agg = keccak256(h0.as_slice()); + let v1_with_agg = batch.public_input_hash(&agg); + assert_eq!(v1_with_agg, v2, "V2 is equivalent to V1 with pre-aggregated hash"); + } +} diff --git a/prover/crates/executor/client/src/types/blob.rs b/prover/crates/executor/client/src/types/blob.rs index 2d0ef80a2..31ab48d1b 100644 --- a/prover/crates/executor/client/src/types/blob.rs +++ b/prover/crates/executor/client/src/types/blob.rs @@ -9,25 +9,42 @@ pub const MAGIC_NUM: u32 = 0xFD2F_B528; /// evaluationform. pub const BLOB_WIDTH: usize = 4096; -const MAX_BLOB_TX_PAYLOAD_SIZE: usize = 131072; // 131072 = 4096 * 32 = 1024 * 4 * 32 = 128kb - #[derive(Clone, Debug)] pub struct BlobData {} -pub fn get_origin_batch(blob_data: &[u8]) -> Result, anyhow::Error> { - // Decode blob, recovering BLS12-381 scalars. - let mut batch_data = vec![0u8; MAX_BLOB_TX_PAYLOAD_SIZE]; - for i in 0..4096 { +/// Decode a single blob's BLS12-381 field elements into raw bytes (4096 x 31 bytes). +/// Does NOT decompress — call [`decompress_batch`] on the concatenated output of all blobs. +pub fn decode_blob_scalars(blob_data: &[u8]) -> Result, anyhow::Error> { + if blob_data.len() != BLOB_WIDTH * 32 { + return Err(anyhow!( + "invalid blob length: expected {}, got {}", + BLOB_WIDTH * 32, + blob_data.len() + )); + } + let mut chunk = vec![0u8; BLOB_WIDTH * 31]; + for i in 0..BLOB_WIDTH { if blob_data[i * 32] != 0 { - return Err(anyhow!(format!( + return Err(anyhow!( "Invalid blob, found non-zero high order byte {:x} of field element {}", blob_data[i * 32], i - ))); + )); } - batch_data[i * 31..i * 31 + 31].copy_from_slice(&blob_data[i * 32 + 1..i * 32 + 32]); + chunk[i * 31..i * 31 + 31].copy_from_slice(&blob_data[i * 32 + 1..i * 32 + 32]); } - decompress_batch(&batch_data) + Ok(chunk) +} + +/// Alias for [`decode_blob_scalars`] — kept for backward compatibility. +pub fn unpack_blob(blob_data: &[u8]) -> Result, anyhow::Error> { + decode_blob_scalars(blob_data) +} + +/// Decode a single blob's scalars and immediately decompress (single-blob / V0/V1 path). +pub fn get_origin_batch(blob_data: &[u8]) -> Result, anyhow::Error> { + let chunk = decode_blob_scalars(blob_data)?; + decompress_batch(&chunk) } pub fn decompress_batch(compressed_batch: &[u8]) -> Result, anyhow::Error> { diff --git a/prover/crates/executor/client/src/types/input.rs b/prover/crates/executor/client/src/types/input.rs index 354563783..4ac2fd13b 100644 --- a/prover/crates/executor/client/src/types/input.rs +++ b/prover/crates/executor/client/src/types/input.rs @@ -69,7 +69,9 @@ impl BlockInput { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ExecutorInput { pub block_inputs: Vec, - pub blob_info: BlobInfo, + pub blob_infos: Vec, + #[serde(default)] + pub batch_version: u8, } #[cfg(test)] diff --git a/prover/crates/executor/client/src/verifier/blob_verifier.rs b/prover/crates/executor/client/src/verifier/blob_verifier.rs index d65ef9cb4..4c83e7a00 100644 --- a/prover/crates/executor/client/src/verifier/blob_verifier.rs +++ b/prover/crates/executor/client/src/verifier/blob_verifier.rs @@ -1,22 +1,56 @@ -use crate::types::{blob::get_origin_batch, input::BlobInfo}; +use crate::types::{ + blob::{decode_blob_scalars, decompress_batch, get_origin_batch}, + input::BlobInfo, +}; use anyhow::anyhow; use kzg_rs::{get_kzg_settings, Blob as KzgRsBlob, Bytes48}; use prover_primitives::B256; use sha2::{Digest as _, Sha256}; -// use Verifier; pub struct BlobVerifier; impl BlobVerifier { + /// Verify multiple blobs: + /// - KZG-verify each blob and decode its BLS scalars (no decompression) + /// - Concatenate all raw scalar bytes, then decompress once + /// + /// Returns `(versioned_hashes, decompressed_batch_data)`. + pub fn verify_blobs(blob_infos: &[BlobInfo]) -> Result<(Vec, Vec), anyhow::Error> { + let mut hashes = Vec::new(); + let mut raw_bytes = Vec::new(); + for info in blob_infos { + let (hash, raw) = Self::verify_raw(info)?; + hashes.push(hash); + raw_bytes.extend(raw); + } + let batch_data = decompress_batch(&raw_bytes)?; + Ok((hashes, batch_data)) + } + + /// KZG-verify a single blob and unpack + decompress its payload (V0/V1 single-blob path). pub fn verify(blob_info: &BlobInfo) -> Result<(B256, Vec), anyhow::Error> { - // decode + let hash = Self::verify_kzg(blob_info)?; let origin_batch = get_origin_batch(&blob_info.blob_data)?; + Ok((hash, origin_batch)) + } - // verify kzg + /// KZG-verify a single blob and decode its BLS scalars without decompression. + /// Returns `(versioned_hash, raw_scalar_bytes)`. + pub fn verify_raw(blob_info: &BlobInfo) -> Result<(B256, Vec), anyhow::Error> { + let hash = Self::verify_kzg(blob_info)?; + let raw = decode_blob_scalars(&blob_info.blob_data)?; + Ok((hash, raw)) + } + + /// KZG-verify a blob's commitment/proof and return its versioned hash. + fn verify_kzg(blob_info: &BlobInfo) -> Result { let versioned_hash = kzg_to_versioned_hash(&blob_info.commitment); - let blob = KzgRsBlob::from_slice(&blob_info.blob_data).unwrap(); - let commitment = Bytes48::from_slice(&blob_info.commitment).unwrap(); - let proof = Bytes48::from_slice(&blob_info.proof).unwrap(); + let blob = KzgRsBlob::from_slice(&blob_info.blob_data) + .map_err(|e| anyhow!("invalid blob_data length: {e:?}"))?; + let commitment = Bytes48::from_slice(&blob_info.commitment) + .map_err(|e| anyhow!("invalid commitment length: {e:?}"))?; + let proof = Bytes48::from_slice(&blob_info.proof) + .map_err(|e| anyhow!("invalid proof length: {e:?}"))?; let verify_result = kzg_rs::KzgProof::verify_blob_kzg_proof(blob, &commitment, &proof, &get_kzg_settings()) @@ -29,8 +63,7 @@ impl BlobVerifier { "verify_blob_kzg_proof successfully, versioned_hash: {:?}", B256::from_slice(&versioned_hash) ); - - Ok((B256::from_slice(&versioned_hash), origin_batch)) + Ok(B256::from_slice(&versioned_hash)) } } diff --git a/prover/crates/executor/core/src/executor.rs b/prover/crates/executor/core/src/executor.rs index d065b7b34..08428b7e1 100644 --- a/prover/crates/executor/core/src/executor.rs +++ b/prover/crates/executor/core/src/executor.rs @@ -8,6 +8,7 @@ use morph_chainspec::hardfork::MorphHardforks; use morph_chainspec::MORPH_HOODI; use morph_chainspec::MORPH_MAINNET; use morph_primitives::MorphTxEnvelope; +use morph_revm::L1BlockInfo; use morph_revm::MorphBlockEnv; use morph_revm::MorphEvm; use revm::MainContext; @@ -36,7 +37,8 @@ impl MorphExecutor { .with_db(db) .with_block(input.block_env) .with_cfg(input.cfg_env) - .with_tx(Default::default()); + .with_tx(Default::default()) + .with_chain(L1BlockInfo::default()); let evm = MorphEvm::new(ctx, NoOpInspector {}); Self { inner: evm } diff --git a/prover/crates/executor/host/src/blob.rs b/prover/crates/executor/host/src/blob.rs index 7ff260220..a7bb38a94 100644 --- a/prover/crates/executor/host/src/blob.rs +++ b/prover/crates/executor/host/src/blob.rs @@ -16,6 +16,9 @@ const BLOB_WIDTH: usize = 4096; /// The bytes len of one blob. const BLOB_DATA_SIZE: usize = BLOB_WIDTH * N_BYTES_U256; +/// Maximum payload bytes that fit in a single blob (4096 field elements × 31 usable bytes each). +const MAX_BLOB_BYTES_SIZE: usize = BLOB_WIDTH * (N_BYTES_U256 - 1); // 4096 * 31 = 126,976 + // Get blob info from L2 blocks pub fn get_blob_info_from_blocks(blocks: &Vec) -> Result { // Assemble batch data from block header and transactions. @@ -42,6 +45,58 @@ pub fn get_blob_info_from_traces( populate_kzg(&blob_data) } +/// Encode batch data from L2 blocks into multiple blob infos (one per 126,976-byte chunk). +pub fn get_blob_infos_from_blocks(blocks: &[L2Block]) -> Result> { + let batch_data = get_blob_data_from_blocks(&blocks.to_vec()); + let compressed = compresse_batch(batch_data.as_slice())?; + encode_multi_blob(compressed) +} + +/// Encode batch data from block traces into multiple blob infos. +pub fn get_blob_infos_from_traces(traces: &[BlockTrace]) -> Result> { + let batch_data = get_blob_data_from_traces(&traces.to_vec()); + let compressed = compresse_batch(batch_data.as_slice())?; + encode_multi_blob(compressed) +} + +/// Split compressed data into N blobs, each holding up to MAX_BLOB_BYTES_SIZE bytes. +fn encode_multi_blob(compressed: Vec) -> Result> { + if compressed.is_empty() { + return Ok(vec![populate_kzg(&[0u8; BLOB_DATA_SIZE])?]); + } + let blob_count = compressed.len().div_ceil(MAX_BLOB_BYTES_SIZE); + let mut infos = Vec::with_capacity(blob_count); + for i in 0..blob_count { + let start = i * MAX_BLOB_BYTES_SIZE; + let end = std::cmp::min(start + MAX_BLOB_BYTES_SIZE, compressed.len()); + let chunk = &compressed[start..end]; + let blob_data = encode_blob_from_bytes(chunk)?; + infos.push(populate_kzg(&blob_data)?); + } + Ok(infos) +} + +/// Encode a byte slice (already compressed) into an EIP-4844 blob payload (131072 bytes). +/// +/// Packs bytes into 4096 BLS12-381 field elements with the MSB forced to 0x00. +pub fn encode_blob_from_bytes(data: &[u8]) -> Result<[u8; BLOB_DATA_SIZE]> { + ensure!( + data.len() <= MAX_BLOB_BYTES_SIZE, + "data size {} exceeds max blob capacity {}", + data.len(), + MAX_BLOB_BYTES_SIZE + ); + let mut coefficients = [[0u8; N_BYTES_U256]; BLOB_WIDTH]; + for (i, byte) in data.iter().enumerate() { + coefficients[i / 31][1 + (i % 31)] = *byte; + } + let mut blob_bytes = [0u8; BLOB_DATA_SIZE]; + for (index, value) in coefficients.iter().enumerate() { + blob_bytes[index * 32..(index + 1) * 32].copy_from_slice(value.as_slice()); + } + Ok(blob_bytes) +} + /// Encode `tx_bytes` into an EIP-4844 blob payload (131072 bytes). /// /// The blob represents `BLOB_WIDTH = 4096` BLS12-381 scalar-field (`Fr`) elements (32 bytes each). @@ -60,13 +115,11 @@ pub fn encode_blob(tx_bytes: Vec) -> Result<[u8; 131072]> { } // zstd compresse let compressed_batch = compresse_batch(tx_bytes.as_slice()).context("compress batch failed")?; - let max = BLOB_WIDTH * (N_BYTES_U256 - 1); - ensure!( - compressed_batch.len() <= max, + compressed_batch.len() <= MAX_BLOB_BYTES_SIZE, "compressed batch size {} exceeds the max capacity {}", compressed_batch.len(), - max + MAX_BLOB_BYTES_SIZE ); let mut coefficients = [[0u8; N_BYTES_U256]; BLOB_WIDTH]; diff --git a/prover/crates/executor/host/src/execute.rs b/prover/crates/executor/host/src/execute.rs index 53ee69c0d..10dd2ac31 100644 --- a/prover/crates/executor/host/src/execute.rs +++ b/prover/crates/executor/host/src/execute.rs @@ -1,4 +1,4 @@ -use crate::utils::{beneficiary_by_chain_id, query_block, query_state_root, HostExecutorOutput}; +use crate::utils::{beneficiary_by_chain_id, query_block, HostExecutorOutput}; use alloy_provider::{DynProvider, Provider}; use anyhow::{bail, Context}; use prover_executor_core::MorphExecutor; @@ -29,6 +29,10 @@ impl HostExecutor { let block = query_block(block_number, provider) .await .with_context(|| format!("query_block failed for block {block_number}"))?; + // Post-MPT migration (PR #886), the L2 state trie is a standard Ethereum MPT, so + // `header.state_root` is authoritative and replaces the previous custom `morph_diskRoot` + // RPC field. The root is re-derived locally below and checked against this value. + let post_state_root = block.header.state_root; // layer2 chain id let chain_id = @@ -40,30 +44,23 @@ impl HostExecutor { // We use a per-chain hardcoded address as the sequencer/beneficiary. let beneficiary = beneficiary_by_chain_id(chain_id); - // mpt root at this block - let disk_root = query_state_root(block_number, provider) - .await - .with_context(|| format!("query_state_root failed for block {block_number}"))?; - // We need a previous block root to initialize the RPC-backed DB. let prev_block_number = block_number .checked_sub(1) .context("HostExecutor::execute_block requires block_number > 0 (needs prev state)")?; - let prev_disk_root = - query_state_root(prev_block_number, provider).await.with_context(|| { - format!("query_state_root failed for prev block {prev_block_number}") - })?; + + let prev_block = query_block(prev_block_number, provider) + .await + .with_context(|| format!("query_block failed for prev block {prev_block_number}"))?; + // Same rationale as `post_state_root`: header state_root is the MPT root. + let prev_state_root = prev_block.header.state_root; let tx_count = block.transactions.len(); let block_num = block.header.number.to::(); // Init DB (RPC-backed, rooted at previous block). - let rpc_db = BasicRpcDb::new( - provider.clone(), - chain_id, - prev_block_number, - prev_disk_root.disk_root, - ); + let rpc_db = + BasicRpcDb::new(provider.clone(), chain_id, prev_block_number, prev_state_root); // Warm up predeployed contract info. load_predeployed_contracts(&rpc_db).await?; @@ -108,7 +105,7 @@ impl HostExecutor { )); state_for_verification.state_root() }; - let expected_state_root = disk_root.disk_root; + let expected_state_root = block.header.state_root; if computed_state_root != expected_state_root { bail!( "Mismatched state root after executing block {block_number}: expected {expected_state_root:?}, got {computed_state_root:?}" @@ -122,8 +119,8 @@ impl HostExecutor { block, state, codes: rpc_db.bytecodes(), - prev_state_root: prev_disk_root.disk_root, - post_state_root: disk_root.disk_root, + prev_state_root, + post_state_root, }) } } diff --git a/prover/crates/executor/host/src/utils.rs b/prover/crates/executor/host/src/utils.rs index 36dd629e3..66d0d7356 100644 --- a/prover/crates/executor/host/src/utils.rs +++ b/prover/crates/executor/host/src/utils.rs @@ -94,17 +94,6 @@ pub fn assemble_block_input( ClientBlockInput { current_block: l2_block, parent_state: state, bytecodes: codes } } -/// Queries the state root at a given block number. -pub async fn query_state_root( - block_number: u64, - provider: &DynProvider, -) -> Result { - provider - .raw_request::<_, DiskRoot>("morph_diskRoot".into(), [format!("{block_number:#x}")]) - .await - .context("morph_diskRoot error") -} - /// Queries the block at a given block number. pub async fn query_block( block_number: u64, @@ -118,17 +107,3 @@ pub async fn query_block( .await .context("eth_getBlockByNumber error") } - -/// Queries the block at a given block number without transactions. -pub async fn query_chain_d( - block_number: u64, - provider: &DynProvider, -) -> Result { - provider - .raw_request::<_, ProverBlock>( - "eth_getBlockByNumber".into(), - [format!("{block_number:#x}")], - ) - .await - .context("eth_getBlockByNumber error") -} diff --git a/prover/crates/primitives/src/lib.rs b/prover/crates/primitives/src/lib.rs index 87e283c22..769e502b4 100644 --- a/prover/crates/primitives/src/lib.rs +++ b/prover/crates/primitives/src/lib.rs @@ -255,7 +255,7 @@ pub trait TxTrace { let tx = TxMorph { chain_id, nonce: self.nonce(), - gas_limit: self.gas_limit() as u128, + gas_limit: self.gas_limit(), max_fee_per_gas: self.max_fee_per_gas(), max_priority_fee_per_gas: self.max_priority_fee_per_gas(), to: self.to(), diff --git a/prover/crates/storage/rpc-db/src/basic_rpc_db.rs b/prover/crates/storage/rpc-db/src/basic_rpc_db.rs index 43418d38b..a16edefca 100644 --- a/prover/crates/storage/rpc-db/src/basic_rpc_db.rs +++ b/prover/crates/storage/rpc-db/src/basic_rpc_db.rs @@ -2,6 +2,7 @@ use std::{ collections::{BTreeMap, BTreeSet}, marker::PhantomData, sync::{Arc, RwLock}, + time::Duration, }; use crate::account_proof::{eip1186_proof_to_account_proof, EIP1186AccountProofResponseCompat}; @@ -16,6 +17,7 @@ use revm::database::BundleState; use revm::database::DatabaseRef; use revm::primitives::{Address, B256, KECCAK_EMPTY}; use revm::state::{AccountInfo, Bytecode}; +use tokio::time::sleep; use crate::error::RpcDbError; @@ -36,6 +38,8 @@ pub struct BasicRpcDb { pub storage: Arc>>>, /// The oldest block whose header/hash has been requested. pub oldest_ancestor: Arc>, + /// Whether to use throttle requests with delays. + pub throttle_requests: bool, phantom: PhantomData, } @@ -43,6 +47,9 @@ pub struct BasicRpcDb { impl + Clone, N: Network> BasicRpcDb { /// Create a new [`BasicRpcDb`]. pub fn new(provider: P, chain_id: u64, block_number: u64, state_root: B256) -> Self { + let throttle_requests = std::env::var("SHOULD_THROTTLE_REQUESTS") + .map(|s| s.parse::().unwrap_or(true)) + .unwrap_or(true); Self { provider, chain_id, @@ -51,6 +58,7 @@ impl + Clone, N: Network> BasicRpcDb { accounts: Arc::new(RwLock::new(HashMap::with_hasher(Default::default()))), storage: Arc::new(RwLock::new(HashMap::with_hasher(Default::default()))), oldest_ancestor: Arc::new(RwLock::new(block_number)), + throttle_requests, phantom: PhantomData, } } @@ -58,6 +66,9 @@ impl + Clone, N: Network> BasicRpcDb { /// Fetch the [AccountInfo] for an [Address]. pub async fn fetch_account_info(&self, address: Address) -> Result { log::debug!("fetching account info for address: {}", address); + if self.throttle_requests { + sleep(Duration::from_millis(50)).await; + } // Fetch the proof for the account. let proof = self @@ -102,6 +113,9 @@ impl + Clone, N: Network> BasicRpcDb { keys: Vec, block_number: u64, ) -> Result { + if self.throttle_requests { + sleep(Duration::from_millis(50)).await; + } let compact_proof: EIP1186AccountProofResponseCompat = self .provider .raw_request::<(Address, Vec, BlockId), _>( @@ -121,6 +135,9 @@ impl + Clone, N: Network> BasicRpcDb { index: U256, ) -> Result { log::debug!("fetching storage value at address: {}, index: {}", address, index); + if self.throttle_requests { + sleep(Duration::from_millis(50)).await; + } // Fetch the storage value. let value = self diff --git a/prover/rust-toolchain b/prover/rust-toolchain deleted file mode 100644 index cdeba7a2b..000000000 --- a/prover/rust-toolchain +++ /dev/null @@ -1,3 +0,0 @@ -[toolchain] -channel = "1.91.0" -components = ["rustfmt", "clippy"] diff --git a/tx-submitter/batch/batch_storage_test.go b/tx-submitter/batch/batch_storage_test.go deleted file mode 100644 index 9346379a2..000000000 --- a/tx-submitter/batch/batch_storage_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package batch - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "morph-l2/tx-submitter/iface" -) - -func Test_storageBatch(t *testing.T) { - testDB := setupTestDB(t) - cache := NewBatchCache(nil, l1Client, []iface.L2Client{l2Client}, rollupContract, l2Caller, testDB) - err := cache.InitAndSyncFromRollup() - require.NoError(t, err) - - batches, _, err := cache.batchStorage.LoadAllSealedBatches() - require.NoError(t, err) - require.NotNil(t, batches) - t.Log("loaded batches count", len(batches)) -} diff --git a/tx-submitter/batch/blob.go b/tx-submitter/batch/blob.go deleted file mode 100644 index 399b0c15f..000000000 --- a/tx-submitter/batch/blob.go +++ /dev/null @@ -1,210 +0,0 @@ -package batch - -import ( - "bytes" - "encoding/binary" - "errors" - "fmt" - "io" - "morph-l2/node/zstd" - - eth "github.com/morph-l2/go-ethereum/core/types" - "github.com/morph-l2/go-ethereum/crypto/kzg4844" - "github.com/morph-l2/go-ethereum/rlp" -) - -const MaxBlobBytesSize = 4096 * 31 - -var ( - emptyBlob = new(kzg4844.Blob) - emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob) - emptyBlobProof, _ = kzg4844.ComputeBlobProof(emptyBlob, emptyBlobCommit) -) - -// MakeBlobCanonical converts the raw blob data into the canonical blob representation of 4096 BLSFieldElements. -func MakeBlobCanonical(blobBytes []byte) (b *kzg4844.Blob, err error) { - if len(blobBytes) > MaxBlobBytesSize { - return nil, fmt.Errorf("data is too large for blob. len=%v", len(blobBytes)) - } - offset := 0 - b = new(kzg4844.Blob) - // encode (up to) 31 bytes of remaining input data at a time into the subsequent field element - for i := 0; i < 4096; i++ { - offset += copy(b[i*32+1:i*32+32], blobBytes[offset:]) - if offset == len(blobBytes) { - break - } - } - if offset < len(blobBytes) { - return nil, fmt.Errorf("failed to fit all data into blob. bytes remaining: %v", len(blobBytes)-offset) - } - return -} - -func RetrieveBlobBytes(blob *kzg4844.Blob) ([]byte, error) { - data := make([]byte, MaxBlobBytesSize) - for i := 0; i < 4096; i++ { - if blob[i*32] != 0 { - return nil, fmt.Errorf("invalid blob, found non-zero high order byte %x of field element %d", data[i*32], i) - } - copy(data[i*31:i*31+31], blob[i*32+1:i*32+32]) - } - return data, nil -} - -func makeBlobCommitment(bz []byte) (b kzg4844.Blob, c kzg4844.Commitment, err error) { - blob, err := MakeBlobCanonical(bz) - if err != nil { - return - } - b = *blob - c, err = kzg4844.BlobToCommitment(&b) - if err != nil { - return - } - return -} - -func MakeBlobTxSidecar(blobBytes []byte) (*eth.BlobTxSidecar, error) { - if len(blobBytes) == 0 { - return ð.BlobTxSidecar{ - Blobs: []kzg4844.Blob{*emptyBlob}, - Commitments: []kzg4844.Commitment{emptyBlobCommit}, - Proofs: []kzg4844.Proof{emptyBlobProof}, - }, nil - } - if len(blobBytes) > 2*MaxBlobBytesSize { - return nil, errors.New("only 2 blobs at most is allowed") - } - blobCount := len(blobBytes)/(MaxBlobBytesSize+1) + 1 - var ( - err error - blobs = make([]kzg4844.Blob, blobCount) - commitments = make([]kzg4844.Commitment, blobCount) - ) - switch blobCount { - case 1: - blobs[0], commitments[0], err = makeBlobCommitment(blobBytes) - if err != nil { - return nil, err - } - case 2: - blobs[0], commitments[0], err = makeBlobCommitment(blobBytes[:MaxBlobBytesSize]) - if err != nil { - return nil, err - } - blobs[1], commitments[1], err = makeBlobCommitment(blobBytes[MaxBlobBytesSize:]) - if err != nil { - return nil, err - } - } - return ð.BlobTxSidecar{ - Blobs: blobs, - Commitments: commitments, - }, nil -} - -func CompressBatchBytes(batchBytes []byte) ([]byte, error) { - if len(batchBytes) == 0 { - return nil, nil - } - compressedBatchBytes, err := zstd.CompressBatchBytes(batchBytes) - if err != nil { - return nil, fmt.Errorf("failed to compress batch bytes, err: %w", err) - } - return compressedBatchBytes, nil -} - -func DecodeTxsFromBytes(txsBytes []byte) (eth.Transactions, error) { - reader := bytes.NewReader(txsBytes) - txs := make(eth.Transactions, 0) - for { - var ( - firstByte byte - fullTxBytes []byte - innerTx eth.TxData - err error - ) - if err = binary.Read(reader, binary.BigEndian, &firstByte); err != nil { - // if the blob byte array is completely consumed, then break the loop - if err == io.EOF { - break - } - return nil, err - } - // zero byte is found after valid tx bytes, break the loop - if firstByte == 0 { - break - } - - switch firstByte { - case eth.AccessListTxType: - if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil { - return nil, err - } - innerTx = new(eth.AccessListTx) - case eth.DynamicFeeTxType: - if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil { - return nil, err - } - innerTx = new(eth.DynamicFeeTx) - case eth.SetCodeTxType: - if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil { - return nil, err - } - innerTx = new(eth.SetCodeTx) - case eth.MorphTxType: - if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil { - return nil, err - } - innerTx = new(eth.MorphTx) - default: - if firstByte <= 0xf7 { // legacy tx first byte must be greater than 0xf7(247) - return nil, fmt.Errorf("not supported tx type: %d", firstByte) - } - innerTx = new(eth.LegacyTx) - } - - // we support the tx types of LegacyTxType/AccessListTxType/DynamicFeeTxType - //if firstByte == eth.AccessListTxType || firstByte == eth.DynamicFeeTxType { - // // the firstByte here is used to indicate tx type, so skip it - // if err := binary.Read(reader, binary.BigEndian, &firstByte); err != nil { - // return nil, err - // } - //} else if firstByte <= 0xf7 { // legacy tx first byte must be greater than 0xf7(247) - // return nil, fmt.Errorf("not supported tx type: %d", firstByte) - //} - fullTxBytes, err = extractInnerTxFullBytes(firstByte, reader) - if err != nil { - return nil, err - } - if err = rlp.DecodeBytes(fullTxBytes, innerTx); err != nil { - return nil, err - } - txs = append(txs, eth.NewTx(innerTx)) - } - return txs, nil -} - -func extractInnerTxFullBytes(firstByte byte, reader io.Reader) ([]byte, error) { - //the occupied byte length for storing the size of the following rlp encoded bytes - sizeByteLen := firstByte - 0xf7 - - // the size of the following rlp encoded bytes - sizeByte := make([]byte, sizeByteLen) - if err := binary.Read(reader, binary.BigEndian, sizeByte); err != nil { - return nil, err - } - size := binary.BigEndian.Uint32(append(make([]byte, 4-len(sizeByte)), sizeByte...)) - - txRaw := make([]byte, size) - if err := binary.Read(reader, binary.BigEndian, txRaw); err != nil { - return nil, err - } - fullTxBytes := make([]byte, 1+uint32(sizeByteLen)+size) - copy(fullTxBytes[:1], []byte{firstByte}) - copy(fullTxBytes[1:1+sizeByteLen], sizeByte) - copy(fullTxBytes[1+sizeByteLen:], txRaw) - - return fullTxBytes, nil -} diff --git a/tx-submitter/constants/methods.go b/tx-submitter/constants/methods.go index aefe24d06..7de9eb498 100644 --- a/tx-submitter/constants/methods.go +++ b/tx-submitter/constants/methods.go @@ -1,8 +1,15 @@ package constants const ( - // MethodCommitBatch is the method name for committing a batch + // MethodCommitBatch is the method name for committing a batch (with blob when applicable) MethodCommitBatch = "commitBatch" + // MethodCommitState is the method name for recommitting batch state using stored blob hash (no blob in tx) + MethodCommitState = "commitState" // MethodFinalizeBatch is the method name for finalizing a batch MethodFinalizeBatch = "finalizeBatch" ) + +// IsCommitLikeMethod returns true for commitBatch or commitState (same calldata shape for batch index parsing). +func IsCommitLikeMethod(method string) bool { + return method == MethodCommitBatch || method == MethodCommitState +} diff --git a/tx-submitter/flags/flags.go b/tx-submitter/flags/flags.go index 2dedec0fe..cdbf1405d 100644 --- a/tx-submitter/flags/flags.go +++ b/tx-submitter/flags/flags.go @@ -331,6 +331,22 @@ var ( Usage: "Enable seal batch", EnvVar: prefixEnvVar("SEAL_BATCH"), } + + // max blob count per batch + MaxBlobCountFlag = cli.IntFlag{ + Name: "max_blob_count", + Usage: "Maximum number of blobs per batch submission (1-6)", + Value: 6, + EnvVar: prefixEnvVar("MAX_BLOB_COUNT"), + } + + // batch v2 upgrade time + BatchV2UpgradeTimeFlag = cli.Uint64Flag{ + Name: "batch_v2_upgrade_time", + Usage: "Unix timestamp at which V2 multi-blob batch format is activated (0 = disabled)", + Value: 0, + EnvVar: prefixEnvVar("BATCH_V2_UPGRADE_TIME"), + } ) var requiredFlags = []cli.Flag{ @@ -391,6 +407,8 @@ var optionalFlags = []cli.Flag{ BlockNotIncreasedThreshold, SealBatch, + MaxBlobCountFlag, + BatchV2UpgradeTimeFlag, } // Flags contains the list of configuration options available to the binary. diff --git a/tx-submitter/go.mod b/tx-submitter/go.mod index b4a224dc1..2d9ada3d3 100644 --- a/tx-submitter/go.mod +++ b/tx-submitter/go.mod @@ -32,8 +32,6 @@ require ( github.com/edsrzf/mmap-go v1.1.0 // indirect github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect - github.com/go-kit/kit v0.12.0 // indirect - github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-resty/resty/v2 v2.17.2 // indirect github.com/go-stack/stack v1.8.1 // indirect diff --git a/tx-submitter/go.sum b/tx-submitter/go.sum index 36b67e6b6..8e8331539 100644 --- a/tx-submitter/go.sum +++ b/tx-submitter/go.sum @@ -63,14 +63,11 @@ github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4 github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= -github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= -github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= -github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= -github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= diff --git a/tx-submitter/iface/client.go b/tx-submitter/iface/client.go index 6fafffdac..2081355db 100644 --- a/tx-submitter/iface/client.go +++ b/tx-submitter/iface/client.go @@ -38,6 +38,11 @@ type L2Clients struct { Clients []L2Client } +// Len returns the number of configured L2 clients. +func (c *L2Clients) Len() int { + return len(c.Clients) +} + // getFirstClient returns the first available client, or an error if no clients are available func (c *L2Clients) getFirstClient() (L2Client, error) { if len(c.Clients) == 0 { diff --git a/tx-submitter/iface/rollup.go b/tx-submitter/iface/rollup.go index afa7d46a2..9a60a64b5 100644 --- a/tx-submitter/iface/rollup.go +++ b/tx-submitter/iface/rollup.go @@ -18,6 +18,7 @@ type IRollup interface { BatchInsideChallengeWindow(opts *bind.CallOpts, batchIndex *big.Int) (bool, error) BatchExist(opts *bind.CallOpts, batchIndex *big.Int) (bool, error) CommittedBatches(opts *bind.CallOpts, batchIndex *big.Int) ([32]byte, error) + BatchBlobVersionedHashes(opts *bind.CallOpts, batchIndex *big.Int) ([32]byte, error) BatchDataStore(opts *bind.CallOpts, batchIndex *big.Int) (struct { OriginTimestamp *big.Int FinalizeTimestamp *big.Int diff --git a/tx-submitter/mock/rollup.go b/tx-submitter/mock/rollup.go index dbf424a59..cf889c6a4 100644 --- a/tx-submitter/mock/rollup.go +++ b/tx-submitter/mock/rollup.go @@ -1,6 +1,7 @@ package mock import ( + "errors" "math/big" "github.com/morph-l2/go-ethereum/core/types" @@ -65,6 +66,11 @@ func (m *MockRollup) CommittedBatches(opts *bind.CallOpts, batchIndex *big.Int) return [32]byte{}, nil } +// BatchBlobVersionedHashes implements IRollup (no stored hash by default) +func (m *MockRollup) BatchBlobVersionedHashes(opts *bind.CallOpts, batchIndex *big.Int) ([32]byte, error) { + return [32]byte{}, nil +} + // BatchDataStore implements IRollup func (m *MockRollup) BatchDataStore(opts *bind.CallOpts, batchIndex *big.Int) (struct { OriginTimestamp *big.Int @@ -87,7 +93,7 @@ func (m *MockRollup) BatchDataStore(opts *bind.CallOpts, batchIndex *big.Int) (s // FilterCommitBatch implements IRollup func (m *MockRollup) FilterCommitBatch(opts *bind.FilterOpts, batchIndex []*big.Int, batchHash [][32]byte) (*bindings.RollupCommitBatchIterator, error) { - return nil, nil + return nil, errors.New("FilterCommitBatch not implemented in mock") } // FilterFinalizeBatch implements IRollup diff --git a/tx-submitter/services/pendingtx.go b/tx-submitter/services/pendingtx.go index fc5ac18c2..b94735b94 100644 --- a/tx-submitter/services/pendingtx.go +++ b/tx-submitter/services/pendingtx.go @@ -18,13 +18,6 @@ import ( "github.com/morph-l2/go-ethereum/log" ) -const ( - // MethodCommitBatch is the method name for committing a batch - MethodCommitBatch = "commitBatch" - // MethodFinalizeBatch is the method name for finalizing a batch - MethodFinalizeBatch = "finalizeBatch" -) - // Journal defines the interface for transaction journaling type Journal interface { Init() error @@ -43,21 +36,16 @@ type PendingTxs struct { pindex uint64 // pending batch index pfinalize uint64 - commitBatchId []byte - finalizeBatchId []byte - journal Journal } -// NewPendingTxs creates a new PendingTxs instance -func NewPendingTxs(commitBatchMethodId, finalizeBatchMethodId []byte, journal Journal) *PendingTxs { - pt := &PendingTxs{ - txinfos: make(map[common.Hash]*types.TxRecord), - journal: journal, - commitBatchId: commitBatchMethodId, - finalizeBatchId: finalizeBatchMethodId, +// NewPendingTxs creates a new PendingTxs instance. +// Commit-like txs (commitBatch / commitState) are detected via utils.ParseMethod + constants.IsCommitLikeMethod, not stored method IDs. +func NewPendingTxs(journal Journal) *PendingTxs { + return &PendingTxs{ + txinfos: make(map[common.Hash]*types.TxRecord), + journal: journal, } - return pt } // Store persists a transaction to the journal @@ -131,6 +119,13 @@ func (pt *PendingTxs) GetAll() []*types.TxRecord { return pt.getAll() } +// Len returns the number of pending transactions (thread-safe). +func (pt *PendingTxs) Len() int { + pt.mu.RLock() + defer pt.mu.RUnlock() + return len(pt.txinfos) +} + func (pt *PendingTxs) getAll() []*types.TxRecord { txs := make([]*types.TxRecord, 0, len(pt.txinfos)) for _, tx := range pt.txinfos { @@ -217,7 +212,7 @@ func (pt *PendingTxs) GetPFinalize() uint64 { // ExistedIndex checks if a batch index exists func (pt *PendingTxs) ExistedIndex(index uint64) bool { - txs := pt.GetAll() // already has RLock + txs := pt.GetAll() // snapshot taken under RLock inside GetAll; caller does not hold the mutex abi, err := bindings.RollupMetaData.GetAbi() if err != nil { log.Error("Failed to get ABI", "err", err) @@ -226,7 +221,7 @@ func (pt *PendingTxs) ExistedIndex(index uint64) bool { for i := len(txs) - 1; i >= 0; i-- { tx := txs[i].Tx - if utils.ParseMethod(tx, abi) == constants.MethodCommitBatch { + if constants.IsCommitLikeMethod(utils.ParseMethod(tx, abi)) { pindex := utils.ParseParentBatchIndex(tx.Data()) + 1 if index == pindex { return true @@ -252,7 +247,7 @@ func (pt *PendingTxs) Recover(txs []*ethtypes.Transaction, abi *abi.ABI) error { // Get batch index based on method var batchIndex uint64 - if method == constants.MethodCommitBatch { + if constants.IsCommitLikeMethod(method) { batchIndex = utils.ParseParentBatchIndex(tx.Data()) + 1 if batchIndex > maxCommitBatchIndex { maxCommitBatchIndex = batchIndex @@ -281,17 +276,31 @@ func (pt *PendingTxs) Recover(txs []*ethtypes.Transaction, abi *abi.ABI) error { "type", tx.Type(), ) - if err := pt.Add(tx); err != nil { - return fmt.Errorf("failed to add tx during recovery: %w", err) + // Add to in-memory map only; do not write to journal yet. + // The original journal data is preserved until dump() succeeds below, + // so a crash here is safe — the next restart will re-read the original entries. + pt.mu.Lock() + pt.txinfos[tx.Hash()] = &types.TxRecord{ + Tx: tx, + SendTime: uint64(time.Now().Unix()), + QueryTimes: 0, + Confirmed: false, } + pt.mu.Unlock() } pt.SetPindex(maxCommitBatchIndex) pt.SetPFinalize(maxFinalizeBatchIndex) pt.SetNonce(txs[len(txs)-1].Nonce()) + // Rewrite the journal with the deduplicated in-memory set. + // This replaces any duplicate entries accumulated by previous buggy restarts. + if err := pt.dump(); err != nil { + return fmt.Errorf("failed to rewrite journal after recovery: %w", err) + } + log.Info("Recovered from mempool", - "tx_count", len(txs), + "tx_count", len(pt.txinfos), "max_batch_index", maxCommitBatchIndex, "max_finalize_index", maxFinalizeBatchIndex, "max_nonce", pt.GetNonce(), diff --git a/tx-submitter/services/reorg.go b/tx-submitter/services/reorg.go index 61c65d68f..8ba385a10 100644 --- a/tx-submitter/services/reorg.go +++ b/tx-submitter/services/reorg.go @@ -21,7 +21,6 @@ type ReorgDetector struct { maxHistory int l1Client iface.Client - metrics iface.IMetrics } type blockInfo struct { @@ -29,12 +28,11 @@ type blockInfo struct { hash common.Hash } -func NewReorgDetector(l1Client iface.Client, metrics iface.IMetrics) *ReorgDetector { +func NewReorgDetector(l1Client iface.Client) *ReorgDetector { return &ReorgDetector{ blockHistory: make([]blockInfo, 0), - maxHistory: 5, // Track last 50 blocks + maxHistory: 5, // Track last 5 blocks l1Client: l1Client, - metrics: metrics, } } @@ -77,10 +75,6 @@ func (r *ReorgDetector) DetectReorg(ctx context.Context) (bool, uint64, error) { "new_hash", block.Hash(), "block_number", info.number) - // Update metrics - r.metrics.IncReorgs() - r.metrics.SetReorgDepth(float64(reorgDepth)) - // Truncate history before reorg point and rebuild r.blockHistory = r.blockHistory[:i] err = r.updateHistory(ctx) diff --git a/tx-submitter/services/rollup.go b/tx-submitter/services/rollup.go index 20bf0ca4e..92e02f69e 100644 --- a/tx-submitter/services/rollup.go +++ b/tx-submitter/services/rollup.go @@ -26,7 +26,8 @@ import ( "github.com/morph-l2/go-ethereum/rpc" "morph-l2/bindings/bindings" - "morph-l2/tx-submitter/batch" + "morph-l2/common/batch" + "morph-l2/common/blob" "morph-l2/tx-submitter/constants" "morph-l2/tx-submitter/db" "morph-l2/tx-submitter/event" @@ -83,7 +84,7 @@ type Rollup struct { eventInfoStorage *event.EventInfoStorage reorgDetector iface.IReorgDetector - ChainConfigMap types.ChainBlobConfigs + ChainConfigMap blob.ChainBlobConfigs } func NewRollup( @@ -106,29 +107,40 @@ func NewRollup( eventInfoStorage *event.EventInfoStorage, l2Caller *types.L2Caller, ) *Rollup { - reorgDetector := NewReorgDetector(l1, metrics) + reorgDetector := NewReorgDetector(l1) r := &Rollup{ - ctx: ctx, - metrics: metrics, - l1RpcClient: l1RpcClient, - L1Client: l1, - Rollup: rollup, - Staking: staking, - L2Clients: l2Clients, - privKey: priKey, - chainId: chainId, - rollupAddr: rollupAddr, - abi: abi, - rotator: rotator, - cfg: cfg, - signer: ethtypes.LatestSignerForChainID(chainId), - externalRsaPriv: rsaPriv, - batchCache: batch.NewBatchCache(nil, l1, l2Clients, rollup, l2Caller, ldb), + ctx: ctx, + metrics: metrics, + l1RpcClient: l1RpcClient, + L1Client: l1, + Rollup: rollup, + Staking: staking, + L2Clients: l2Clients, + privKey: priKey, + chainId: chainId, + rollupAddr: rollupAddr, + abi: abi, + rotator: rotator, + cfg: cfg, + signer: ethtypes.LatestSignerForChainID(chainId), + externalRsaPriv: rsaPriv, + batchCache: batch.NewBatchCache( + nil, + func(blockTimestamp uint64) bool { + return cfg.BatchV2UpgradeTime > 0 && blockTimestamp >= cfg.BatchV2UpgradeTime + }, + cfg.MaxBlobCount, + l1, + &iface.L2Clients{Clients: l2Clients}, + rollup, + l2Caller, + ldb, + ), ldb: ldb, bm: bm, eventInfoStorage: eventInfoStorage, reorgDetector: reorgDetector, - ChainConfigMap: types.ChainConfigMap, + ChainConfigMap: blob.ChainConfigMap, } if !cfg.SealBatch { fetcher := NewBatchFetcher(l2Clients) @@ -151,7 +163,7 @@ func (r *Rollup) Start() error { log.Crit("journal file init failed", "err", err) } // pendingtxs - r.pendingTxs = NewPendingTxs(r.abi.Methods[constants.MethodCommitBatch].ID, r.abi.Methods[constants.MethodFinalizeBatch].ID, jn) + r.pendingTxs = NewPendingTxs(jn) txs, err := jn.ParseAllTxs() if err != nil { log.Crit("parse l1 mempool error", "error", err) @@ -298,10 +310,15 @@ func (r *Rollup) Start() error { func (r *Rollup) ProcessTx() error { // Check for reorgs first with exponential backoff retry - _, _, err := r.detectReorgWithRetry() + hasReorg, depth, err := r.detectReorgWithRetry() if err != nil { log.Warn("Failed to check for reorgs", "error", err) } + if hasReorg { + if err := r.handleReorg(depth); err != nil { + log.Warn("Post-reorg handling failed", "error", err) + } + } // Get all local transactions txRecords := r.pendingTxs.GetAll() @@ -312,8 +329,20 @@ func (r *Rollup) ProcessTx() error { // Check if this submitter should process transactions if err = r.checkSubmitterTurn(); err != nil { if errors.Is(err, errNotMyTurn) { + // If rotator is not configured or not yet initialized, just skip this round safely. + if r.rotator == nil || r.rotator.startTime == nil || r.rotator.epoch == nil { + log.Info("Awaiting turn for transaction processing, but rotator state is not initialized", + "has_rotator", r.rotator != nil) + return nil + } + // Get current submitter index for logging - activeSubmitter, activeIndex, _ := r.rotator.CurrentSubmitter(r.L2Clients, r.Staking) + activeSubmitter, activeIndex, rotErr := r.rotator.CurrentSubmitter(r.L2Clients, r.Staking) + if rotErr != nil || activeSubmitter == nil { + log.Warn("Failed to get current submitter while awaiting turn", + "error", rotErr) + return nil + } // Calculate rotation timing information past := (time.Now().Unix() - r.rotator.startTime.Int64()) % r.rotator.epoch.Int64() @@ -366,9 +395,11 @@ func (r *Rollup) detectReorgWithRetry() (bool, uint64, error) { var errNotMyTurn = errors.New("not my turn") func (r *Rollup) checkSubmitterTurn() error { - if r.cfg.PriorityRollup { + // If we are in priority rollup mode or rotator is not configured, always allow processing. + if r.cfg.PriorityRollup || r.rotator == nil { return nil } + activeSubmitter, submitterIndex, err := r.rotator.CurrentSubmitter(r.L2Clients, r.Staking) if err != nil { return fmt.Errorf("rollup: get current submitter err, %w", err) @@ -379,6 +410,11 @@ func (r *Rollup) checkSubmitterTurn() error { isMyTurn := activeAddress == myAddress // Calculate rotation timing information + if r.rotator.startTime == nil || r.rotator.epoch == nil { + log.Warn("rotator state not initialized, skipping submitter turn check", + "has_rotator", r.rotator != nil) + return errNotMyTurn + } past := (time.Now().Unix() - r.rotator.startTime.Int64()) % r.rotator.epoch.Int64() start := time.Now().Unix() - past end := start + r.rotator.epoch.Int64() @@ -409,11 +445,13 @@ func (r *Rollup) checkSubmitterTurn() error { return nil } -// Handle chain reorganization +// Handle chain reorganization (metrics + pending pool; DetectReorg only detects and updates block history). func (r *Rollup) handleReorg(depth uint64) error { - // Update metrics r.metrics.SetReorgDepth(float64(depth)) r.metrics.IncReorgs() + if r.pendingTxs != nil { + r.pendingTxs.ClearConfirmedTxs() + } return nil } @@ -467,7 +505,7 @@ func (r *Rollup) processSingleTx(txRecord *types.TxRecord) error { r.metrics.IncTxConfirmed(method) return nil } - return r.handleConfirmedTx(txRecord, rtx, method) + return r.handleConfirmedTx(txRecord, rtx, status, currentBlock) case txStatusMissing: return r.handleMissingTx(txRecord, rtx, method) default: @@ -481,7 +519,7 @@ func (r *Rollup) updateFeeMetrics(tx *ethtypes.Transaction, receipt *ethtypes.Re txFeeFloat, _ := txFeeEth.Float64() // Update metrics based on transaction type - if method == constants.MethodCommitBatch { + if constants.IsCommitLikeMethod(method) { r.rollupFeeSum += txFeeFloat r.metrics.RollupCostSum.Add(txFeeFloat) r.metrics.RollupCost.Set(txFeeFloat) @@ -542,19 +580,8 @@ func (r *Rollup) getTxStatus(tx *ethtypes.Transaction) (*txStatus, error) { } func (r *Rollup) handlePendingTx(txRecord *types.TxRecord, tx *ethtypes.Transaction, method string) error { - // Check for timeout - if txRecord.SendTime+uint64(r.cfg.TxTimeout.Seconds()) < uint64(time.Now().Unix()) { - log.Info("Transaction timed out", - "tx", tx.Hash().Hex(), - "nonce", tx.Nonce(), - "method", method) - - // Try to replace the transaction with higher gas price - return r.replaceTimedOutTx(tx) - } - - // Check if transaction might fail - if method == constants.MethodCommitBatch { + // Obsolete / doomed txs: cancel before timeout handling so we do not resubmit a tx that will revert. + if constants.IsCommitLikeMethod(method) { batchIndex := utils.ParseParentBatchIndex(tx.Data()) + 1 lastCommitted, err := r.Rollup.LastCommittedBatchIndex(nil) if err != nil { @@ -562,13 +589,11 @@ func (r *Rollup) handlePendingTx(txRecord *types.TxRecord, tx *ethtypes.Transact } if batchIndex <= lastCommitted.Uint64() { - // This batch is already committed by another submitter log.Info("Batch already committed by another submitter, trying to cancel transaction", "batch_index", batchIndex, "last_committed", lastCommitted.Uint64(), "tx_hash", tx.Hash().String()) - // Try to cancel the transaction since it will fail cancelTx, err := r.CancelTx(tx) if err != nil { log.Error("Failed to cancel commit batch transaction", @@ -591,9 +616,7 @@ func (r *Rollup) handlePendingTx(txRecord *types.TxRecord, tx *ethtypes.Transact if err := r.pendingTxs.Remove(tx.Hash()); err != nil { log.Error("failed to remove transaction", "hash", tx.Hash().String(), "error", err) } - if err := r.pendingTxs.Add(cancelTx); err != nil { - log.Error("failed to add cancel transaction", "hash", cancelTx.Hash().String(), "error", err) - } + // CancelTx -> SendTx already adds the cancel tx to the pool return nil } } else if method == constants.MethodFinalizeBatch { @@ -604,13 +627,11 @@ func (r *Rollup) handlePendingTx(txRecord *types.TxRecord, tx *ethtypes.Transact } if batchIndex <= lastFinalized.Uint64() { - // This batch is already finalized by another submitter log.Info("Batch already finalized by another submitter, trying to cancel transaction", "batch_index", batchIndex, "last_finalized", lastFinalized.Uint64(), "tx_hash", tx.Hash().String()) - // Try to cancel the transaction since it will fail cancelTx, err := r.CancelTx(tx) if err != nil { log.Error("Failed to cancel finalize batch transaction", @@ -633,13 +654,19 @@ func (r *Rollup) handlePendingTx(txRecord *types.TxRecord, tx *ethtypes.Transact if err := r.pendingTxs.Remove(tx.Hash()); err != nil { log.Error("failed to remove transaction", "hash", tx.Hash().String(), "error", err) } - if err := r.pendingTxs.Add(cancelTx); err != nil { - log.Error("failed to add cancel transaction", "hash", cancelTx.Hash().String(), "error", err) - } + // CancelTx -> SendTx already adds the cancel tx to the pool return nil } } + if txRecord.SendTime+uint64(r.cfg.TxTimeout.Seconds()) < uint64(time.Now().Unix()) { + log.Info("Transaction timed out", + "tx", tx.Hash().Hex(), + "nonce", tx.Nonce(), + "method", method) + return r.replaceTimedOutTx(tx) + } + return nil } @@ -661,9 +688,7 @@ func (r *Rollup) replaceTimedOutTx(tx *ethtypes.Transaction) error { if err := r.pendingTxs.Remove(tx.Hash()); err != nil { log.Error("failed to remove transaction", "hash", tx.Hash().String(), "error", err) } - if err := r.pendingTxs.Add(newTx); err != nil { - log.Error("failed to add new transaction", "hash", newTx.Hash().String(), "error", err) - } + // ReSubmitTx -> SendTx already adds newTx to the pool return nil } @@ -722,12 +747,6 @@ func (r *Rollup) handleDiscardedTx(txRecord *types.TxRecord, tx *ethtypes.Transa if err = r.pendingTxs.Remove(tx.Hash()); err != nil { log.Error("failed to remove transaction", "hash", tx.Hash().String(), "error", err) } - record := r.pendingTxs.GetTxRecord(replacedTx.Hash()) - if record == nil { - if err = r.pendingTxs.Add(replacedTx); err != nil { - log.Error("failed to add replaced transaction", "hash", replacedTx.Hash().String(), "error", err) - } - } log.Info("Successfully resubmitted discarded transaction", "old_tx", tx.Hash().String(), "new_tx", replacedTx.Hash().String(), @@ -736,17 +755,12 @@ func (r *Rollup) handleDiscardedTx(txRecord *types.TxRecord, tx *ethtypes.Transa return nil } -// handleConfirmedTx handles a confirmed transaction -func (r *Rollup) handleConfirmedTx(txRecord *types.TxRecord, tx *ethtypes.Transaction, txType string) error { - status, err := r.getTxStatus(tx) - if err != nil { - return fmt.Errorf("get tx status error: %w", err) - } - - // Get the current block number for confirmation count - currentBlock, err := r.L1Client.BlockNumber(context.Background()) - if err != nil { - return fmt.Errorf("get current block number error: %w", err) +// handleConfirmedTx handles a confirmed transaction. +// status and currentBlock must come from the same processSingleTx pass as getTxStatus / BlockNumber +// so a reorg between polls cannot leave receipt nil while we still treat the tx as confirmed-on-chain. +func (r *Rollup) handleConfirmedTx(txRecord *types.TxRecord, tx *ethtypes.Transaction, status *txStatus, currentBlock uint64) error { + if status == nil || status.receipt == nil { + return nil } confirmations := currentBlock - status.receipt.BlockNumber.Uint64() @@ -758,7 +772,7 @@ func (r *Rollup) handleConfirmedTx(txRecord *types.TxRecord, tx *ethtypes.Transa method := utils.ParseMethod(tx, r.abi) if status.receipt.Status == ethtypes.ReceiptStatusFailed { - if method == constants.MethodCommitBatch { + if constants.IsCommitLikeMethod(method) { batchIndex := utils.ParseParentBatchIndex(tx.Data()) + 1 lastCommitted, err := r.Rollup.LastCommittedBatchIndex(nil) if err != nil { @@ -788,23 +802,15 @@ func (r *Rollup) handleConfirmedTx(txRecord *types.TxRecord, tx *ethtypes.Transa } } } else { // Transaction succeeded - // Get current block number for confirmation count only for successful transactions - currentBlock, err = r.L1Client.BlockNumber(context.Background()) - if err != nil { - return fmt.Errorf("get current block number error: %w", err) - } - confirmations = currentBlock - status.receipt.BlockNumber.Uint64() - - if method == constants.MethodCommitBatch { + if constants.IsCommitLikeMethod(method) { batchIndex := utils.ParseParentBatchIndex(tx.Data()) + 1 - log.Info("Successfully committed batch", "batch_index", batchIndex, "tx_hash", tx.Hash().String(), "block_number", status.receipt.BlockNumber.Uint64(), "gas_used", status.receipt.GasUsed, "confirm", confirmations) + log.Info("Successfully committed batch", "method", method, "batch_index", batchIndex, "tx_hash", tx.Hash().String(), "block_number", status.receipt.BlockNumber.Uint64(), "gas_used", status.receipt.GasUsed, "confirm", confirmations) } else if method == constants.MethodFinalizeBatch { batchIndex := utils.ParseFBatchIndex(tx.Data()) if batchIndex > 0 { if r.cfg.SealBatch { - err = r.batchCache.Delete(batchIndex - 1) - if err != nil { - log.Error("failed to delete batch", "batch_index", batchIndex, "tx_hash", tx.Hash().String()) + if delErr := r.batchCache.Delete(batchIndex - 1); delErr != nil { + log.Error("failed to delete batch", "batch_index", batchIndex, "tx_hash", tx.Hash().String(), "error", delErr) } } else { r.batchCacheLegacy.Delete(batchIndex - 1) @@ -830,7 +836,7 @@ func (r *Rollup) finalize() error { return fmt.Errorf("get last committed error:%v", err) } - target := big.NewInt(int64(r.pendingTxs.pfinalize + 1)) + target := big.NewInt(int64(r.pendingTxs.GetPFinalize() + 1)) if target.Cmp(lastFinalized) <= 0 { target = new(big.Int).Add(lastFinalized, big.NewInt(1)) } @@ -904,7 +910,7 @@ func (r *Rollup) finalize() error { return fmt.Errorf("get gas tip and cap error:%v", err) } - gas, err := r.EstimateGas(r.WalletAddr(), r.rollupAddr, calldata, feecap, tip) + gas, err := r.EstimateGas(r.WalletAddr(), r.rollupAddr, calldata, feecap, tip, nil, nil) if err != nil { log.Warn("estimate finalize tx gas error", "error", err, @@ -921,14 +927,9 @@ func (r *Rollup) finalize() error { // gas bump gas = r.BumpGas(gas) - var nonce uint64 - if r.pendingTxs.pnonce != 0 { - nonce = r.pendingTxs.pnonce + 1 - } else { - nonce, err = r.L1Client.PendingNonceAt(context.Background(), r.WalletAddr()) - if err != nil { - return fmt.Errorf("query layer1 nonce error:%v", err.Error()) - } + nonce := r.getNextNonce() + if nonce == 0 { + return fmt.Errorf("failed to get next nonce") } tx := ethtypes.NewTx(ðtypes.DynamicFeeTx{ @@ -981,9 +982,7 @@ func (r *Rollup) finalize() error { r.pendingTxs.SetNonce(signedTx.Nonce()) r.pendingTxs.SetPFinalize(target.Uint64()) - if err = r.pendingTxs.Add(signedTx); err != nil { - log.Error("failed to add signed transaction", "hash", signedTx.Hash().String(), "error", err) - } + // SendTx already adds signedTx to the pending pool } return nil } @@ -1067,9 +1066,9 @@ func (r *Rollup) rollup() error { } } - if len(r.pendingTxs.txinfos) > int(r.cfg.MaxTxsInPendingPool) { + if pendingN := r.pendingTxs.Len(); pendingN > int(r.cfg.MaxTxsInPendingPool) { log.Info("Pending pool full", - "current_size", len(r.pendingTxs.txinfos), + "current_size", pendingN, "max_size", r.cfg.MaxTxsInPendingPool) return nil } @@ -1082,14 +1081,16 @@ func (r *Rollup) rollup() error { } cindex := cindexBig.Uint64() batchIndex = cindex + 1 - if len(r.pendingTxs.getAll()) != 0 && r.pendingTxs.pindex != 0 { - batchIndex = max(cindex, r.pendingTxs.pindex) + 1 + pendingN := r.pendingTxs.Len() + pidx := r.pendingTxs.GetPindex() + if pendingN != 0 && pidx != 0 { + batchIndex = max(cindex, pidx) + 1 } log.Debug("Batch status", "last_committed", cindex, "next_batch", batchIndex, - "current_processing", r.pendingTxs.pindex) + "current_processing", pidx) if r.pendingTxs.ExistedIndex(batchIndex) { log.Debug("Batch already committed", @@ -1123,19 +1124,46 @@ func (r *Rollup) rollup() error { WithdrawalRoot: rpcRollupBatch.WithdrawRoot, } + storedBlobHash, err := r.Rollup.BatchBlobVersionedHashes(nil, big.NewInt(int64(batchIndex))) + if err != nil { + return fmt.Errorf("get batch blob versioned hash: %w", err) + } + useCommitState := storedBlobHash != [32]byte{} + if useCommitState { + if err := r.validateStoredBlobAgainstSealedHeader(storedBlobHash, batchIndex); err != nil { + return err + } + log.Info("Using commitState (L1 stored blob hash matches sealed header)", + "batch_index", batchIndex, + "stored_blob_hash", common.Hash(storedBlobHash).Hex()) + } + // tip and cap tip, gasFeeCap, blobFee, head, err := r.GetGasTipAndCap() if err != nil { return fmt.Errorf("get gas tip and cap error:%v", err) } - // calldata encode - calldata, err := r.abi.Pack("commitBatch", rollupBatch, *signature) + // calldata encode — commitState reuses stored blob hash and must not carry blob data in tx + var calldata []byte + if useCommitState { + calldata, err = r.abi.Pack("commitState", rollupBatch, *signature) + } else { + calldata, err = r.abi.Pack("commitBatch", rollupBatch, *signature) + } if err != nil { return fmt.Errorf("pack calldata error:%v", err) } - // Estimate gas for transaction - gas, err := r.EstimateGas(r.WalletAddr(), r.rollupAddr, calldata, gasFeeCap, tip) + // Estimate gas for transaction. + // For blob batches (e.g. V2), include BlobHashes/BlobGasFeeCap so `blobhash(i)` + // is available during eth_estimateGas simulation. + var estimateBlobHashes []common.Hash + var estimateBlobFeeCap *big.Int + if !useCommitState && len(rpcRollupBatch.Sidecar.Blobs) > 0 { + estimateBlobHashes = blob.BlobHashes(rpcRollupBatch.Sidecar.Blobs, rpcRollupBatch.Sidecar.Commitments) + estimateBlobFeeCap = blobFee + } + gas, err := r.EstimateGas(r.WalletAddr(), r.rollupAddr, calldata, gasFeeCap, tip, estimateBlobHashes, estimateBlobFeeCap) if err != nil { log.Warn("Estimate gas failed", "batch_index", batchIndex, "error", err) // Use estimation based on L1 message count @@ -1160,8 +1188,13 @@ func (r *Rollup) rollup() error { return fmt.Errorf("failed to get next nonce") } - // Create and sign transaction - tx, err := r.createRollupTx(rpcRollupBatch, nonce, gas, tip, gasFeeCap, blobFee, calldata, head) + // Create and sign transaction (commitState is always type-2, never blob) + var tx *ethtypes.Transaction + if useCommitState { + tx, err = r.createDynamicFeeTx(nonce, gas, tip, gasFeeCap, calldata) + } else { + tx, err = r.createRollupTx(rpcRollupBatch, nonce, gas, tip, gasFeeCap, blobFee, calldata, head) + } if err != nil { return fmt.Errorf("failed to create rollup tx: %w", err) } @@ -1182,23 +1215,24 @@ func (r *Rollup) rollup() error { // Update pending state r.pendingTxs.SetPindex(batchIndex) r.pendingTxs.SetNonce(tx.Nonce()) - if err = r.pendingTxs.Add(signedTx); err != nil { - log.Error("Failed to track transaction", "error", err) - } + // SendTx already adds signedTx to the pending pool return nil } func (r *Rollup) getNextNonce() uint64 { - if r.pendingTxs.pnonce != 0 { - return r.pendingTxs.pnonce + 1 - } - nonce, err := r.L1Client.PendingNonceAt(context.Background(), r.WalletAddr()) if err != nil { log.Error("Failed to get nonce", "error", err) return 0 } + if r.pendingTxs.Len() == 0 { + return nonce + } + pn := r.pendingTxs.GetNonce() + if pn+1 > nonce { + return pn + 1 + } return nonce } @@ -1209,23 +1243,23 @@ func (r *Rollup) createRollupTx(batch *eth.RPCRollupBatch, nonce, gas uint64, ti return r.createDynamicFeeTx(nonce, gas, tip, gasFeeCap, calldata) } -func (r *Rollup) createBlobTx(batch *eth.RPCRollupBatch, nonce, gas uint64, tip, gasFeeCap, blobFee *big.Int, calldata []byte, head *ethtypes.Header) (*ethtypes.Transaction, error) { - versionedHashes := types.BlobHashes(batch.Sidecar.Blobs, batch.Sidecar.Commitments) +func (r *Rollup) createBlobTx(rpcBatch *eth.RPCRollupBatch, nonce, gas uint64, tip, gasFeeCap, blobFee *big.Int, calldata []byte, head *ethtypes.Header) (*ethtypes.Transaction, error) { + versionedHashes := blob.BlobHashes(rpcBatch.Sidecar.Blobs, rpcBatch.Sidecar.Commitments) sidecar := ðtypes.BlobTxSidecar{ - Blobs: batch.Sidecar.Blobs, - Commitments: batch.Sidecar.Commitments, + Blobs: rpcBatch.Sidecar.Blobs, + Commitments: rpcBatch.Sidecar.Commitments, } - switch types.DetermineBlobVersion(head, r.chainId.Uint64()) { + switch blob.DetermineBlobVersion(head, r.chainId.Uint64()) { case ethtypes.BlobSidecarVersion0: sidecar.Version = ethtypes.BlobSidecarVersion0 - proof, err := types.MakeBlobProof(sidecar.Blobs, sidecar.Commitments) + proof, err := blob.MakeBlobProof(sidecar.Blobs, sidecar.Commitments) if err != nil { return nil, fmt.Errorf("gen blob proof failed %v", err) } sidecar.Proofs = proof case ethtypes.BlobSidecarVersion1: sidecar.Version = ethtypes.BlobSidecarVersion1 - proof, err := types.MakeCellProof(sidecar.Blobs) + proof, err := blob.MakeCellProof(sidecar.Blobs) if err != nil { return nil, fmt.Errorf("gen cell proof failed %v", err) } @@ -1260,6 +1294,119 @@ func (r *Rollup) createDynamicFeeTx(nonce, gas uint64, tip, gasFeeCap *big.Int, }), nil } +// validateStoredBlobAgainstSealedHeader requires L1 stored blob hash to match the sealed +// header blob field (offset 57). Sealed headers always carry a non-zero semantic value +// (e.g. EmptyVersionedHash); callers must not skip validation when the field decodes to zero. +func (r *Rollup) validateStoredBlobAgainstSealedHeader(stored [32]byte, batchIndex uint64) error { + if stored == ([32]byte{}) { + return nil + } + if !r.cfg.SealBatch || r.batchCache == nil { + return nil + } + header, ok := r.batchCache.GetSealedBatchHeader(batchIndex) + if !ok || header == nil { + return fmt.Errorf("commitState: sealed batch header %d not in cache", batchIndex) + } + headerBlob, err := header.BlobCommitHash() + if err != nil { + return fmt.Errorf("commitState: batch %d header blob field: %w", batchIndex, err) + } + if common.Hash(stored) != headerBlob { + return fmt.Errorf( + "commitState: L1 stored blob hash %s != sealed header %s (batch %d)", + common.Hash(stored).Hex(), headerBlob.Hex(), batchIndex, + ) + } + return nil +} + +// tryRebuildRollupCommitTx aligns an in-flight commit-like tx with L1 blob-hash state: +// - stored blob versioned hash set -> must use commitState (no blob), upgrading commitBatch / blob txs +// - stored hash cleared -> must use commitBatch (+ blob sidecar when present), downgrading stale commitState +// +// Returns handled=true when newTx must be used and the default ReSubmitTx copy path must be skipped. +func (r *Rollup) tryRebuildRollupCommitTx(tx *ethtypes.Transaction, tip, gasFeeCap, blobFeeCap *big.Int, head *ethtypes.Header) (newTx *ethtypes.Transaction, handled bool, err error) { + method := utils.ParseMethod(tx, r.abi) + if !constants.IsCommitLikeMethod(method) { + return nil, false, nil + } + batchIndex := utils.ParseParentBatchIndex(tx.Data()) + 1 + stored, err := r.Rollup.BatchBlobVersionedHashes(nil, big.NewInt(int64(batchIndex))) + if err != nil { + return nil, false, err + } + if err := r.validateStoredBlobAgainstSealedHeader(stored, batchIndex); err != nil { + return nil, true, err + } + if stored != ([32]byte{}) { + if method == constants.MethodCommitState && tx.Type() == ethtypes.DynamicFeeTxType { + return nil, false, nil + } + } else { + if method == constants.MethodCommitBatch { + return nil, false, nil + } + } + + var rpcRollupBatch *eth.RPCRollupBatch + exist := true + if r.cfg.SealBatch { + rpcRollupBatch, err = r.batchCache.Get(batchIndex) + } else { + rpcRollupBatch, exist = r.batchCacheLegacy.Get(batchIndex) + } + if err != nil || !exist || rpcRollupBatch == nil { + return nil, true, fmt.Errorf("cannot rebuild rollup commit tx: batch %d not in cache (err=%v)", batchIndex, err) + } + signature, err := r.buildSignatureInput(rpcRollupBatch) + if err != nil { + return nil, true, err + } + rollupBatch := bindings.IRollupBatchDataInput{ + Version: uint8(rpcRollupBatch.Version), + ParentBatchHeader: rpcRollupBatch.ParentBatchHeader, + LastBlockNumber: rpcRollupBatch.LastBlockNumber, + NumL1Messages: rpcRollupBatch.NumL1Messages, + PrevStateRoot: rpcRollupBatch.PrevStateRoot, + PostStateRoot: rpcRollupBatch.PostStateRoot, + WithdrawalRoot: rpcRollupBatch.WithdrawRoot, + } + + if stored != ([32]byte{}) { + calldata, err := r.abi.Pack("commitState", rollupBatch, *signature) + if err != nil { + return nil, true, err + } + newTx, err = r.createDynamicFeeTx(tx.Nonce(), tx.Gas(), tip, gasFeeCap, calldata) + if err != nil { + return nil, true, err + } + log.Info("Rebuilt pending rollup tx as commitState (stored blob hash on L1)", + "batch_index", batchIndex, + "old_tx_type", tx.Type(), + "old_method", method) + return newTx, true, nil + } + + calldata, err := r.abi.Pack("commitBatch", rollupBatch, *signature) + if err != nil { + return nil, true, err + } + if head == nil { + return nil, true, fmt.Errorf("cannot rebuild commitBatch: nil L1 head") + } + newTx, err = r.createRollupTx(rpcRollupBatch, tx.Nonce(), tx.Gas(), tip, gasFeeCap, blobFeeCap, calldata, head) + if err != nil { + return nil, true, err + } + log.Info("Rebuilt pending rollup tx as commitBatch (no stored blob hash on L1)", + "batch_index", batchIndex, + "old_tx_type", tx.Type(), + "old_method", method) + return newTx, true, nil +} + func (r *Rollup) logTxInfo(tx *ethtypes.Transaction, batchIndex uint64) { log.Info("Rollup transaction created", "batch_index", batchIndex, @@ -1325,11 +1472,11 @@ func (r *Rollup) GetGasTipAndCap() (*big.Int, *big.Int, *big.Int, *ethtypes.Head var blobFee *big.Int if head.ExcessBlobGas != nil { log.Info("market blob fee info", "excess blob gas", *head.ExcessBlobGas) - blobConfig, exist := types.ChainConfigMap[r.chainId.Uint64()] + blobConfig, exist := blob.ChainConfigMap[r.chainId.Uint64()] if !exist { - blobConfig = types.DefaultBlobConfig + blobConfig = blob.DefaultBlobConfig } - blobFeeDenominator := types.GetBlobFeeDenominator(blobConfig, head.Time) + blobFeeDenominator := blob.GetBlobFeeDenominator(blobConfig, head.Time) blobFee = eip4844.CalcBlobFee(*head.ExcessBlobGas, blobFeeDenominator.Uint64()) // Set to 3x to handle blob market congestion blobFee = new(big.Int).Mul(blobFee, big.NewInt(3)) @@ -1549,33 +1696,34 @@ func UpdateGasLimit(tx *ethtypes.Transaction) (*ethtypes.Transaction, error) { return newTx, nil } -// send tx to l1 with business logic check +// SendTx tracks the transaction in the pending pool, then broadcasts it to L1. +// Add runs before send so a broadcast failure never leaves an untracked in-flight nonce. +// If send fails after Add, the tx is removed from the pool and journal. func (r *Rollup) SendTx(tx *ethtypes.Transaction) error { - - // judge tx info is valid if tx == nil { return errors.New("nil tx") } - // l1 health check if r.bm != nil && !r.bm.IsGrowth() { return fmt.Errorf("block not growth in %d blocks time", r.cfg.BlockNotIncreasedThreshold) } - err := sendTx(r.L1Client, r.cfg.TxFeeLimit, tx) - if err != nil { - return err + if r.pendingTxs != nil { + if err := r.pendingTxs.Add(tx); err != nil { + return fmt.Errorf("track tx before send: %w", err) + } } - // after send tx - // add to pending txs - if r.pendingTxs != nil { - if err = r.pendingTxs.Add(tx); err != nil { - log.Error("failed to add transaction", "hash", tx.Hash().String(), "error", err) + if err := sendTx(r.L1Client, r.cfg.TxFeeLimit, tx); err != nil { + if r.pendingTxs != nil { + if remErr := r.pendingTxs.Remove(tx.Hash()); remErr != nil { + log.Error("failed to untrack tx after send failure", + "hash", tx.Hash().String(), "send_err", err, "remove_err", remErr) + } } + return err } return nil - } // send tx to l1 with business logic check @@ -1665,47 +1813,82 @@ func (r *Rollup) ReSubmitTx(resend bool, tx *ethtypes.Transaction) (*ethtypes.Tr } var newTx *ethtypes.Transaction - switch tx.Type() { - case ethtypes.DynamicFeeTxType: - newTx = ethtypes.NewTx(ðtypes.DynamicFeeTx{ - ChainID: tx.ChainId(), - To: tx.To(), - Nonce: tx.Nonce(), - GasFeeCap: gasFeeCap, - GasTipCap: tip, - Gas: tx.Gas(), - Value: tx.Value(), - Data: tx.Data(), - }) - case ethtypes.BlobTxType: - sidecar := tx.BlobTxSidecar() - version := types.DetermineBlobVersion(head, r.chainId.Uint64()) - if sidecar != nil { - if sidecar.Version == ethtypes.BlobSidecarVersion0 && version == ethtypes.BlobSidecarVersion1 { - err = types.BlobSidecarVersionToV1(sidecar) - if err != nil { - return nil, err + if rebuilt, ok, err := r.tryRebuildRollupCommitTx(tx, tip, gasFeeCap, blobFeeCap, head); ok { + if err != nil { + return nil, err + } + newTx = rebuilt + } else if err != nil { + return nil, err + } else { + switch tx.Type() { + case ethtypes.DynamicFeeTxType: + newTx = ethtypes.NewTx(ðtypes.DynamicFeeTx{ + ChainID: tx.ChainId(), + To: tx.To(), + Nonce: tx.Nonce(), + GasFeeCap: gasFeeCap, + GasTipCap: tip, + Gas: tx.Gas(), + Value: tx.Value(), + Data: tx.Data(), + }) + case ethtypes.BlobTxType: + sidecar := tx.BlobTxSidecar() + version := blob.DetermineBlobVersion(head, r.chainId.Uint64()) + if sidecar != nil { + if sidecar.Version == ethtypes.BlobSidecarVersion0 && version == ethtypes.BlobSidecarVersion1 { + err = blob.BlobSidecarVersionToV1(sidecar) + if err != nil { + return nil, err + } } } - } - - newTx = ethtypes.NewTx(ðtypes.BlobTx{ - ChainID: uint256.MustFromBig(tx.ChainId()), - Nonce: tx.Nonce(), - GasTipCap: uint256.MustFromBig(tip), - GasFeeCap: uint256.MustFromBig(gasFeeCap), - Gas: tx.Gas(), - To: *tx.To(), - Value: uint256.MustFromBig(tx.Value()), - Data: tx.Data(), - BlobFeeCap: uint256.MustFromBig(blobFeeCap), - BlobHashes: tx.BlobHashes(), - Sidecar: sidecar, - }) - - default: - return nil, fmt.Errorf("replace unknown tx type:%v", tx.Type()) + newTx = ethtypes.NewTx(ðtypes.BlobTx{ + ChainID: uint256.MustFromBig(tx.ChainId()), + Nonce: tx.Nonce(), + GasTipCap: uint256.MustFromBig(tip), + GasFeeCap: uint256.MustFromBig(gasFeeCap), + Gas: tx.Gas(), + To: *tx.To(), + Value: uint256.MustFromBig(tx.Value()), + Data: tx.Data(), + BlobFeeCap: uint256.MustFromBig(blobFeeCap), + BlobHashes: tx.BlobHashes(), + Sidecar: sidecar, + }) + + default: + return nil, fmt.Errorf("replace unknown tx type:%v", tx.Type()) + + } + } + + // Original tx was not a blob tx, but rebuild (e.g. commitState -> commitBatch) may produce a blob tx. + // In that case blobFeeCap was never bumped above (bump only ran for BlobTxType). Apply the same bump as for blob replacements. + if !resend && newTx != nil && newTx.Type() == ethtypes.BlobTxType && tx.Type() != ethtypes.BlobTxType { + embeddedCap := newTx.BlobGasFeeCap() + if embeddedCap != nil { + bumpedBlob := calcThresholdValue(embeddedCap, true) + if bumpedBlob.Cmp(blobFeeCap) > 0 { + blobFeeCap = bumpedBlob + } + sidecar := newTx.BlobTxSidecar() + newTx = ethtypes.NewTx(ðtypes.BlobTx{ + ChainID: uint256.MustFromBig(newTx.ChainId()), + Nonce: newTx.Nonce(), + GasTipCap: uint256.MustFromBig(newTx.GasTipCap()), + GasFeeCap: uint256.MustFromBig(newTx.GasFeeCap()), + Gas: newTx.Gas(), + To: *newTx.To(), + Value: uint256.MustFromBig(newTx.Value()), + Data: newTx.Data(), + BlobFeeCap: uint256.MustFromBig(blobFeeCap), + BlobHashes: newTx.BlobHashes(), + Sidecar: sidecar, + }) + } } // weiToGwei converts wei value to gwei string representation @@ -1749,14 +1932,23 @@ func (r *Rollup) IsStaker() (bool, error) { return isStaker, nil } -func (r *Rollup) EstimateGas(from, to common.Address, data []byte, feecap *big.Int, tip *big.Int) (uint64, error) { +func (r *Rollup) EstimateGas( + from, to common.Address, + data []byte, + feecap *big.Int, + tip *big.Int, + blobHashes []common.Hash, + blobGasFeeCap *big.Int, +) (uint64, error) { gas, err := r.L1Client.EstimateGas(context.Background(), ethereum.CallMsg{ - From: from, - To: &to, - GasFeeCap: feecap, - GasTipCap: tip, - Data: data, + From: from, + To: &to, + GasFeeCap: feecap, + GasTipCap: tip, + Data: data, + BlobHashes: blobHashes, + BlobGasFeeCap: blobGasFeeCap, }) if err != nil { return 0, fmt.Errorf("call estimate gas error:%v", err) @@ -1838,18 +2030,6 @@ func (r *Rollup) InitFeeMetricsSum() error { return nil } -// ClearPendingTxs clears all pending transactions -func (p *PendingTxs) ClearPendingTxs() { - p.txinfos = make(map[common.Hash]*types.TxRecord) -} - -// MarkUnconfirmed marks a transaction as unconfirmed in the pending pool -func (p *PendingTxs) MarkUnconfirmed(hash common.Hash) { - if txRecord, ok := p.txinfos[hash]; ok { - txRecord.Confirmed = false - } -} - // CancelTx creates a new transaction with empty calldata to cancel the original transaction func (r *Rollup) CancelTx(tx *ethtypes.Transaction) (*ethtypes.Transaction, error) { if tx == nil { diff --git a/tx-submitter/services/rollup_handle_test.go b/tx-submitter/services/rollup_handle_test.go index 465965272..2c3bb3ed3 100644 --- a/tx-submitter/services/rollup_handle_test.go +++ b/tx-submitter/services/rollup_handle_test.go @@ -82,6 +82,7 @@ func setupTestRollup(t *testing.T) (*Rollup, *mock.L1ClientWrapper, *mock.L2Clie TipFeeBump: 100, TxTimeout: 10 * time.Second, PriorityRollup: true, + MaxBlobCount: 6, // required by batch.NewBatchCache (must be > 0) } // Create mock journal @@ -118,7 +119,7 @@ func setupTestRollup(t *testing.T) (*Rollup, *mock.L1ClientWrapper, *mock.L2Clie ) // Initialize pending transactions - rollup.pendingTxs = NewPendingTxs([]byte{}, []byte{}, mockJournal) + rollup.pendingTxs = NewPendingTxs(mockJournal) // Initialize reorg detector // Use the mock implementation for controlled testing diff --git a/tx-submitter/types/blob.go b/tx-submitter/types/blob.go deleted file mode 100644 index d0da2b6bc..000000000 --- a/tx-submitter/types/blob.go +++ /dev/null @@ -1,73 +0,0 @@ -package types - -import ( - "crypto/sha256" - - "github.com/morph-l2/go-ethereum/common" - ethtypes "github.com/morph-l2/go-ethereum/core/types" - "github.com/morph-l2/go-ethereum/crypto/kzg4844" -) - -// BlobHashes computes the blob hashes of the given blobs. -func BlobHashes(blobs []kzg4844.Blob, commitments []kzg4844.Commitment) []common.Hash { - hasher := sha256.New() - h := make([]common.Hash, len(commitments)) - for i := range blobs { - h[i] = kzg4844.CalcBlobHashV1(hasher, &commitments[i]) - } - return h -} - -func MakeBlobProof(blobs []kzg4844.Blob, commitment []kzg4844.Commitment) ([]kzg4844.Proof, error) { - proofs := make([]kzg4844.Proof, len(blobs)) - for i := range blobs { - proof, err := kzg4844.ComputeBlobProof(&blobs[i], commitment[i]) - if err != nil { - return nil, err - } - proofs[i] = proof - } - return proofs, nil -} - -func MakeCellProof(blobs []kzg4844.Blob) ([]kzg4844.Proof, error) { - proofs := make([]kzg4844.Proof, 0, len(blobs)*kzg4844.CellProofsPerBlob) - for _, blob := range blobs { - cellProofs, err := kzg4844.ComputeCellProofs(&blob) - if err != nil { - return nil, err - } - proofs = append(proofs, cellProofs...) - } - return proofs, nil -} - -func DetermineBlobVersion(head *ethtypes.Header, chainID uint64) byte { - if head == nil { - return ethtypes.BlobSidecarVersion0 - } - blobConfig, exist := ChainConfigMap[chainID] - if !exist { - blobConfig = DefaultBlobConfig - } - if blobConfig.OsakaTime != nil && blobConfig.IsOsaka(head.Number, head.Time) { - return ethtypes.BlobSidecarVersion1 - } - return ethtypes.BlobSidecarVersion0 -} - -// BlobSidecarVersionToV1 converts the BlobSidecar to version 1, attaching the cell proofs. -func BlobSidecarVersionToV1(sc *ethtypes.BlobTxSidecar) error { - if sc.Version == ethtypes.BlobSidecarVersion1 { - return nil - } - if sc.Version == ethtypes.BlobSidecarVersion0 { - proofs, err := MakeCellProof(sc.Blobs) - if err != nil { - return err - } - sc.Version = ethtypes.BlobSidecarVersion1 - sc.Proofs = proofs - } - return nil -} diff --git a/tx-submitter/types/blob_compat.go b/tx-submitter/types/blob_compat.go new file mode 100644 index 000000000..01152bea9 --- /dev/null +++ b/tx-submitter/types/blob_compat.go @@ -0,0 +1,54 @@ +package types + +import ( + "math/big" + + "morph-l2/common/blob" + + "github.com/morph-l2/go-ethereum/common" + ethtypes "github.com/morph-l2/go-ethereum/core/types" + "github.com/morph-l2/go-ethereum/crypto/kzg4844" +) + +type BlobFeeConfig = blob.BlobFeeConfig +type BlobConfig = blob.BlobConfig +type ChainBlobConfigs = blob.ChainBlobConfigs + +var ( + ChainConfigMap = blob.ChainConfigMap + DefaultBlobConfig = blob.DefaultBlobConfig + MainnetChainConfig = blob.MainnetChainConfig + HoodiChainConfig = blob.HoodiChainConfig + DevnetChainConfig = blob.DevnetChainConfig + DefaultCancunBlobConfig = blob.DefaultCancunBlobConfig + DefaultPragueBlobConfig = blob.DefaultPragueBlobConfig + DefaultOsakaBlobConfig = blob.DefaultOsakaBlobConfig + DefaultBPO1BlobConfig = blob.DefaultBPO1BlobConfig + DefaultBPO2BlobConfig = blob.DefaultBPO2BlobConfig + DefaultBPO3BlobConfig = blob.DefaultBPO3BlobConfig + DefaultBPO4BlobConfig = blob.DefaultBPO4BlobConfig +) + +func GetBlobFeeDenominator(blobFeeConfig *BlobFeeConfig, blockTime uint64) *big.Int { + return blob.GetBlobFeeDenominator(blobFeeConfig, blockTime) +} + +func BlobHashes(blobs []kzg4844.Blob, commitments []kzg4844.Commitment) []common.Hash { + return blob.BlobHashes(blobs, commitments) +} + +func MakeBlobProof(blobs []kzg4844.Blob, commitment []kzg4844.Commitment) ([]kzg4844.Proof, error) { + return blob.MakeBlobProof(blobs, commitment) +} + +func MakeCellProof(blobs []kzg4844.Blob) ([]kzg4844.Proof, error) { + return blob.MakeCellProof(blobs) +} + +func DetermineBlobVersion(head *ethtypes.Header, chainID uint64) byte { + return blob.DetermineBlobVersion(head, chainID) +} + +func BlobSidecarVersionToV1(sc *ethtypes.BlobTxSidecar) error { + return blob.BlobSidecarVersionToV1(sc) +} diff --git a/tx-submitter/types/blob_params.go b/tx-submitter/types/blob_params.go deleted file mode 100644 index 4ebe43a41..000000000 --- a/tx-submitter/types/blob_params.go +++ /dev/null @@ -1,103 +0,0 @@ -package types - -import ( - "math/big" -) - -var ( - DefaultBlobConfig = HoodiChainConfig - - ChainConfigMap = ChainBlobConfigs{ - 1: MainnetChainConfig, - 560048: HoodiChainConfig, - 900: DevnetChainConfig, - } -) - -func newUint64(val uint64) *uint64 { return &val } - -type ChainBlobConfigs map[uint64]*BlobFeeConfig - -var ( - // MainnetChainConfig is the chain parameters to run a node on the main network. - MainnetChainConfig = &BlobFeeConfig{ - ChainID: big.NewInt(1), - LondonBlock: big.NewInt(12_965_000), - CancunTime: newUint64(1710338135), - PragueTime: newUint64(1746612311), - OsakaTime: newUint64(1764798551), - BPO1Time: newUint64(1765290071), - BPO2Time: newUint64(1767747671), - Cancun: DefaultCancunBlobConfig, - Prague: DefaultPragueBlobConfig, - Osaka: DefaultOsakaBlobConfig, - BPO1: DefaultBPO1BlobConfig, - BPO2: DefaultBPO2BlobConfig, - Default: DefaultOsakaBlobConfig, - } - - // HoodiChainConfig contains the chain parameters to run a node on the Hoodi test network. - HoodiChainConfig = &BlobFeeConfig{ - ChainID: big.NewInt(560048), - LondonBlock: big.NewInt(0), - CancunTime: newUint64(0), - PragueTime: newUint64(1742999832), - OsakaTime: newUint64(1761677592), - BPO1Time: newUint64(1762365720), - BPO2Time: newUint64(1762955544), - Cancun: DefaultCancunBlobConfig, - Prague: DefaultPragueBlobConfig, - Osaka: DefaultOsakaBlobConfig, - BPO1: DefaultBPO1BlobConfig, - BPO2: DefaultBPO2BlobConfig, - Default: DefaultOsakaBlobConfig, - } - - // DevnetChainConfig contains the chain parameters to run a node on the devnet test network. - DevnetChainConfig = &BlobFeeConfig{ - ChainID: big.NewInt(900), - LondonBlock: big.NewInt(0), - CancunTime: newUint64(0), - PragueTime: newUint64(1742999832), - OsakaTime: newUint64(1761677592), - BPO1Time: newUint64(1762365720), - BPO2Time: newUint64(1762955544), - Cancun: DefaultCancunBlobConfig, - Prague: DefaultPragueBlobConfig, - Osaka: DefaultOsakaBlobConfig, - BPO1: DefaultBPO1BlobConfig, - BPO2: DefaultBPO2BlobConfig, - Default: DefaultOsakaBlobConfig, - } -) - -var ( - // DefaultCancunBlobConfig is the default blob configuration for the Cancun fork. - DefaultCancunBlobConfig = &BlobConfig{ - UpdateFraction: 3338477, - } - // DefaultPragueBlobConfig is the default blob configuration for the Prague fork. - DefaultPragueBlobConfig = &BlobConfig{ - UpdateFraction: 5007716, - } - // DefaultOsakaBlobConfig is the default blob configuration for the Osaka fork. - DefaultOsakaBlobConfig = &BlobConfig{ - UpdateFraction: 5007716, - } - // DefaultBPO1BlobConfig is the default blob configuration for the BPO1 fork. - DefaultBPO1BlobConfig = &BlobConfig{ - UpdateFraction: 8346193, - } - // DefaultBPO2BlobConfig is the default blob configuration for the BPO2 fork. - DefaultBPO2BlobConfig = &BlobConfig{ - UpdateFraction: 11684671, - } - // DefaultBPO3BlobConfig is the default blob configuration for the BPO3 fork. - DefaultBPO3BlobConfig = &BlobConfig{ - UpdateFraction: 20609697, - } - // DefaultBPO4BlobConfig is the default blob configuration for the BPO4 fork. - DefaultBPO4BlobConfig = &BlobConfig{ - UpdateFraction: 13739630, - } -) diff --git a/tx-submitter/types/converter.go b/tx-submitter/types/converter.go index d5b16398d..b1b9863fd 100644 --- a/tx-submitter/types/converter.go +++ b/tx-submitter/types/converter.go @@ -1,25 +1,15 @@ package types -import ( - "encoding/binary" - "fmt" -) +import "morph-l2/common/batch" func Uint64ToBigEndianBytes(value uint64) []byte { - valueBytes := make([]byte, 8) - binary.BigEndian.PutUint64(valueBytes, value) - return valueBytes + return batch.Uint64ToBigEndianBytes(value) } func Uint16ToBigEndianBytes(value uint16) []byte { - valueBytes := make([]byte, 2) - binary.BigEndian.PutUint16(valueBytes, value) - return valueBytes + return batch.Uint16ToBigEndianBytes(value) } func HeightFromBlockContextBytes(blockContextBytes []byte) (uint64, error) { - if len(blockContextBytes) != 60 { - return 0, fmt.Errorf("wrong block context bytes length, input: %x", blockContextBytes) - } - return binary.BigEndian.Uint64(blockContextBytes[:8]), nil + return batch.HeightFromBlockContextBytes(blockContextBytes) } diff --git a/tx-submitter/types/l2Caller.go b/tx-submitter/types/l2Caller.go index cef0ab903..e3a9311d2 100644 --- a/tx-submitter/types/l2Caller.go +++ b/tx-submitter/types/l2Caller.go @@ -1,28 +1,17 @@ package types import ( - "bytes" "fmt" - "math/big" - "morph-l2/bindings/bindings" - "morph-l2/bindings/predeploys" + "morph-l2/common/batch" "morph-l2/tx-submitter/iface" - - "github.com/morph-l2/go-ethereum/accounts/abi/bind" - "github.com/morph-l2/go-ethereum/common" - "github.com/morph-l2/go-ethereum/common/hexutil" - "github.com/morph-l2/go-ethereum/crypto" ) -type L2Caller struct { - l2Clients *iface.L2Clients - sequencerContract *bindings.SequencerCaller - l2MessagePasserContract *bindings.L2ToL1MessagePasserCaller - govContract *bindings.GovCaller -} +// L2Caller reads L2 gov / sequencer state for batch assembly (see batch.L2Gov). +type L2Caller = batch.L2Gov -func NewL2Caller(l2Clients []iface.L2Client) (*L2Caller, error) { +// NewL2Caller builds an L2Caller backed by the given L2 RPC clients. +func NewL2Caller(l2Clients []iface.L2Client) (*batch.L2Gov, error) { if len(l2Clients) == 0 { return nil, fmt.Errorf("no l2clients provided") } @@ -31,65 +20,5 @@ func NewL2Caller(l2Clients []iface.L2Client) (*L2Caller, error) { return nil, fmt.Errorf("nil l2client") } } - clients := &iface.L2Clients{Clients: l2Clients} - - // Initialize Sequencer contract - sequencerContract, err := bindings.NewSequencerCaller(predeploys.SequencerAddr, clients) - if err != nil { - return nil, err - } - - // Initialize L2ToL1MessagePasser contract - l2MessagePasserContract, err := bindings.NewL2ToL1MessagePasserCaller(predeploys.L2ToL1MessagePasserAddr, clients) - if err != nil { - return nil, err - } - - // Initialize Gov contract - govContract, err := bindings.NewGovCaller(predeploys.GovAddr, clients) - if err != nil { - return nil, err - } - - return &L2Caller{ - l2Clients: clients, - sequencerContract: sequencerContract, - l2MessagePasserContract: l2MessagePasserContract, - govContract: govContract, - }, nil -} - -// SequencerSetVerifyHash gets the sequencer set verify hash from the Sequencer contract -func (c *L2Caller) SequencerSetVerifyHash(opts *bind.CallOpts) ([32]byte, error) { - return c.sequencerContract.SequencerSetVerifyHash(opts) -} - -// GetTreeRoot gets the tree root from the L2ToL1MessagePasser contract -func (c *L2Caller) GetTreeRoot(opts *bind.CallOpts) ([32]byte, error) { - return c.l2MessagePasserContract.GetTreeRoot(opts) -} - -// BatchBlockInterval gets the batch block interval from the Gov contract -func (c *L2Caller) BatchBlockInterval(opts *bind.CallOpts) (*big.Int, error) { - return c.govContract.BatchBlockInterval(opts) -} - -// BatchTimeout gets the batch timeout from the Gov contract -func (c *L2Caller) BatchTimeout(opts *bind.CallOpts) (*big.Int, error) { - return c.govContract.BatchTimeout(opts) -} - -func (c *L2Caller) GetSequencerSetBytes(opts *bind.CallOpts) ([]byte, common.Hash, error) { - hash, err := c.sequencerContract.SequencerSetVerifyHash(opts) - if err != nil { - return nil, common.Hash{}, err - } - setBytes, err := c.sequencerContract.GetSequencerSetBytes(opts) - if err != nil { - return nil, common.Hash{}, err - } - if bytes.Equal(hash[:], crypto.Keccak256Hash(setBytes).Bytes()) { - return setBytes, hash, nil - } - return nil, common.Hash{}, fmt.Errorf("sequencer set hash verify failed %v: %v", hexutil.Encode(setBytes), common.BytesToHash(hash[:]).String()) + return batch.NewL2Gov(&iface.L2Clients{Clients: l2Clients}) } diff --git a/tx-submitter/utils/config.go b/tx-submitter/utils/config.go index a24d5604b..4e9269f95 100644 --- a/tx-submitter/utils/config.go +++ b/tx-submitter/utils/config.go @@ -112,6 +112,10 @@ type Config struct { BlockNotIncreasedThreshold int64 // enable seal batch SealBatch bool + // max blob count per batch + MaxBlobCount int + // unix timestamp at which V2 multi-blob batch format is activated (0 = disabled) + BatchV2UpgradeTime uint64 } // NewConfig parses the DriverConfig from the provided flags or environment variables. @@ -187,6 +191,10 @@ func NewConfig(ctx *cli.Context) (Config, error) { BlockNotIncreasedThreshold: ctx.GlobalInt64(flags.BlockNotIncreasedThreshold.Name), // SealBatch SealBatch: ctx.GlobalBool(flags.SealBatch.Name), + // MaxBlobCount + MaxBlobCount: ctx.GlobalInt(flags.MaxBlobCountFlag.Name), + // BatchV2UpgradeTime + BatchV2UpgradeTime: ctx.GlobalUint64(flags.BatchV2UpgradeTimeFlag.Name), } return cfg, nil diff --git a/tx-submitter/utils/utils.go b/tx-submitter/utils/utils.go index 06de87e6e..7001e5dae 100644 --- a/tx-submitter/utils/utils.go +++ b/tx-submitter/utils/utils.go @@ -15,11 +15,9 @@ import ( ntype "morph-l2/node/types" "github.com/morph-l2/go-ethereum/accounts/abi" - "github.com/morph-l2/go-ethereum/common" "github.com/morph-l2/go-ethereum/common/hexutil" "github.com/morph-l2/go-ethereum/core/types" "github.com/morph-l2/go-ethereum/log" - "github.com/morph-l2/go-ethereum/rpc" ) // Loop Run the f func periodically. @@ -71,12 +69,42 @@ func ParseParentBatchIndex(calldata []byte) uint64 { /// * batchIndex 8 uint64 1 The index of the batch /// * l1MessagePopped 8 uint64 9 Number of L1 messages popped in the batch - abi, _ := bindings.RollupMetaData.GetAbi() - parms, _ := abi.Methods["commitBatch"].Inputs.UnpackValues(calldata[4:]) + if len(calldata) < 4 { + return 0 + } + rollupAbi, err := bindings.RollupMetaData.GetAbi() + if err != nil { + return 0 + } + sel := calldata[:4] + var method abi.Method + var ok bool + if bytes.Equal(sel, rollupAbi.Methods["commitState"].ID) { + method, ok = rollupAbi.Methods["commitState"] + } else if bytes.Equal(sel, rollupAbi.Methods["commitBatch"].ID) { + method, ok = rollupAbi.Methods["commitBatch"] + } else { + // Unknown selector: keep legacy behavior (unpack as commitBatch). Matches older fixtures and + // any tx whose first tuple matches BatchDataInput layout even if the selector differs. + method, ok = rollupAbi.Methods["commitBatch"] + } + if !ok { + return 0 + } + parms, err := method.Inputs.UnpackValues(calldata[4:]) + if err != nil || len(parms) == 0 { + return 0 + } v := reflect.ValueOf(parms[0]) pbh := v.FieldByName("ParentBatchHeader") - batchIndex := binary.BigEndian.Uint64(pbh.Bytes()[1:9]) - return batchIndex + if !pbh.IsValid() { + return 0 + } + b := pbh.Bytes() + if len(b) < 9 { + return 0 + } + return binary.BigEndian.Uint64(b[1:9]) } // SetFBatchIndex sets the batch index in the calldata while preserving all other data @@ -119,51 +147,6 @@ func SetFBatchIndex(calldata []byte, batchIndex uint64) error { return nil } -// ParseL1Mempool parses the L1 mempool and returns the transactions. -func ParseL1Mempool(rpc *rpc.Client, addr common.Address) ([]*types.Transaction, error) { - - var result map[string]map[string]*types.Transaction - err := rpc.Call(&result, "txpool_contentFrom", addr) - if err != nil { - return nil, fmt.Errorf("failed to get txpool content: %v", err) - } - - var txs []*types.Transaction - - // get pending txs - if pendingTxs, ok := result["pending"]; ok { - for _, tx := range pendingTxs { - txs = append(txs, tx) - } - } - - // get queued txs - if pendingTxs, ok := result["queued"]; ok { - for _, tx := range pendingTxs { - txs = append(txs, tx) - } - } - - return txs, nil - -} - -func ParseMempoolLatestBatchIndex(id []byte, txs []*types.Transaction) uint64 { - - var res uint64 - for _, tx := range txs { - if bytes.Equal(tx.Data()[:4], id) { - pindex := ParseParentBatchIndex(tx.Data()) - if pindex > res { - res = pindex - } - } - } - - return res + 1 - -} - func ParseBusinessInfo(tx *types.Transaction, a *abi.ABI) []interface{} { // var method string // var batchIndex uint64 @@ -178,6 +161,13 @@ func ParseBusinessInfo(tx *types.Transaction, a *abi.ABI) []interface{} { "method", method, "batchIndex", batchIndex, ) + } else if bytes.Equal(id, a.Methods["commitState"].ID) { + method := "commitState" + batchIndex := ParseParentBatchIndex(tx.Data()) + 1 + res = append(res, + "method", method, + "batchIndex", batchIndex, + ) } else if bytes.Equal(id, a.Methods["finalizeBatch"].ID) { method := "finalizeBatch" parms, err := a.Methods["finalizeBatch"].Inputs.Unpack(tx.Data()[4:]) @@ -205,6 +195,8 @@ func ParseMethod(tx *types.Transaction, a *abi.ABI) string { id := tx.Data()[:4] if bytes.Equal(id, a.Methods["commitBatch"].ID) { return "commitBatch" + } else if bytes.Equal(id, a.Methods["commitState"].ID) { + return "commitState" } else if bytes.Equal(id, a.Methods["finalizeBatch"].ID) { return "finalizeBatch" } else {