Commit 44201560 authored by Inphi's avatar Inphi Committed by GitHub

op-program: Generic precompile oracle (#9699)

* op-program: Generic precompile oracle

The generic precompile oracle replaces the point evaluation precompile
oracle. The new oracle can be used to retrieve the return data and
status of any precompile, including bn256Pairing and ecrecover.

* op-challenger: Use generic precompile oracle

Replace the KZG point evaluation oracle with a generic precompile oracle

* op-program: Simplify required gas logic.
Use FromHex instead of Hex2Bytes

* op-program: Set beacon URL when capturing and verifying sepolia chain data

* op-program: Actually use the beacon URL

* op-program: Use default l1-rpckind if not set rather than overriding to debug_geth

* Use freshly generated sepolia test data

* Use sepolia compatibility data

* Fix spelling

* update PreimageOracle.sol snapshot

---------
Co-authored-by: default avatarAdrian Sutton <adrian@oplabs.co>
parent e983f527
...@@ -257,8 +257,8 @@ func Run(ctx *cli.Context) error { ...@@ -257,8 +257,8 @@ func Run(ctx *cli.Context) error {
stopAtPreimageTypeByte = preimage.Sha256KeyType stopAtPreimageTypeByte = preimage.Sha256KeyType
case "blob": case "blob":
stopAtPreimageTypeByte = preimage.BlobKeyType stopAtPreimageTypeByte = preimage.BlobKeyType
case "kzg-point-evaluation": case "precompile":
stopAtPreimageTypeByte = preimage.KZGPointEvaluationKeyType stopAtPreimageTypeByte = preimage.PrecompileKeyType
case "any": case "any":
stopAtAnyPreimage = true stopAtAnyPreimage = true
case "": case "":
......
...@@ -52,9 +52,14 @@ type Addresses struct { ...@@ -52,9 +52,14 @@ type Addresses struct {
} }
func NewEVMEnv(contracts *Contracts, addrs *Addresses) (*vm.EVM, *state.StateDB) { func NewEVMEnv(contracts *Contracts, addrs *Addresses) (*vm.EVM, *state.StateDB) {
chainCfg := params.MainnetChainConfig // Temporary hack until Cancun is activated on mainnet
offsetBlocks := uint64(1000) // blocks after shanghai fork cpy := *params.MainnetChainConfig
bc := &testChain{startTime: *chainCfg.ShanghaiTime + offsetBlocks*12} chainCfg := &cpy // don't modify the global chain config
// Activate Cancun for EIP-4844 KZG point evaluation precompile
cancunActivation := *chainCfg.ShanghaiTime + 10
chainCfg.CancunTime = &cancunActivation
offsetBlocks := uint64(1000) // blocks after cancun fork
bc := &testChain{startTime: *chainCfg.CancunTime + offsetBlocks*12}
header := bc.GetHeader(common.Hash{}, 17034870+offsetBlocks) header := bc.GetHeader(common.Hash{}, 17034870+offsetBlocks)
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
statedb := state.NewDatabase(db) statedb := state.NewDatabase(db)
......
...@@ -136,15 +136,18 @@ func encodePreimageOracleInput(t *testing.T, wit *StepWitness, localContext Loca ...@@ -136,15 +136,18 @@ func encodePreimageOracleInput(t *testing.T, wit *StepWitness, localContext Loca
wit.PreimageValue[8:]) wit.PreimageValue[8:])
require.NoError(t, err) require.NoError(t, err)
return input, nil return input, nil
case preimage.KZGPointEvaluationKeyType: case preimage.PrecompileKeyType:
if localOracle == nil { if localOracle == nil {
return nil, fmt.Errorf("local oracle is required for point evaluation preimages") return nil, fmt.Errorf("local oracle is required for precompile preimages")
} }
preimage := localOracle.GetPreimage(preimage.Keccak256Key(wit.PreimageKey).PreimageKey()) preimage := localOracle.GetPreimage(preimage.Keccak256Key(wit.PreimageKey).PreimageKey())
precompile := common.BytesToAddress(preimage[:20])
callInput := preimage[20:]
input, err := preimageAbi.Pack( input, err := preimageAbi.Pack(
"loadKZGPointEvaluationPreimagePart", "loadPrecompilePreimagePart",
new(big.Int).SetUint64(uint64(wit.PreimageOffset)), new(big.Int).SetUint64(uint64(wit.PreimageOffset)),
preimage, precompile,
callInput,
) )
require.NoError(t, err) require.NoError(t, err)
return input, nil return input, nil
...@@ -199,8 +202,8 @@ func TestEVM(t *testing.T) { ...@@ -199,8 +202,8 @@ func TestEVM(t *testing.T) {
// verify the post-state matches. // verify the post-state matches.
// TODO: maybe more readable to decode the evmPost state, and do attribute-wise comparison. // TODO: maybe more readable to decode the evmPost state, and do attribute-wise comparison.
goPost := goState.state.EncodeWitness() goPost := goState.state.EncodeWitness()
require.Equal(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), require.Equalf(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(),
"mipsevm produced different state than EVM") "mipsevm produced different state than EVM at step %d", state.Step)
} }
if exitGroup { if exitGroup {
require.NotEqual(t, uint32(endAddr), goState.state.PC, "must not reach end") require.NotEqual(t, uint32(endAddr), goState.state.PC, "must not reach end")
......
...@@ -5,35 +5,36 @@ ...@@ -5,35 +5,36 @@
.ent test .ent test
# load hash at 0x30001000 # load hash at 0x30001000
# 0x47173285 a8d7341e 5e972fc6 77286384 f802f8ef 42a5ec5f 03bbfa25 4cb01fad = keccak("hello world") # point evaluation precompile input - 01e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a
# 0x06173285 a8d7341e 5e972fc6 77286384 f802f8ef 42a5ec5f 03bbfa25 4cb01fad = keccak("hello world").key (kzg) # 0x0a44472c cb798bc5 954fc466 e6ee2c31 e1ca8a87 d000966c 629d679a 4a29921f = keccak(address(0xa) ++ precompile_input)
# 0x0644472c cb798bc5 954fc466 e6ee2c31 e1ca8a87 d000966c 629d679a 4a29921f = keccak(address(0xa) ++ precompile_input).key (precompile)
test: test:
lui $s0, 0x3000 lui $s0, 0x3000
ori $s0, 0x1000 ori $s0, 0x1000
lui $t0, 0x0617 lui $t0, 0x0644
ori $t0, 0x3285 ori $t0, 0x472c
sw $t0, 0($s0) sw $t0, 0($s0)
lui $t0, 0xa8d7 lui $t0, 0xcb79
ori $t0, 0x341e ori $t0, 0x8bc5
sw $t0, 4($s0) sw $t0, 4($s0)
lui $t0, 0x5e97 lui $t0, 0x954f
ori $t0, 0x2fc6 ori $t0, 0xc466
sw $t0, 8($s0) sw $t0, 8($s0)
lui $t0, 0x7728 lui $t0, 0xe6ee
ori $t0, 0x6384 ori $t0, 0x2c31
sw $t0, 0xc($s0) sw $t0, 0xc($s0)
lui $t0, 0xf802 lui $t0, 0xe1ca
ori $t0, 0xf8ef ori $t0, 0x8a87
sw $t0, 0x10($s0) sw $t0, 0x10($s0)
lui $t0, 0x42a5 lui $t0, 0xd000
ori $t0, 0xec5f ori $t0, 0x966c
sw $t0, 0x14($s0) sw $t0, 0x14($s0)
lui $t0, 0x03bb lui $t0, 0x629d
ori $t0, 0xfa25 ori $t0, 0x679a
sw $t0, 0x18($s0) sw $t0, 0x18($s0)
lui $t0, 0x4cb0 lui $t0, 0x4a29
ori $t0, 0x1fad ori $t0, 0x921f
sw $t0, 0x1c($s0) sw $t0, 0x1c($s0)
# preimage request - write(fdPreimageWrite, preimageData, 32) # preimage request - write(fdPreimageWrite, preimageData, 32)
...@@ -59,7 +60,7 @@ $writeloop: ...@@ -59,7 +60,7 @@ $writeloop:
li $a1, 0x31000004 li $a1, 0x31000004
li $v0, 4003 li $v0, 4003
syscall syscall
# read the 1 byte preimage data # read the 1 byte precompile status and 3 bytes of return data
li $a1, 0x31000008 li $a1, 0x31000008
li $v0, 4003 li $v0, 4003
syscall syscall
...@@ -71,13 +72,21 @@ $writeloop: ...@@ -71,13 +72,21 @@ $writeloop:
sltiu $t6, $t0, 1 sltiu $t6, $t0, 1
li $s1, 0x31000004 li $s1, 0x31000004
lw $t0, 0($s1) lw $t0, 0($s1)
# len should be 1 # should be 1 + len(blobPrecompileReturnValue) = 65
li $t4, 1 li $t4, 65
subu $t5, $t0, $t4 subu $t5, $t0, $t4
sltiu $v0, $t5, 1 sltiu $v0, $t5, 1
and $v0, $v0, $t6 and $v0, $v0, $t6
# most likely broken. need to check pc for exact case # data at 0x31000008
# first byte is 01 status. Next 3 bytes are 0
lw $t0, 4($s1)
lui $t4, 0x0100
ori $t4, 0x0000
subu $t5, $t0, $t4
sltiu $v1, $t5, 1
and $v0, $v0, $v1
# save results # save results
lui $s0, 0xbfff # Load the base address 0xbffffff0 lui $s0, 0xbfff # Load the base address 0xbffffff0
ori $s0, 0xfff0 ori $s0, 0xfff0
......
...@@ -267,18 +267,19 @@ func staticOracle(t *testing.T, preimageData []byte) *testOracle { ...@@ -267,18 +267,19 @@ func staticOracle(t *testing.T, preimageData []byte) *testOracle {
} }
} }
func staticPrecompileOracle(t *testing.T, preimageData []byte, result []byte) *testOracle { func staticPrecompileOracle(t *testing.T, precompile common.Address, input []byte, result []byte) *testOracle {
return &testOracle{ return &testOracle{
hint: func(v []byte) {}, hint: func(v []byte) {},
getPreimage: func(k [32]byte) []byte { getPreimage: func(k [32]byte) []byte {
keyData := append(precompile.Bytes(), input...)
switch k[0] { switch k[0] {
case byte(preimage.Keccak256KeyType): case byte(preimage.Keccak256KeyType):
if k != preimage.Keccak256Key(crypto.Keccak256Hash(preimageData)).PreimageKey() { if k != preimage.Keccak256Key(crypto.Keccak256Hash(keyData)).PreimageKey() {
t.Fatalf("invalid preimage request for %x", k) t.Fatalf("invalid preimage request for %x", k)
} }
return preimageData return keyData
case byte(preimage.KZGPointEvaluationKeyType): case byte(preimage.PrecompileKeyType):
if k != preimage.KZGPointEvaluationKey(crypto.Keccak256Hash(preimageData)).PreimageKey() { if k != preimage.PrecompileKey(crypto.Keccak256Hash(keyData)).PreimageKey() {
t.Fatalf("invalid preimage request for %x", k) t.Fatalf("invalid preimage request for %x", k)
} }
return result return result
...@@ -290,7 +291,10 @@ func staticPrecompileOracle(t *testing.T, preimageData []byte, result []byte) *t ...@@ -290,7 +291,10 @@ func staticPrecompileOracle(t *testing.T, preimageData []byte, result []byte) *t
func selectOracleFixture(t *testing.T, programName string) PreimageOracle { func selectOracleFixture(t *testing.T, programName string) PreimageOracle {
if strings.HasPrefix(programName, "oracle_kzg") { if strings.HasPrefix(programName, "oracle_kzg") {
return staticPrecompileOracle(t, []byte("hello world"), []byte{0x1}) precompile := common.BytesToAddress([]byte{0xa})
input := common.FromHex("01e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a")
blobPrecompileReturnValue := common.FromHex("000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001")
return staticPrecompileOracle(t, precompile, input, append([]byte{0x1}, blobPrecompileReturnValue...))
} else if strings.HasPrefix(programName, "oracle") { } else if strings.HasPrefix(programName, "oracle") {
return staticOracle(t, []byte("hello world")) return staticOracle(t, []byte("hello world"))
} else { } else {
......
...@@ -42,8 +42,8 @@ type PreimageOracleLeaf struct { ...@@ -42,8 +42,8 @@ type PreimageOracleLeaf struct {
// PreimageOracleMetaData contains all meta data concerning the PreimageOracle contract. // PreimageOracleMetaData contains all meta data concerning the PreimageOracle contract.
var PreimageOracleMetaData = &bind.MetaData{ var PreimageOracleMetaData = &bind.MetaData{
ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_minProposalSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_challengePeriod\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_cancunActivation\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"KECCAK_TREE_DEPTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAX_LEAF_COUNT\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MIN_BOND_SIZE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addLeavesLPP\",\"inputs\":[{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_inputStartBlock\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_stateCommitments\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"_finalize\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"challengeFirstLPP\",\"inputs\":[{\"name\":\"_claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_postState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_postStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"challengeLPP\",\"inputs\":[{\"name\":\"_claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_stateMatrix\",\"type\":\"tuple\",\"internalType\":\"structLibKeccak.StateMatrix\",\"components\":[{\"name\":\"state\",\"type\":\"uint64[25]\",\"internalType\":\"uint64[25]\"}]},{\"name\":\"_preState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_preStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"_postState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_postStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"challengePeriod\",\"inputs\":[],\"outputs\":[{\"name\":\"challengePeriod_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTreeRootLPP\",\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"treeRoot_\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initLPP\",\"inputs\":[{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_partOffset\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"_claimedSize\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"loadBlobPreimagePart\",\"inputs\":[{\"name\":\"_z\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_y\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_commitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"loadKZGPointEvaluationPreimagePart\",\"inputs\":[{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_input\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"loadKeccak256PreimagePart\",\"inputs\":[{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_preimage\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"loadLocalData\",\"inputs\":[{\"name\":\"_ident\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_localContext\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"_word\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"_size\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"key_\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"loadSha256PreimagePart\",\"inputs\":[{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_preimage\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"minProposalSize\",\"inputs\":[],\"outputs\":[{\"name\":\"minProposalSize_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"preimageLengths\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"preimagePartOk\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"preimageParts\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalBlocks\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalBlocksLen\",\"inputs\":[{\"name\":\"_claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"len_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalBonds\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalBranches\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalCount\",\"inputs\":[],\"outputs\":[{\"name\":\"count_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalMetadata\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"LPPMetaData\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalParts\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposals\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"readPreimage\",\"inputs\":[{\"name\":\"_key\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"_offset\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"dat_\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"datLen_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"squeezeLPP\",\"inputs\":[{\"name\":\"_claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_stateMatrix\",\"type\":\"tuple\",\"internalType\":\"structLibKeccak.StateMatrix\",\"components\":[{\"name\":\"state\",\"type\":\"uint64[25]\",\"internalType\":\"uint64[25]\"}]},{\"name\":\"_preState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_preStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"_postState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_postStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"zeroHashes\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"error\",\"name\":\"ActiveProposal\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AlreadyFinalized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadProposal\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BondTransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CancunNotActive\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InsufficientBond\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidInputSize\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidPreimage\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidProof\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotEOA\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PartOffsetOOB\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PostStateMatches\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"StatesNotContiguous\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TreeSizeOverflow\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WrongStartingBlock\",\"inputs\":[]}]", ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_minProposalSize\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_challengePeriod\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_cancunActivation\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"KECCAK_TREE_DEPTH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MAX_LEAF_COUNT\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MIN_BOND_SIZE\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addLeavesLPP\",\"inputs\":[{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_inputStartBlock\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_stateCommitments\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"_finalize\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"challengeFirstLPP\",\"inputs\":[{\"name\":\"_claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_postState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_postStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"challengeLPP\",\"inputs\":[{\"name\":\"_claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_stateMatrix\",\"type\":\"tuple\",\"internalType\":\"structLibKeccak.StateMatrix\",\"components\":[{\"name\":\"state\",\"type\":\"uint64[25]\",\"internalType\":\"uint64[25]\"}]},{\"name\":\"_preState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_preStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"_postState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_postStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"challengePeriod\",\"inputs\":[],\"outputs\":[{\"name\":\"challengePeriod_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTreeRootLPP\",\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"treeRoot_\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initLPP\",\"inputs\":[{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_partOffset\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"_claimedSize\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"loadBlobPreimagePart\",\"inputs\":[{\"name\":\"_z\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_y\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_commitment\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_proof\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"loadKeccak256PreimagePart\",\"inputs\":[{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_preimage\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"loadLocalData\",\"inputs\":[{\"name\":\"_ident\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_localContext\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"_word\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"_size\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"key_\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"loadPrecompilePreimagePart\",\"inputs\":[{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_precompile\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_input\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"loadSha256PreimagePart\",\"inputs\":[{\"name\":\"_partOffset\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_preimage\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"minProposalSize\",\"inputs\":[],\"outputs\":[{\"name\":\"minProposalSize_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"preimageLengths\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"preimagePartOk\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"preimageParts\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalBlocks\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalBlocksLen\",\"inputs\":[{\"name\":\"_claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"len_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalBonds\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalBranches\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalCount\",\"inputs\":[],\"outputs\":[{\"name\":\"count_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalMetadata\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"LPPMetaData\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposalParts\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"proposals\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"readPreimage\",\"inputs\":[{\"name\":\"_key\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"_offset\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"dat_\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"datLen_\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"squeezeLPP\",\"inputs\":[{\"name\":\"_claimant\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_uuid\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_stateMatrix\",\"type\":\"tuple\",\"internalType\":\"structLibKeccak.StateMatrix\",\"components\":[{\"name\":\"state\",\"type\":\"uint64[25]\",\"internalType\":\"uint64[25]\"}]},{\"name\":\"_preState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_preStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"_postState\",\"type\":\"tuple\",\"internalType\":\"structPreimageOracle.Leaf\",\"components\":[{\"name\":\"input\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"stateCommitment\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_postStateProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"zeroHashes\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"error\",\"name\":\"ActiveProposal\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"AlreadyFinalized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BadProposal\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"BondTransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"CancunNotActive\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InsufficientBond\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidInputSize\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidPreimage\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidProof\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotEOA\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PartOffsetOOB\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PostStateMatches\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"StatesNotContiguous\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TreeSizeOverflow\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WrongStartingBlock\",\"inputs\":[]}]",
Bin: "0x60e06040523480156200001157600080fd5b506040516200395e3803806200395e8339810160408190526200003491620000f9565b60c083905260a0829052608081905260005b62000054600160106200013e565b811015620000ef576003816010811062000072576200007262000158565b0154600382601081106200008a576200008a62000158565b0154604080516020810193909352820152606001604051602081830303815290604052805190602001206003826001620000c591906200016e565b60108110620000d857620000d862000158565b015580620000e68162000189565b91505062000046565b50505050620001a5565b6000806000606084860312156200010f57600080fd5b8351925060208401519150604084015190509250925092565b634e487b7160e01b600052601160045260246000fd5b60008282101562000153576200015362000128565b500390565b634e487b7160e01b600052603260045260246000fd5b6000821982111562000184576200018462000128565b500190565b6000600182016200019e576200019e62000128565b5060010190565b60805160a05160c051613774620001ea6000396000818161054d0152611d4d01526000818161062d01526115b50152600081816111b301526113c401526137746000f3fe6080604052600436106101c25760003560e01c80639d53a648116100f7578063dd24f9bf11610095578063ec5efcbc11610064578063ec5efcbc146105fe578063f3f480d91461061e578063faf37bc714610651578063fef2b4ed1461066457600080fd5b8063dd24f9bf1461053e578063ddcd58de14610571578063e03110e1146105a9578063e1592611146105de57600080fd5b8063b2e67ba8116100d1578063b2e67ba8146104b1578063b4801e61146104e9578063d18534b514610509578063da35c6641461052957600080fd5b80639d53a648146104225780639d7e8769146104715780639dede8cc1461049157600080fd5b80636551927b116101645780637ac547671161013e5780637ac547671461035e5780638542cf501461037e578063882856ef146103c95780638dc4be111461040257600080fd5b80636551927b146102ea5780637051472e146103225780637917de1d1461033e57600080fd5b80633909af5c116101a05780633909af5c1461025b5780634d52b4c91461027d57806352f0f3ad1461029257806361238bde146102b257600080fd5b8063013cf08b146101c75780630359a563146102185780632055b36b14610246575b600080fd5b3480156101d357600080fd5b506101e76101e2366004612d2b565b610691565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561022457600080fd5b50610238610233366004612d6d565b6106d6565b60405190815260200161020f565b34801561025257600080fd5b50610238601081565b34801561026757600080fd5b5061027b610276366004612f68565b61080e565b005b34801561028957600080fd5b50610238610a65565b34801561029e57600080fd5b506102386102ad366004613054565b610a80565b3480156102be57600080fd5b506102386102cd36600461308f565b600160209081526000928352604080842090915290825290205481565b3480156102f657600080fd5b50610238610305366004612d6d565b601560209081526000928352604080842090915290825290205481565b34801561032e57600080fd5b506102386703782dace9d9000081565b34801561034a57600080fd5b5061027b6103593660046130f3565b610b55565b34801561036a57600080fd5b50610238610379366004612d2b565b611045565b34801561038a57600080fd5b506103b961039936600461308f565b600260209081526000928352604080842090915290825290205460ff1681565b604051901515815260200161020f565b3480156103d557600080fd5b506103e96103e436600461318f565b61105c565b60405167ffffffffffffffff909116815260200161020f565b34801561040e57600080fd5b5061027b61041d3660046131c2565b6110b6565b34801561042e57600080fd5b5061023861043d366004612d6d565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b34801561047d57600080fd5b5061027b61048c36600461320e565b6111b1565b34801561049d57600080fd5b5061027b6104ac3660046131c2565b6113c2565b3480156104bd57600080fd5b506102386104cc366004612d6d565b601760209081526000928352604080842090915290825290205481565b3480156104f557600080fd5b5061023861050436600461318f565b61150e565b34801561051557600080fd5b5061027b610524366004612f68565b611540565b34801561053557600080fd5b50601354610238565b34801561054a57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610238565b34801561057d57600080fd5b5061023861058c366004612d6d565b601660209081526000928352604080842090915290825290205481565b3480156105b557600080fd5b506105c96105c436600461308f565b611902565b6040805192835260208301919091520161020f565b3480156105ea57600080fd5b5061027b6105f93660046131c2565b6119f3565b34801561060a57600080fd5b5061027b61061936600461329a565b611afb565b34801561062a57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610238565b61027b61065f366004613333565b611c81565b34801561067057600080fd5b5061023861067f366004612d2b565b60006020819052908152604090205481565b601381815481106106a157600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260156020908152604080832084845290915281205481906107199060601c63ffffffff1690565b63ffffffff16905060005b601081101561080657816001166001036107ac5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107795761077961336f565b015460408051602081019290925281018490526060016040516020818303038152906040528051906020012092506107ed565b82600382601081106107c0576107c061336f565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c90806107fe816133cd565b915050610724565b505092915050565b600061081a8a8a6106d6565b905061083d86868360208b01356108386108338d613405565b611eec565b611f2c565b801561085b575061085b83838360208801356108386108338a613405565b610891576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8660400135886040516020016108a791906134d4565b60405160208183030381529060405280519060200120146108f4576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161090a9190613512565b14610941576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109898861094f868061352a565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f8d92505050565b610992886120e8565b8360400135886040516020016109a891906134d4565b60405160208183030381529060405280519060200120036109f5576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610a598a8a33612890565b50505050505050505050565b6001610a73601060026136b1565b610a7d91906136bd565b81565b6000610a8c8686612949565b9050610a99836008613512565b821180610aa65750602083115b15610add576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610b6e57610b6786866129f6565b9050610ba8565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610bd557505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610c568260601c63ffffffff1690565b63ffffffff169050333214610c97576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca78260801c63ffffffff1690565b63ffffffff16600003610ce6576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cf08260c01c90565b67ffffffffffffffff1615610d31576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610d6a576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d7789898d8886612a6f565b83516020850160888204881415608883061715610d9c576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610e4c578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610e41576001821615610e215782818b0152610e41565b8981015160009081526020938452604090209260019290921c9101610e04565b505050608801610da9565b50505050600160106002610e6091906136b1565b610e6a91906136bd565b811115610ea3576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f18610eb68360401c63ffffffff1690565b610ec69063ffffffff168a613512565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b91508415610fa55777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b179150610f528260801c63ffffffff1690565b63ffffffff16610f688360401c63ffffffff1690565b63ffffffff1614610fa5576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e84529091529020610fcb90846010612ca1565b50503360008181526018602090815260408083208e8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055928252601581528282209c82529b909b52909920989098555050505050505050565b6003816010811061105557600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061108457600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b6044356000806008830186106110d45763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061110157600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b7f000000000000000000000000000000000000000000000000000000000000000042101561120b576040517f299f254900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080603087600037602060006030600060025afa806112335763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa9250826112b5576309bde3396000526004601cfd5b602886106112cb5763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b7f000000000000000000000000000000000000000000000000000000000000000042101561141c576040517f299f254900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060006080848682378481207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06000000000000000000000000000000000000000000000000000000000000001792506000808683600a5afa7801000000000000000000000000000000000000000000000000825260f81b600882015286015160008381526002602090815260408083208a8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558684528083528184209a845299825280832093909355938152928390529091209490945550505050565b6014602052826000526040600020602052816000526040600020816010811061153657600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156115b3576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006115de8260c01c90565b6115f29067ffffffffffffffff16426136bd565b11611629576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006116358b8b6106d6565b905061164e87878360208c01356108386108338e613405565b801561166c575061166c84848360208901356108386108338b613405565b6116a2576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016116b891906134d4565b6040516020818303038152906040528051906020012014611705576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161171b9190613512565b14158061174d575060016117358360601c63ffffffff1690565b61173f91906136d4565b63ffffffff16856020013514155b15611784576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117928961094f878061352a565b61179b896120e8565b60006117a68a612bc2565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f020000000000000000000000000000000000000000000000000000000000000017905060006117fd8460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d815260200190815260200160002054600160008481526020019081526020016000206000838152602001908152602001600020819055506118cf8460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556118f38d8d81612890565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff1661198b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546119a7816008613512565b6119b2856020613512565b106119d057836119c3826008613512565b6119cd91906136bd565b91505b506000938452600160209081526040808620948652939052919092205492909150565b604435600080600883018610611a115763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b6000611b0786866106d6565b9050611b2083838360208801356108386108338a613405565b611b56576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611b92576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b9a612cdf565b611ba88161094f878061352a565b611bb1816120e8565b846040013581604051602001611bc791906134d4565b6040516020818303038152906040528051906020012003611c14576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611c78878733612890565b50505050505050565b6703782dace9d90000341015611cc3576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611cfc576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d078160086136f9565b63ffffffff168263ffffffff1610611d4b576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008163ffffffff161015611dab576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000818152601560209081526040808320878452825280832080547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1660a09790971b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff169690961760809590951b949094179094558251808401845282815280850186815260138054600181018255908452915160029092027f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0908101805473ffffffffffffffffffffffffffffffffffffffff9094167fffffffffffffffffffffffff000000000000000000000000000000000000000090941693909317909255517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015590815260168352818120938152929091529020349055565b6000816000015182602001518360400151604051602001611f0f93929190613721565b604051602081830303815290604052805190602001209050919050565b60008160005b6010811015611f80578060051b880135600186831c1660018114611f655760008481526020839052604090209350611f76565b600082815260208590526040902093505b5050600101611f32565b5090931495945050505050565b6088815114611f9b57600080fd5b602081016020830161201c565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b171717905061201681612001868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b61202860008383611fa8565b61203460018383611fa8565b61204060028383611fa8565b61204c60038383611fa8565b61205860048383611fa8565b61206460058383611fa8565b61207060068383611fa8565b61207c60078383611fa8565b61208860088383611fa8565b61209460098383611fa8565b6120a0600a8383611fa8565b6120ac600b8383611fa8565b6120b8600c8383611fa8565b6120c4600d8383611fa8565b6120d0600e8383611fa8565b6120dc600f8383611fa8565b61201660108383611fa8565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e00160405160208183030381529060405290506020820160208201612770565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c61229b8660011b67ffffffffffffffff1690565b18188584603f1c6122b68660011b67ffffffffffffffff1690565b18188584603f1c6122d18660011b67ffffffffffffffff1690565b181895508483603f1c6122ee8560011b67ffffffffffffffff1690565b181894508387603f1c61230b8960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611c78565b61270a600082612683565b612715600582612683565b612720600a82612683565b61272b600f82612683565b612736601482612683565b50565b612742816121de565b61274b816126ff565b600383901b820151815160c09190911c9061201690821867ffffffffffffffff168352565b61277c60008284612739565b61278860018284612739565b61279460028284612739565b6127a060038284612739565b6127ac60048284612739565b6127b860058284612739565b6127c460068284612739565b6127d060078284612739565b6127dc60088284612739565b6127e860098284612739565b6127f4600a8284612739565b612800600b8284612739565b61280c600c8284612739565b612818600d8284612739565b612824600e8284612739565b612830600f8284612739565b61283c60108284612739565b61284860118284612739565b61285460128284612739565b61286060138284612739565b61286c60148284612739565b61287860158284612739565b61288460168284612739565b61201660178284612739565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d8060008114612909576040519150601f19603f3d011682016040523d82523d6000602084013e61290e565b606091505b505090508061267c576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316176129ef818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612a3f5760888290038501848101848103803687375060806001820353506001845160001a1784538652612a56565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612a818260a01c63ffffffff1690565b67ffffffffffffffff1690506000612a9f8360801c63ffffffff1690565b63ffffffff1690506000612ab98460401c63ffffffff1690565b63ffffffff169050600883108015612acf575080155b15612b035760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612bb8565b60088310158015612b21575080612b1b6008856136bd565b93508310155b8015612b355750612b328782613512565b83105b15612bb8576000612b4682856136bd565b905087612b54826020613512565b10158015612b60575085155b15612b97576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612c45565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612bf38360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612c208360101b67ffffffffffffffff1690565b1617905060008160201c612c3e8360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612c5d90612bc9565b612bc9565b6040820151612c6b90612bc9565b60401b17612c83612c5860018460059190911b015190565b825160809190911b90612c9590612bc9565b60c01b17179392505050565b8260108101928215612ccf579160200282015b82811115612ccf578251825591602001919060010190612cb4565b50612cdb929150612cf7565b5090565b6040518060200160405280612cf2612d0c565b905290565b5b80821115612cdb5760008155600101612cf8565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612d3d57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612d6857600080fd5b919050565b60008060408385031215612d8057600080fd5b612d8983612d44565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612dea57612dea612d97565b60405290565b6040516060810167ffffffffffffffff81118282101715612dea57612dea612d97565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612e5a57612e5a612d97565b604052919050565b6000610320808385031215612e7657600080fd5b604051602080820167ffffffffffffffff8382108183111715612e9b57612e9b612d97565b8160405283955087601f880112612eb157600080fd5b612eb9612dc6565b9487019491508188861115612ecd57600080fd5b875b86811015612ef55780358381168114612ee85760008081fd5b8452928401928401612ecf565b50909352509295945050505050565b600060608284031215612f1657600080fd5b50919050565b60008083601f840112612f2e57600080fd5b50813567ffffffffffffffff811115612f4657600080fd5b6020830191508360208260051b8501011115612f6157600080fd5b9250929050565b60008060008060008060008060006103e08a8c031215612f8757600080fd5b612f908a612d44565b985060208a01359750612fa68b60408c01612e62565b96506103608a013567ffffffffffffffff80821115612fc457600080fd5b612fd08d838e01612f04565b97506103808c0135915080821115612fe757600080fd5b612ff38d838e01612f1c565b90975095506103a08c013591508082111561300d57600080fd5b6130198d838e01612f04565b94506103c08c013591508082111561303057600080fd5b5061303d8c828d01612f1c565b915080935050809150509295985092959850929598565b600080600080600060a0868803121561306c57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b600080604083850312156130a257600080fd5b50508035926020909101359150565b60008083601f8401126130c357600080fd5b50813567ffffffffffffffff8111156130db57600080fd5b602083019150836020828501011115612f6157600080fd5b600080600080600080600060a0888a03121561310e57600080fd5b8735965060208801359550604088013567ffffffffffffffff8082111561313457600080fd5b6131408b838c016130b1565b909750955060608a013591508082111561315957600080fd5b506131668a828b01612f1c565b9094509250506080880135801515811461317f57600080fd5b8091505092959891949750929550565b6000806000606084860312156131a457600080fd5b6131ad84612d44565b95602085013595506040909401359392505050565b6000806000604084860312156131d757600080fd5b83359250602084013567ffffffffffffffff8111156131f557600080fd5b613201868287016130b1565b9497909650939450505050565b600080600080600080600060a0888a03121561322957600080fd5b8735965060208801359550604088013567ffffffffffffffff8082111561324f57600080fd5b61325b8b838c016130b1565b909750955060608a013591508082111561327457600080fd5b506132818a828b016130b1565b989b979a50959894979596608090950135949350505050565b6000806000806000608086880312156132b257600080fd5b6132bb86612d44565b945060208601359350604086013567ffffffffffffffff808211156132df57600080fd5b6132eb89838a01612f04565b9450606088013591508082111561330157600080fd5b5061330e88828901612f1c565b969995985093965092949392505050565b803563ffffffff81168114612d6857600080fd5b60008060006060848603121561334857600080fd5b833592506133586020850161331f565b91506133666040850161331f565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036133fe576133fe61339e565b5060010190565b60006060823603121561341757600080fd5b61341f612df0565b823567ffffffffffffffff8082111561343757600080fd5b9084019036601f83011261344a57600080fd5b813560208282111561345e5761345e612d97565b61348e817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612e13565b925081835236818386010111156134a457600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b601981101561350957825167ffffffffffffffff168252602092830192909101906001016134e0565b50505092915050565b600082198211156135255761352561339e565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261355f57600080fd5b83018035915067ffffffffffffffff82111561357a57600080fd5b602001915036819003821315612f6157600080fd5b600181815b808511156135e857817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156135ce576135ce61339e565b808516156135db57918102915b93841c9390800290613594565b509250929050565b6000826135ff575060016136ab565b8161360c575060006136ab565b8160018114613622576002811461362c57613648565b60019150506136ab565b60ff84111561363d5761363d61339e565b50506001821b6136ab565b5060208310610133831016604e8410600b841016171561366b575081810a6136ab565b613675838361358f565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156136a7576136a761339e565b0290505b92915050565b60006129ef83836135f0565b6000828210156136cf576136cf61339e565b500390565b600063ffffffff838116908316818110156136f1576136f161339e565b039392505050565b600063ffffffff8083168185168083038211156137185761371861339e565b01949350505050565b6000845160005b818110156137425760208188018101518583015201613728565b81811115613751576000828501525b509190910192835250602082015260400191905056fea164736f6c634300080f000a", Bin: "0x60e06040523480156200001157600080fd5b50604051620039fc380380620039fc8339810160408190526200003491620000f9565b60c083905260a0829052608081905260005b62000054600160106200013e565b811015620000ef576003816010811062000072576200007262000158565b0154600382601081106200008a576200008a62000158565b0154604080516020810193909352820152606001604051602081830303815290604052805190602001206003826001620000c591906200016e565b60108110620000d857620000d862000158565b015580620000e68162000189565b91505062000046565b50505050620001a5565b6000806000606084860312156200010f57600080fd5b8351925060208401519150604084015190509250925092565b634e487b7160e01b600052601160045260246000fd5b60008282101562000153576200015362000128565b500390565b634e487b7160e01b600052603260045260246000fd5b6000821982111562000184576200018462000128565b500190565b6000600182016200019e576200019e62000128565b5060010190565b60805160a05160c051613812620001ea6000396000818161054d0152611d9101526000818161062d01526115f9015260008181610810015261134301526138126000f3fe6080604052600436106101c25760003560e01c80638dc4be11116100f7578063dd24f9bf11610095578063ec5efcbc11610064578063ec5efcbc146105fe578063f3f480d91461061e578063faf37bc714610651578063fef2b4ed1461066457600080fd5b8063dd24f9bf1461053e578063ddcd58de14610571578063e03110e1146105a9578063e1592611146105de57600080fd5b8063b2e67ba8116100d1578063b2e67ba8146104b1578063b4801e61146104e9578063d18534b514610509578063da35c6641461052957600080fd5b80638dc4be11146104225780639d53a648146104425780639d7e87691461049157600080fd5b806361238bde116101645780637917de1d1161013e5780637917de1d1461035e5780637ac547671461037e5780638542cf501461039e578063882856ef146103e957600080fd5b806361238bde146102d25780636551927b1461030a5780637051472e1461034257600080fd5b80632055b36b116101a05780632055b36b146102685780633909af5c1461027d5780634d52b4c91461029d57806352f0f3ad146102b257600080fd5b8063013cf08b146101c75780630359a5631461021857806304697c7814610246575b600080fd5b3480156101d357600080fd5b506101e76101e2366004612d6f565b610691565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561022457600080fd5b50610238610233366004612db1565b6106d6565b60405190815260200161020f565b34801561025257600080fd5b50610266610261366004612e24565b61080e565b005b34801561027457600080fd5b50610238601081565b34801561028957600080fd5b50610266610298366004613048565b61099e565b3480156102a957600080fd5b50610238610bf5565b3480156102be57600080fd5b506102386102cd366004613134565b610c10565b3480156102de57600080fd5b506102386102ed36600461316f565b600160209081526000928352604080842090915290825290205481565b34801561031657600080fd5b50610238610325366004612db1565b601560209081526000928352604080842090915290825290205481565b34801561034e57600080fd5b506102386703782dace9d9000081565b34801561036a57600080fd5b50610266610379366004613191565b610ce5565b34801561038a57600080fd5b50610238610399366004612d6f565b6111d5565b3480156103aa57600080fd5b506103d96103b936600461316f565b600260209081526000928352604080842090915290825290205460ff1681565b604051901515815260200161020f565b3480156103f557600080fd5b5061040961040436600461322d565b6111ec565b60405167ffffffffffffffff909116815260200161020f565b34801561042e57600080fd5b5061026661043d366004613260565b611246565b34801561044e57600080fd5b5061023861045d366004612db1565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b34801561049d57600080fd5b506102666104ac3660046132ac565b611341565b3480156104bd57600080fd5b506102386104cc366004612db1565b601760209081526000928352604080842090915290825290205481565b3480156104f557600080fd5b5061023861050436600461322d565b611552565b34801561051557600080fd5b50610266610524366004613048565b611584565b34801561053557600080fd5b50601354610238565b34801561054a57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610238565b34801561057d57600080fd5b5061023861058c366004612db1565b601660209081526000928352604080842090915290825290205481565b3480156105b557600080fd5b506105c96105c436600461316f565b611946565b6040805192835260208301919091520161020f565b3480156105ea57600080fd5b506102666105f9366004613260565b611a37565b34801561060a57600080fd5b50610266610619366004613338565b611b3f565b34801561062a57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610238565b61026661065f3660046133d1565b611cc5565b34801561067057600080fd5b5061023861067f366004612d6f565b60006020819052908152604090205481565b601381815481106106a157600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260156020908152604080832084845290915281205481906107199060601c63ffffffff1690565b63ffffffff16905060005b601081101561080657816001166001036107ac5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107795761077961340d565b015460408051602081019290925281018490526060016040516020818303038152906040528051906020012092506107ed565b82600382601081106107c0576107c061340d565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c90806107fe8161346b565b915050610724565b505092915050565b7f0000000000000000000000000000000000000000000000000000000000000000421015610868576040517f299f254900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600080608060146030823785878260140137601480870182207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06000000000000000000000000000000000000000000000000000000000000001794506000908190889084018b5afa94503d60010191506008820189106108f55763fe2549876000526004601cfd5b60c082901b81526008018481533d6000600183013e88017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8015160008481526002602090815260408083208c8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915587845282528083209b83529a81528a82209290925593845283905296909120959095555050505050565b60006109aa8a8a6106d6565b90506109cd86868360208b01356109c86109c38d6134a3565b611f30565b611f70565b80156109eb57506109eb83838360208801356109c86109c38a6134a3565b610a21576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b866040013588604051602001610a379190613572565b6040516020818303038152906040528051906020012014610a84576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836020013587602001356001610a9a91906135b0565b14610ad1576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b1988610adf86806135c8565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611fd192505050565b610b228861212c565b836040013588604051602001610b389190613572565b6040516020818303038152906040528051906020012003610b85576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610be98a8a336128d4565b50505050505050505050565b6001610c036010600261374f565b610c0d919061375b565b81565b6000610c1c868661298d565b9050610c298360086135b0565b821180610c365750602083115b15610c6d576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610cfe57610cf78686612a3a565b9050610d38565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610d6557505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610de68260601c63ffffffff1690565b63ffffffff169050333214610e27576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e378260801c63ffffffff1690565b63ffffffff16600003610e76576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e808260c01c90565b67ffffffffffffffff1615610ec1576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610efa576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f0789898d8886612ab3565b83516020850160888204881415608883061715610f2c576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610fdc578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610fd1576001821615610fb15782818b0152610fd1565b8981015160009081526020938452604090209260019290921c9101610f94565b505050608801610f39565b50505050600160106002610ff0919061374f565b610ffa919061375b565b811115611033576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110a86110468360401c63ffffffff1690565b6110569063ffffffff168a6135b0565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b915084156111355777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b1791506110e28260801c63ffffffff1690565b63ffffffff166110f88360401c63ffffffff1690565b63ffffffff1614611135576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e8452909152902061115b90846010612ce5565b50503360008181526018602090815260408083208e8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055928252601581528282209c82529b909b52909920989098555050505050505050565b600381601081106111e557600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061121457600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b6044356000806008830186106112645763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061129157600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b7f000000000000000000000000000000000000000000000000000000000000000042101561139b576040517f299f254900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080603087600037602060006030600060025afa806113c35763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa925082611445576309bde3396000526004601cfd5b6028861061145b5763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b6014602052826000526040600020602052816000526040600020816010811061157a57600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156115f7576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006116228260c01c90565b6116369067ffffffffffffffff164261375b565b1161166d576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006116798b8b6106d6565b905061169287878360208c01356109c86109c38e6134a3565b80156116b057506116b084848360208901356109c86109c38b6134a3565b6116e6576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016116fc9190613572565b6040516020818303038152906040528051906020012014611749576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161175f91906135b0565b141580611791575060016117798360601c63ffffffff1690565b6117839190613772565b63ffffffff16856020013514155b156117c8576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117d689610adf87806135c8565b6117df8961212c565b60006117ea8a612c06565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f020000000000000000000000000000000000000000000000000000000000000017905060006118418460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d815260200190815260200160002054600160008481526020019081526020016000206000838152602001908152602001600020819055506119138460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556119378d8d816128d4565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166119cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546119eb8160086135b0565b6119f68560206135b0565b10611a145783611a078260086135b0565b611a11919061375b565b91505b506000938452600160209081526040808620948652939052919092205492909150565b604435600080600883018610611a555763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b6000611b4b86866106d6565b9050611b6483838360208801356109c86109c38a6134a3565b611b9a576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611bd6576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611bde612d23565b611bec81610adf87806135c8565b611bf58161212c565b846040013581604051602001611c0b9190613572565b6040516020818303038152906040528051906020012003611c58576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611cbc8787336128d4565b50505050505050565b6703782dace9d90000341015611d07576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611d40576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d4b816008613797565b63ffffffff168263ffffffff1610611d8f576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008163ffffffff161015611def576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000818152601560209081526040808320878452825280832080547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1660a09790971b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff169690961760809590951b949094179094558251808401845282815280850186815260138054600181018255908452915160029092027f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0908101805473ffffffffffffffffffffffffffffffffffffffff9094167fffffffffffffffffffffffff000000000000000000000000000000000000000090941693909317909255517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015590815260168352818120938152929091529020349055565b6000816000015182602001518360400151604051602001611f53939291906137bf565b604051602081830303815290604052805190602001209050919050565b60008160005b6010811015611fc4578060051b880135600186831c1660018114611fa95760008481526020839052604090209350611fba565b600082815260208590526040902093505b5050600101611f76565b5090931495945050505050565b6088815114611fdf57600080fd5b6020810160208301612060565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b171717905061205a81612045868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b61206c60008383611fec565b61207860018383611fec565b61208460028383611fec565b61209060038383611fec565b61209c60048383611fec565b6120a860058383611fec565b6120b460068383611fec565b6120c060078383611fec565b6120cc60088383611fec565b6120d860098383611fec565b6120e4600a8383611fec565b6120f0600b8383611fec565b6120fc600c8383611fec565b612108600d8383611fec565b612114600e8383611fec565b612120600f8383611fec565b61205a60108383611fec565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e001604051602081830303815290604052905060208201602082016127b4565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c6122df8660011b67ffffffffffffffff1690565b18188584603f1c6122fa8660011b67ffffffffffffffff1690565b18188584603f1c6123158660011b67ffffffffffffffff1690565b181895508483603f1c6123328560011b67ffffffffffffffff1690565b181894508387603f1c61234f8960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611cbc565b61274e6000826126c7565b6127596005826126c7565b612764600a826126c7565b61276f600f826126c7565b61277a6014826126c7565b50565b61278681612222565b61278f81612743565b600383901b820151815160c09190911c9061205a90821867ffffffffffffffff168352565b6127c06000828461277d565b6127cc6001828461277d565b6127d86002828461277d565b6127e46003828461277d565b6127f06004828461277d565b6127fc6005828461277d565b6128086006828461277d565b6128146007828461277d565b6128206008828461277d565b61282c6009828461277d565b612838600a828461277d565b612844600b828461277d565b612850600c828461277d565b61285c600d828461277d565b612868600e828461277d565b612874600f828461277d565b6128806010828461277d565b61288c6011828461277d565b6128986012828461277d565b6128a46013828461277d565b6128b06014828461277d565b6128bc6015828461277d565b6128c86016828461277d565b61205a6017828461277d565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d806000811461294d576040519150601f19603f3d011682016040523d82523d6000602084013e612952565b606091505b50509050806126c0576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831617612a33818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612a835760888290038501848101848103803687375060806001820353506001845160001a1784538652612a9a565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612ac58260a01c63ffffffff1690565b67ffffffffffffffff1690506000612ae38360801c63ffffffff1690565b63ffffffff1690506000612afd8460401c63ffffffff1690565b63ffffffff169050600883108015612b13575080155b15612b475760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612bfc565b60088310158015612b65575080612b5f60088561375b565b93508310155b8015612b795750612b7687826135b0565b83105b15612bfc576000612b8a828561375b565b905087612b988260206135b0565b10158015612ba4575085155b15612bdb576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612c89565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612c378360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612c648360101b67ffffffffffffffff1690565b1617905060008160201c612c828360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612ca190612c0d565b612c0d565b6040820151612caf90612c0d565b60401b17612cc7612c9c60018460059190911b015190565b825160809190911b90612cd990612c0d565b60c01b17179392505050565b8260108101928215612d13579160200282015b82811115612d13578251825591602001919060010190612cf8565b50612d1f929150612d3b565b5090565b6040518060200160405280612d36612d50565b905290565b5b80821115612d1f5760008155600101612d3c565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612d8157600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612dac57600080fd5b919050565b60008060408385031215612dc457600080fd5b612dcd83612d88565b946020939093013593505050565b60008083601f840112612ded57600080fd5b50813567ffffffffffffffff811115612e0557600080fd5b602083019150836020828501011115612e1d57600080fd5b9250929050565b60008060008060608587031215612e3a57600080fd5b84359350612e4a60208601612d88565b9250604085013567ffffffffffffffff811115612e6657600080fd5b612e7287828801612ddb565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612ed157612ed1612e7e565b60405290565b6040516060810167ffffffffffffffff81118282101715612ed157612ed1612e7e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612f4157612f41612e7e565b604052919050565b6000610320808385031215612f5d57600080fd5b604051602080820167ffffffffffffffff8382108183111715612f8257612f82612e7e565b8160405283955087601f880112612f9857600080fd5b612fa0612ead565b9487019491508188861115612fb457600080fd5b875b86811015612fdc5780358381168114612fcf5760008081fd5b8452928401928401612fb6565b50909352509295945050505050565b600060608284031215612ffd57600080fd5b50919050565b60008083601f84011261301557600080fd5b50813567ffffffffffffffff81111561302d57600080fd5b6020830191508360208260051b8501011115612e1d57600080fd5b60008060008060008060008060006103e08a8c03121561306757600080fd5b6130708a612d88565b985060208a013597506130868b60408c01612f49565b96506103608a013567ffffffffffffffff808211156130a457600080fd5b6130b08d838e01612feb565b97506103808c01359150808211156130c757600080fd5b6130d38d838e01613003565b90975095506103a08c01359150808211156130ed57600080fd5b6130f98d838e01612feb565b94506103c08c013591508082111561311057600080fd5b5061311d8c828d01613003565b915080935050809150509295985092959850929598565b600080600080600060a0868803121561314c57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b6000806040838503121561318257600080fd5b50508035926020909101359150565b600080600080600080600060a0888a0312156131ac57600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156131d257600080fd5b6131de8b838c01612ddb565b909750955060608a01359150808211156131f757600080fd5b506132048a828b01613003565b9094509250506080880135801515811461321d57600080fd5b8091505092959891949750929550565b60008060006060848603121561324257600080fd5b61324b84612d88565b95602085013595506040909401359392505050565b60008060006040848603121561327557600080fd5b83359250602084013567ffffffffffffffff81111561329357600080fd5b61329f86828701612ddb565b9497909650939450505050565b600080600080600080600060a0888a0312156132c757600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156132ed57600080fd5b6132f98b838c01612ddb565b909750955060608a013591508082111561331257600080fd5b5061331f8a828b01612ddb565b989b979a50959894979596608090950135949350505050565b60008060008060006080868803121561335057600080fd5b61335986612d88565b945060208601359350604086013567ffffffffffffffff8082111561337d57600080fd5b61338989838a01612feb565b9450606088013591508082111561339f57600080fd5b506133ac88828901613003565b969995985093965092949392505050565b803563ffffffff81168114612dac57600080fd5b6000806000606084860312156133e657600080fd5b833592506133f6602085016133bd565b9150613404604085016133bd565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361349c5761349c61343c565b5060010190565b6000606082360312156134b557600080fd5b6134bd612ed7565b823567ffffffffffffffff808211156134d557600080fd5b9084019036601f8301126134e857600080fd5b81356020828211156134fc576134fc612e7e565b61352c817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612efa565b9250818352368183860101111561354257600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b60198110156135a757825167ffffffffffffffff1682526020928301929091019060010161357e565b50505092915050565b600082198211156135c3576135c361343c565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126135fd57600080fd5b83018035915067ffffffffffffffff82111561361857600080fd5b602001915036819003821315612e1d57600080fd5b600181815b8085111561368657817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561366c5761366c61343c565b8085161561367957918102915b93841c9390800290613632565b509250929050565b60008261369d57506001613749565b816136aa57506000613749565b81600181146136c057600281146136ca576136e6565b6001915050613749565b60ff8411156136db576136db61343c565b50506001821b613749565b5060208310610133831016604e8410600b8410161715613709575081810a613749565b613713838361362d565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156137455761374561343c565b0290505b92915050565b6000612a33838361368e565b60008282101561376d5761376d61343c565b500390565b600063ffffffff8381169083168181101561378f5761378f61343c565b039392505050565b600063ffffffff8083168185168083038211156137b6576137b661343c565b01949350505050565b6000845160005b818110156137e057602081880181015185830152016137c6565b818111156137ef576000828501525b509190910192835250602082015260400191905056fea164736f6c634300080f000a",
} }
// PreimageOracleABI is the input ABI used to generate the binding from. // PreimageOracleABI is the input ABI used to generate the binding from.
...@@ -935,27 +935,6 @@ func (_PreimageOracle *PreimageOracleTransactorSession) LoadBlobPreimagePart(_z ...@@ -935,27 +935,6 @@ func (_PreimageOracle *PreimageOracleTransactorSession) LoadBlobPreimagePart(_z
return _PreimageOracle.Contract.LoadBlobPreimagePart(&_PreimageOracle.TransactOpts, _z, _y, _commitment, _proof, _partOffset) return _PreimageOracle.Contract.LoadBlobPreimagePart(&_PreimageOracle.TransactOpts, _z, _y, _commitment, _proof, _partOffset)
} }
// LoadKZGPointEvaluationPreimagePart is a paid mutator transaction binding the contract method 0x9dede8cc.
//
// Solidity: function loadKZGPointEvaluationPreimagePart(uint256 _partOffset, bytes _input) returns()
func (_PreimageOracle *PreimageOracleTransactor) LoadKZGPointEvaluationPreimagePart(opts *bind.TransactOpts, _partOffset *big.Int, _input []byte) (*types.Transaction, error) {
return _PreimageOracle.contract.Transact(opts, "loadKZGPointEvaluationPreimagePart", _partOffset, _input)
}
// LoadKZGPointEvaluationPreimagePart is a paid mutator transaction binding the contract method 0x9dede8cc.
//
// Solidity: function loadKZGPointEvaluationPreimagePart(uint256 _partOffset, bytes _input) returns()
func (_PreimageOracle *PreimageOracleSession) LoadKZGPointEvaluationPreimagePart(_partOffset *big.Int, _input []byte) (*types.Transaction, error) {
return _PreimageOracle.Contract.LoadKZGPointEvaluationPreimagePart(&_PreimageOracle.TransactOpts, _partOffset, _input)
}
// LoadKZGPointEvaluationPreimagePart is a paid mutator transaction binding the contract method 0x9dede8cc.
//
// Solidity: function loadKZGPointEvaluationPreimagePart(uint256 _partOffset, bytes _input) returns()
func (_PreimageOracle *PreimageOracleTransactorSession) LoadKZGPointEvaluationPreimagePart(_partOffset *big.Int, _input []byte) (*types.Transaction, error) {
return _PreimageOracle.Contract.LoadKZGPointEvaluationPreimagePart(&_PreimageOracle.TransactOpts, _partOffset, _input)
}
// LoadKeccak256PreimagePart is a paid mutator transaction binding the contract method 0xe1592611. // LoadKeccak256PreimagePart is a paid mutator transaction binding the contract method 0xe1592611.
// //
// Solidity: function loadKeccak256PreimagePart(uint256 _partOffset, bytes _preimage) returns() // Solidity: function loadKeccak256PreimagePart(uint256 _partOffset, bytes _preimage) returns()
...@@ -998,6 +977,27 @@ func (_PreimageOracle *PreimageOracleTransactorSession) LoadLocalData(_ident *bi ...@@ -998,6 +977,27 @@ func (_PreimageOracle *PreimageOracleTransactorSession) LoadLocalData(_ident *bi
return _PreimageOracle.Contract.LoadLocalData(&_PreimageOracle.TransactOpts, _ident, _localContext, _word, _size, _partOffset) return _PreimageOracle.Contract.LoadLocalData(&_PreimageOracle.TransactOpts, _ident, _localContext, _word, _size, _partOffset)
} }
// LoadPrecompilePreimagePart is a paid mutator transaction binding the contract method 0x04697c78.
//
// Solidity: function loadPrecompilePreimagePart(uint256 _partOffset, address _precompile, bytes _input) returns()
func (_PreimageOracle *PreimageOracleTransactor) LoadPrecompilePreimagePart(opts *bind.TransactOpts, _partOffset *big.Int, _precompile common.Address, _input []byte) (*types.Transaction, error) {
return _PreimageOracle.contract.Transact(opts, "loadPrecompilePreimagePart", _partOffset, _precompile, _input)
}
// LoadPrecompilePreimagePart is a paid mutator transaction binding the contract method 0x04697c78.
//
// Solidity: function loadPrecompilePreimagePart(uint256 _partOffset, address _precompile, bytes _input) returns()
func (_PreimageOracle *PreimageOracleSession) LoadPrecompilePreimagePart(_partOffset *big.Int, _precompile common.Address, _input []byte) (*types.Transaction, error) {
return _PreimageOracle.Contract.LoadPrecompilePreimagePart(&_PreimageOracle.TransactOpts, _partOffset, _precompile, _input)
}
// LoadPrecompilePreimagePart is a paid mutator transaction binding the contract method 0x04697c78.
//
// Solidity: function loadPrecompilePreimagePart(uint256 _partOffset, address _precompile, bytes _input) returns()
func (_PreimageOracle *PreimageOracleTransactorSession) LoadPrecompilePreimagePart(_partOffset *big.Int, _precompile common.Address, _input []byte) (*types.Transaction, error) {
return _PreimageOracle.Contract.LoadPrecompilePreimagePart(&_PreimageOracle.TransactOpts, _partOffset, _precompile, _input)
}
// LoadSha256PreimagePart is a paid mutator transaction binding the contract method 0x8dc4be11. // LoadSha256PreimagePart is a paid mutator transaction binding the contract method 0x8dc4be11.
// //
// Solidity: function loadSha256PreimagePart(uint256 _partOffset, bytes _preimage) returns() // Solidity: function loadSha256PreimagePart(uint256 _partOffset, bytes _preimage) returns()
......
...@@ -13,7 +13,7 @@ const PreimageOracleStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contrac ...@@ -13,7 +13,7 @@ const PreimageOracleStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contrac
var PreimageOracleStorageLayout = new(solc.StorageLayout) var PreimageOracleStorageLayout = new(solc.StorageLayout)
var PreimageOracleDeployedBin = "0x6080604052600436106101c25760003560e01c80639d53a648116100f7578063dd24f9bf11610095578063ec5efcbc11610064578063ec5efcbc146105fe578063f3f480d91461061e578063faf37bc714610651578063fef2b4ed1461066457600080fd5b8063dd24f9bf1461053e578063ddcd58de14610571578063e03110e1146105a9578063e1592611146105de57600080fd5b8063b2e67ba8116100d1578063b2e67ba8146104b1578063b4801e61146104e9578063d18534b514610509578063da35c6641461052957600080fd5b80639d53a648146104225780639d7e8769146104715780639dede8cc1461049157600080fd5b80636551927b116101645780637ac547671161013e5780637ac547671461035e5780638542cf501461037e578063882856ef146103c95780638dc4be111461040257600080fd5b80636551927b146102ea5780637051472e146103225780637917de1d1461033e57600080fd5b80633909af5c116101a05780633909af5c1461025b5780634d52b4c91461027d57806352f0f3ad1461029257806361238bde146102b257600080fd5b8063013cf08b146101c75780630359a563146102185780632055b36b14610246575b600080fd5b3480156101d357600080fd5b506101e76101e2366004612d2b565b610691565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561022457600080fd5b50610238610233366004612d6d565b6106d6565b60405190815260200161020f565b34801561025257600080fd5b50610238601081565b34801561026757600080fd5b5061027b610276366004612f68565b61080e565b005b34801561028957600080fd5b50610238610a65565b34801561029e57600080fd5b506102386102ad366004613054565b610a80565b3480156102be57600080fd5b506102386102cd36600461308f565b600160209081526000928352604080842090915290825290205481565b3480156102f657600080fd5b50610238610305366004612d6d565b601560209081526000928352604080842090915290825290205481565b34801561032e57600080fd5b506102386703782dace9d9000081565b34801561034a57600080fd5b5061027b6103593660046130f3565b610b55565b34801561036a57600080fd5b50610238610379366004612d2b565b611045565b34801561038a57600080fd5b506103b961039936600461308f565b600260209081526000928352604080842090915290825290205460ff1681565b604051901515815260200161020f565b3480156103d557600080fd5b506103e96103e436600461318f565b61105c565b60405167ffffffffffffffff909116815260200161020f565b34801561040e57600080fd5b5061027b61041d3660046131c2565b6110b6565b34801561042e57600080fd5b5061023861043d366004612d6d565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b34801561047d57600080fd5b5061027b61048c36600461320e565b6111b1565b34801561049d57600080fd5b5061027b6104ac3660046131c2565b6113c2565b3480156104bd57600080fd5b506102386104cc366004612d6d565b601760209081526000928352604080842090915290825290205481565b3480156104f557600080fd5b5061023861050436600461318f565b61150e565b34801561051557600080fd5b5061027b610524366004612f68565b611540565b34801561053557600080fd5b50601354610238565b34801561054a57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610238565b34801561057d57600080fd5b5061023861058c366004612d6d565b601660209081526000928352604080842090915290825290205481565b3480156105b557600080fd5b506105c96105c436600461308f565b611902565b6040805192835260208301919091520161020f565b3480156105ea57600080fd5b5061027b6105f93660046131c2565b6119f3565b34801561060a57600080fd5b5061027b61061936600461329a565b611afb565b34801561062a57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610238565b61027b61065f366004613333565b611c81565b34801561067057600080fd5b5061023861067f366004612d2b565b60006020819052908152604090205481565b601381815481106106a157600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260156020908152604080832084845290915281205481906107199060601c63ffffffff1690565b63ffffffff16905060005b601081101561080657816001166001036107ac5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107795761077961336f565b015460408051602081019290925281018490526060016040516020818303038152906040528051906020012092506107ed565b82600382601081106107c0576107c061336f565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c90806107fe816133cd565b915050610724565b505092915050565b600061081a8a8a6106d6565b905061083d86868360208b01356108386108338d613405565b611eec565b611f2c565b801561085b575061085b83838360208801356108386108338a613405565b610891576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8660400135886040516020016108a791906134d4565b60405160208183030381529060405280519060200120146108f4576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161090a9190613512565b14610941576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109898861094f868061352a565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f8d92505050565b610992886120e8565b8360400135886040516020016109a891906134d4565b60405160208183030381529060405280519060200120036109f5576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610a598a8a33612890565b50505050505050505050565b6001610a73601060026136b1565b610a7d91906136bd565b81565b6000610a8c8686612949565b9050610a99836008613512565b821180610aa65750602083115b15610add576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610b6e57610b6786866129f6565b9050610ba8565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610bd557505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610c568260601c63ffffffff1690565b63ffffffff169050333214610c97576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ca78260801c63ffffffff1690565b63ffffffff16600003610ce6576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cf08260c01c90565b67ffffffffffffffff1615610d31576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610d6a576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d7789898d8886612a6f565b83516020850160888204881415608883061715610d9c576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610e4c578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610e41576001821615610e215782818b0152610e41565b8981015160009081526020938452604090209260019290921c9101610e04565b505050608801610da9565b50505050600160106002610e6091906136b1565b610e6a91906136bd565b811115610ea3576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f18610eb68360401c63ffffffff1690565b610ec69063ffffffff168a613512565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b91508415610fa55777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b179150610f528260801c63ffffffff1690565b63ffffffff16610f688360401c63ffffffff1690565b63ffffffff1614610fa5576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e84529091529020610fcb90846010612ca1565b50503360008181526018602090815260408083208e8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055928252601581528282209c82529b909b52909920989098555050505050505050565b6003816010811061105557600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061108457600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b6044356000806008830186106110d45763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061110157600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b7f000000000000000000000000000000000000000000000000000000000000000042101561120b576040517f299f254900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080603087600037602060006030600060025afa806112335763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa9250826112b5576309bde3396000526004601cfd5b602886106112cb5763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b7f000000000000000000000000000000000000000000000000000000000000000042101561141c576040517f299f254900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060006080848682378481207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06000000000000000000000000000000000000000000000000000000000000001792506000808683600a5afa7801000000000000000000000000000000000000000000000000825260f81b600882015286015160008381526002602090815260408083208a8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558684528083528184209a845299825280832093909355938152928390529091209490945550505050565b6014602052826000526040600020602052816000526040600020816010811061153657600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156115b3576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006115de8260c01c90565b6115f29067ffffffffffffffff16426136bd565b11611629576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006116358b8b6106d6565b905061164e87878360208c01356108386108338e613405565b801561166c575061166c84848360208901356108386108338b613405565b6116a2576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016116b891906134d4565b6040516020818303038152906040528051906020012014611705576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161171b9190613512565b14158061174d575060016117358360601c63ffffffff1690565b61173f91906136d4565b63ffffffff16856020013514155b15611784576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117928961094f878061352a565b61179b896120e8565b60006117a68a612bc2565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f020000000000000000000000000000000000000000000000000000000000000017905060006117fd8460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d815260200190815260200160002054600160008481526020019081526020016000206000838152602001908152602001600020819055506118cf8460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556118f38d8d81612890565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff1661198b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546119a7816008613512565b6119b2856020613512565b106119d057836119c3826008613512565b6119cd91906136bd565b91505b506000938452600160209081526040808620948652939052919092205492909150565b604435600080600883018610611a115763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b6000611b0786866106d6565b9050611b2083838360208801356108386108338a613405565b611b56576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611b92576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b9a612cdf565b611ba88161094f878061352a565b611bb1816120e8565b846040013581604051602001611bc791906134d4565b6040516020818303038152906040528051906020012003611c14576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611c78878733612890565b50505050505050565b6703782dace9d90000341015611cc3576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611cfc576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d078160086136f9565b63ffffffff168263ffffffff1610611d4b576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008163ffffffff161015611dab576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000818152601560209081526040808320878452825280832080547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1660a09790971b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff169690961760809590951b949094179094558251808401845282815280850186815260138054600181018255908452915160029092027f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0908101805473ffffffffffffffffffffffffffffffffffffffff9094167fffffffffffffffffffffffff000000000000000000000000000000000000000090941693909317909255517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015590815260168352818120938152929091529020349055565b6000816000015182602001518360400151604051602001611f0f93929190613721565b604051602081830303815290604052805190602001209050919050565b60008160005b6010811015611f80578060051b880135600186831c1660018114611f655760008481526020839052604090209350611f76565b600082815260208590526040902093505b5050600101611f32565b5090931495945050505050565b6088815114611f9b57600080fd5b602081016020830161201c565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b171717905061201681612001868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b61202860008383611fa8565b61203460018383611fa8565b61204060028383611fa8565b61204c60038383611fa8565b61205860048383611fa8565b61206460058383611fa8565b61207060068383611fa8565b61207c60078383611fa8565b61208860088383611fa8565b61209460098383611fa8565b6120a0600a8383611fa8565b6120ac600b8383611fa8565b6120b8600c8383611fa8565b6120c4600d8383611fa8565b6120d0600e8383611fa8565b6120dc600f8383611fa8565b61201660108383611fa8565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e00160405160208183030381529060405290506020820160208201612770565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c61229b8660011b67ffffffffffffffff1690565b18188584603f1c6122b68660011b67ffffffffffffffff1690565b18188584603f1c6122d18660011b67ffffffffffffffff1690565b181895508483603f1c6122ee8560011b67ffffffffffffffff1690565b181894508387603f1c61230b8960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611c78565b61270a600082612683565b612715600582612683565b612720600a82612683565b61272b600f82612683565b612736601482612683565b50565b612742816121de565b61274b816126ff565b600383901b820151815160c09190911c9061201690821867ffffffffffffffff168352565b61277c60008284612739565b61278860018284612739565b61279460028284612739565b6127a060038284612739565b6127ac60048284612739565b6127b860058284612739565b6127c460068284612739565b6127d060078284612739565b6127dc60088284612739565b6127e860098284612739565b6127f4600a8284612739565b612800600b8284612739565b61280c600c8284612739565b612818600d8284612739565b612824600e8284612739565b612830600f8284612739565b61283c60108284612739565b61284860118284612739565b61285460128284612739565b61286060138284612739565b61286c60148284612739565b61287860158284612739565b61288460168284612739565b61201660178284612739565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d8060008114612909576040519150601f19603f3d011682016040523d82523d6000602084013e61290e565b606091505b505090508061267c576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316176129ef818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612a3f5760888290038501848101848103803687375060806001820353506001845160001a1784538652612a56565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612a818260a01c63ffffffff1690565b67ffffffffffffffff1690506000612a9f8360801c63ffffffff1690565b63ffffffff1690506000612ab98460401c63ffffffff1690565b63ffffffff169050600883108015612acf575080155b15612b035760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612bb8565b60088310158015612b21575080612b1b6008856136bd565b93508310155b8015612b355750612b328782613512565b83105b15612bb8576000612b4682856136bd565b905087612b54826020613512565b10158015612b60575085155b15612b97576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612c45565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612bf38360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612c208360101b67ffffffffffffffff1690565b1617905060008160201c612c3e8360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612c5d90612bc9565b612bc9565b6040820151612c6b90612bc9565b60401b17612c83612c5860018460059190911b015190565b825160809190911b90612c9590612bc9565b60c01b17179392505050565b8260108101928215612ccf579160200282015b82811115612ccf578251825591602001919060010190612cb4565b50612cdb929150612cf7565b5090565b6040518060200160405280612cf2612d0c565b905290565b5b80821115612cdb5760008155600101612cf8565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612d3d57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612d6857600080fd5b919050565b60008060408385031215612d8057600080fd5b612d8983612d44565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612dea57612dea612d97565b60405290565b6040516060810167ffffffffffffffff81118282101715612dea57612dea612d97565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612e5a57612e5a612d97565b604052919050565b6000610320808385031215612e7657600080fd5b604051602080820167ffffffffffffffff8382108183111715612e9b57612e9b612d97565b8160405283955087601f880112612eb157600080fd5b612eb9612dc6565b9487019491508188861115612ecd57600080fd5b875b86811015612ef55780358381168114612ee85760008081fd5b8452928401928401612ecf565b50909352509295945050505050565b600060608284031215612f1657600080fd5b50919050565b60008083601f840112612f2e57600080fd5b50813567ffffffffffffffff811115612f4657600080fd5b6020830191508360208260051b8501011115612f6157600080fd5b9250929050565b60008060008060008060008060006103e08a8c031215612f8757600080fd5b612f908a612d44565b985060208a01359750612fa68b60408c01612e62565b96506103608a013567ffffffffffffffff80821115612fc457600080fd5b612fd08d838e01612f04565b97506103808c0135915080821115612fe757600080fd5b612ff38d838e01612f1c565b90975095506103a08c013591508082111561300d57600080fd5b6130198d838e01612f04565b94506103c08c013591508082111561303057600080fd5b5061303d8c828d01612f1c565b915080935050809150509295985092959850929598565b600080600080600060a0868803121561306c57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b600080604083850312156130a257600080fd5b50508035926020909101359150565b60008083601f8401126130c357600080fd5b50813567ffffffffffffffff8111156130db57600080fd5b602083019150836020828501011115612f6157600080fd5b600080600080600080600060a0888a03121561310e57600080fd5b8735965060208801359550604088013567ffffffffffffffff8082111561313457600080fd5b6131408b838c016130b1565b909750955060608a013591508082111561315957600080fd5b506131668a828b01612f1c565b9094509250506080880135801515811461317f57600080fd5b8091505092959891949750929550565b6000806000606084860312156131a457600080fd5b6131ad84612d44565b95602085013595506040909401359392505050565b6000806000604084860312156131d757600080fd5b83359250602084013567ffffffffffffffff8111156131f557600080fd5b613201868287016130b1565b9497909650939450505050565b600080600080600080600060a0888a03121561322957600080fd5b8735965060208801359550604088013567ffffffffffffffff8082111561324f57600080fd5b61325b8b838c016130b1565b909750955060608a013591508082111561327457600080fd5b506132818a828b016130b1565b989b979a50959894979596608090950135949350505050565b6000806000806000608086880312156132b257600080fd5b6132bb86612d44565b945060208601359350604086013567ffffffffffffffff808211156132df57600080fd5b6132eb89838a01612f04565b9450606088013591508082111561330157600080fd5b5061330e88828901612f1c565b969995985093965092949392505050565b803563ffffffff81168114612d6857600080fd5b60008060006060848603121561334857600080fd5b833592506133586020850161331f565b91506133666040850161331f565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036133fe576133fe61339e565b5060010190565b60006060823603121561341757600080fd5b61341f612df0565b823567ffffffffffffffff8082111561343757600080fd5b9084019036601f83011261344a57600080fd5b813560208282111561345e5761345e612d97565b61348e817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612e13565b925081835236818386010111156134a457600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b601981101561350957825167ffffffffffffffff168252602092830192909101906001016134e0565b50505092915050565b600082198211156135255761352561339e565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261355f57600080fd5b83018035915067ffffffffffffffff82111561357a57600080fd5b602001915036819003821315612f6157600080fd5b600181815b808511156135e857817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156135ce576135ce61339e565b808516156135db57918102915b93841c9390800290613594565b509250929050565b6000826135ff575060016136ab565b8161360c575060006136ab565b8160018114613622576002811461362c57613648565b60019150506136ab565b60ff84111561363d5761363d61339e565b50506001821b6136ab565b5060208310610133831016604e8410600b841016171561366b575081810a6136ab565b613675838361358f565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156136a7576136a761339e565b0290505b92915050565b60006129ef83836135f0565b6000828210156136cf576136cf61339e565b500390565b600063ffffffff838116908316818110156136f1576136f161339e565b039392505050565b600063ffffffff8083168185168083038211156137185761371861339e565b01949350505050565b6000845160005b818110156137425760208188018101518583015201613728565b81811115613751576000828501525b509190910192835250602082015260400191905056fea164736f6c634300080f000a" var PreimageOracleDeployedBin = "0x6080604052600436106101c25760003560e01c80638dc4be11116100f7578063dd24f9bf11610095578063ec5efcbc11610064578063ec5efcbc146105fe578063f3f480d91461061e578063faf37bc714610651578063fef2b4ed1461066457600080fd5b8063dd24f9bf1461053e578063ddcd58de14610571578063e03110e1146105a9578063e1592611146105de57600080fd5b8063b2e67ba8116100d1578063b2e67ba8146104b1578063b4801e61146104e9578063d18534b514610509578063da35c6641461052957600080fd5b80638dc4be11146104225780639d53a648146104425780639d7e87691461049157600080fd5b806361238bde116101645780637917de1d1161013e5780637917de1d1461035e5780637ac547671461037e5780638542cf501461039e578063882856ef146103e957600080fd5b806361238bde146102d25780636551927b1461030a5780637051472e1461034257600080fd5b80632055b36b116101a05780632055b36b146102685780633909af5c1461027d5780634d52b4c91461029d57806352f0f3ad146102b257600080fd5b8063013cf08b146101c75780630359a5631461021857806304697c7814610246575b600080fd5b3480156101d357600080fd5b506101e76101e2366004612d6f565b610691565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561022457600080fd5b50610238610233366004612db1565b6106d6565b60405190815260200161020f565b34801561025257600080fd5b50610266610261366004612e24565b61080e565b005b34801561027457600080fd5b50610238601081565b34801561028957600080fd5b50610266610298366004613048565b61099e565b3480156102a957600080fd5b50610238610bf5565b3480156102be57600080fd5b506102386102cd366004613134565b610c10565b3480156102de57600080fd5b506102386102ed36600461316f565b600160209081526000928352604080842090915290825290205481565b34801561031657600080fd5b50610238610325366004612db1565b601560209081526000928352604080842090915290825290205481565b34801561034e57600080fd5b506102386703782dace9d9000081565b34801561036a57600080fd5b50610266610379366004613191565b610ce5565b34801561038a57600080fd5b50610238610399366004612d6f565b6111d5565b3480156103aa57600080fd5b506103d96103b936600461316f565b600260209081526000928352604080842090915290825290205460ff1681565b604051901515815260200161020f565b3480156103f557600080fd5b5061040961040436600461322d565b6111ec565b60405167ffffffffffffffff909116815260200161020f565b34801561042e57600080fd5b5061026661043d366004613260565b611246565b34801561044e57600080fd5b5061023861045d366004612db1565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b34801561049d57600080fd5b506102666104ac3660046132ac565b611341565b3480156104bd57600080fd5b506102386104cc366004612db1565b601760209081526000928352604080842090915290825290205481565b3480156104f557600080fd5b5061023861050436600461322d565b611552565b34801561051557600080fd5b50610266610524366004613048565b611584565b34801561053557600080fd5b50601354610238565b34801561054a57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610238565b34801561057d57600080fd5b5061023861058c366004612db1565b601660209081526000928352604080842090915290825290205481565b3480156105b557600080fd5b506105c96105c436600461316f565b611946565b6040805192835260208301919091520161020f565b3480156105ea57600080fd5b506102666105f9366004613260565b611a37565b34801561060a57600080fd5b50610266610619366004613338565b611b3f565b34801561062a57600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610238565b61026661065f3660046133d1565b611cc5565b34801561067057600080fd5b5061023861067f366004612d6f565b60006020819052908152604090205481565b601381815481106106a157600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260156020908152604080832084845290915281205481906107199060601c63ffffffff1690565b63ffffffff16905060005b601081101561080657816001166001036107ac5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107795761077961340d565b015460408051602081019290925281018490526060016040516020818303038152906040528051906020012092506107ed565b82600382601081106107c0576107c061340d565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c90806107fe8161346b565b915050610724565b505092915050565b7f0000000000000000000000000000000000000000000000000000000000000000421015610868576040517f299f254900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600080608060146030823785878260140137601480870182207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06000000000000000000000000000000000000000000000000000000000000001794506000908190889084018b5afa94503d60010191506008820189106108f55763fe2549876000526004601cfd5b60c082901b81526008018481533d6000600183013e88017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8015160008481526002602090815260408083208c8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915587845282528083209b83529a81528a82209290925593845283905296909120959095555050505050565b60006109aa8a8a6106d6565b90506109cd86868360208b01356109c86109c38d6134a3565b611f30565b611f70565b80156109eb57506109eb83838360208801356109c86109c38a6134a3565b610a21576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b866040013588604051602001610a379190613572565b6040516020818303038152906040528051906020012014610a84576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836020013587602001356001610a9a91906135b0565b14610ad1576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b1988610adf86806135c8565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611fd192505050565b610b228861212c565b836040013588604051602001610b389190613572565b6040516020818303038152906040528051906020012003610b85576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610be98a8a336128d4565b50505050505050505050565b6001610c036010600261374f565b610c0d919061375b565b81565b6000610c1c868661298d565b9050610c298360086135b0565b821180610c365750602083115b15610c6d576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610cfe57610cf78686612a3a565b9050610d38565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610d6557505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610de68260601c63ffffffff1690565b63ffffffff169050333214610e27576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e378260801c63ffffffff1690565b63ffffffff16600003610e76576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e808260c01c90565b67ffffffffffffffff1615610ec1576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610efa576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f0789898d8886612ab3565b83516020850160888204881415608883061715610f2c576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610fdc578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610fd1576001821615610fb15782818b0152610fd1565b8981015160009081526020938452604090209260019290921c9101610f94565b505050608801610f39565b50505050600160106002610ff0919061374f565b610ffa919061375b565b811115611033576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110a86110468360401c63ffffffff1690565b6110569063ffffffff168a6135b0565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b915084156111355777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b1791506110e28260801c63ffffffff1690565b63ffffffff166110f88360401c63ffffffff1690565b63ffffffff1614611135576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e8452909152902061115b90846010612ce5565b50503360008181526018602090815260408083208e8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055928252601581528282209c82529b909b52909920989098555050505050505050565b600381601081106111e557600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061121457600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b6044356000806008830186106112645763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061129157600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b7f000000000000000000000000000000000000000000000000000000000000000042101561139b576040517f299f254900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080603087600037602060006030600060025afa806113c35763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa925082611445576309bde3396000526004601cfd5b6028861061145b5763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b6014602052826000526040600020602052816000526040600020816010811061157a57600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156115f7576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006116228260c01c90565b6116369067ffffffffffffffff164261375b565b1161166d576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006116798b8b6106d6565b905061169287878360208c01356109c86109c38e6134a3565b80156116b057506116b084848360208901356109c86109c38b6134a3565b6116e6576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016116fc9190613572565b6040516020818303038152906040528051906020012014611749576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161175f91906135b0565b141580611791575060016117798360601c63ffffffff1690565b6117839190613772565b63ffffffff16856020013514155b156117c8576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6117d689610adf87806135c8565b6117df8961212c565b60006117ea8a612c06565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f020000000000000000000000000000000000000000000000000000000000000017905060006118418460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d815260200190815260200160002054600160008481526020019081526020016000206000838152602001908152602001600020819055506119138460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556119378d8d816128d4565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166119cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546119eb8160086135b0565b6119f68560206135b0565b10611a145783611a078260086135b0565b611a11919061375b565b91505b506000938452600160209081526040808620948652939052919092205492909150565b604435600080600883018610611a555763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b6000611b4b86866106d6565b9050611b6483838360208801356109c86109c38a6134a3565b611b9a576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611bd6576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611bde612d23565b611bec81610adf87806135c8565b611bf58161212c565b846040013581604051602001611c0b9190613572565b6040516020818303038152906040528051906020012003611c58576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611cbc8787336128d4565b50505050505050565b6703782dace9d90000341015611d07576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611d40576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d4b816008613797565b63ffffffff168263ffffffff1610611d8f576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008163ffffffff161015611def576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000818152601560209081526040808320878452825280832080547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1660a09790971b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff169690961760809590951b949094179094558251808401845282815280850186815260138054600181018255908452915160029092027f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0908101805473ffffffffffffffffffffffffffffffffffffffff9094167fffffffffffffffffffffffff000000000000000000000000000000000000000090941693909317909255517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015590815260168352818120938152929091529020349055565b6000816000015182602001518360400151604051602001611f53939291906137bf565b604051602081830303815290604052805190602001209050919050565b60008160005b6010811015611fc4578060051b880135600186831c1660018114611fa95760008481526020839052604090209350611fba565b600082815260208590526040902093505b5050600101611f76565b5090931495945050505050565b6088815114611fdf57600080fd5b6020810160208301612060565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b171717905061205a81612045868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b61206c60008383611fec565b61207860018383611fec565b61208460028383611fec565b61209060038383611fec565b61209c60048383611fec565b6120a860058383611fec565b6120b460068383611fec565b6120c060078383611fec565b6120cc60088383611fec565b6120d860098383611fec565b6120e4600a8383611fec565b6120f0600b8383611fec565b6120fc600c8383611fec565b612108600d8383611fec565b612114600e8383611fec565b612120600f8383611fec565b61205a60108383611fec565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e001604051602081830303815290604052905060208201602082016127b4565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c6122df8660011b67ffffffffffffffff1690565b18188584603f1c6122fa8660011b67ffffffffffffffff1690565b18188584603f1c6123158660011b67ffffffffffffffff1690565b181895508483603f1c6123328560011b67ffffffffffffffff1690565b181894508387603f1c61234f8960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611cbc565b61274e6000826126c7565b6127596005826126c7565b612764600a826126c7565b61276f600f826126c7565b61277a6014826126c7565b50565b61278681612222565b61278f81612743565b600383901b820151815160c09190911c9061205a90821867ffffffffffffffff168352565b6127c06000828461277d565b6127cc6001828461277d565b6127d86002828461277d565b6127e46003828461277d565b6127f06004828461277d565b6127fc6005828461277d565b6128086006828461277d565b6128146007828461277d565b6128206008828461277d565b61282c6009828461277d565b612838600a828461277d565b612844600b828461277d565b612850600c828461277d565b61285c600d828461277d565b612868600e828461277d565b612874600f828461277d565b6128806010828461277d565b61288c6011828461277d565b6128986012828461277d565b6128a46013828461277d565b6128b06014828461277d565b6128bc6015828461277d565b6128c86016828461277d565b61205a6017828461277d565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d806000811461294d576040519150601f19603f3d011682016040523d82523d6000602084013e612952565b606091505b50509050806126c0576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831617612a33818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612a835760888290038501848101848103803687375060806001820353506001845160001a1784538652612a9a565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612ac58260a01c63ffffffff1690565b67ffffffffffffffff1690506000612ae38360801c63ffffffff1690565b63ffffffff1690506000612afd8460401c63ffffffff1690565b63ffffffff169050600883108015612b13575080155b15612b475760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612bfc565b60088310158015612b65575080612b5f60088561375b565b93508310155b8015612b795750612b7687826135b0565b83105b15612bfc576000612b8a828561375b565b905087612b988260206135b0565b10158015612ba4575085155b15612bdb576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612c89565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612c378360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612c648360101b67ffffffffffffffff1690565b1617905060008160201c612c828360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612ca190612c0d565b612c0d565b6040820151612caf90612c0d565b60401b17612cc7612c9c60018460059190911b015190565b825160809190911b90612cd990612c0d565b60c01b17179392505050565b8260108101928215612d13579160200282015b82811115612d13578251825591602001919060010190612cf8565b50612d1f929150612d3b565b5090565b6040518060200160405280612d36612d50565b905290565b5b80821115612d1f5760008155600101612d3c565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612d8157600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612dac57600080fd5b919050565b60008060408385031215612dc457600080fd5b612dcd83612d88565b946020939093013593505050565b60008083601f840112612ded57600080fd5b50813567ffffffffffffffff811115612e0557600080fd5b602083019150836020828501011115612e1d57600080fd5b9250929050565b60008060008060608587031215612e3a57600080fd5b84359350612e4a60208601612d88565b9250604085013567ffffffffffffffff811115612e6657600080fd5b612e7287828801612ddb565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612ed157612ed1612e7e565b60405290565b6040516060810167ffffffffffffffff81118282101715612ed157612ed1612e7e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612f4157612f41612e7e565b604052919050565b6000610320808385031215612f5d57600080fd5b604051602080820167ffffffffffffffff8382108183111715612f8257612f82612e7e565b8160405283955087601f880112612f9857600080fd5b612fa0612ead565b9487019491508188861115612fb457600080fd5b875b86811015612fdc5780358381168114612fcf5760008081fd5b8452928401928401612fb6565b50909352509295945050505050565b600060608284031215612ffd57600080fd5b50919050565b60008083601f84011261301557600080fd5b50813567ffffffffffffffff81111561302d57600080fd5b6020830191508360208260051b8501011115612e1d57600080fd5b60008060008060008060008060006103e08a8c03121561306757600080fd5b6130708a612d88565b985060208a013597506130868b60408c01612f49565b96506103608a013567ffffffffffffffff808211156130a457600080fd5b6130b08d838e01612feb565b97506103808c01359150808211156130c757600080fd5b6130d38d838e01613003565b90975095506103a08c01359150808211156130ed57600080fd5b6130f98d838e01612feb565b94506103c08c013591508082111561311057600080fd5b5061311d8c828d01613003565b915080935050809150509295985092959850929598565b600080600080600060a0868803121561314c57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b6000806040838503121561318257600080fd5b50508035926020909101359150565b600080600080600080600060a0888a0312156131ac57600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156131d257600080fd5b6131de8b838c01612ddb565b909750955060608a01359150808211156131f757600080fd5b506132048a828b01613003565b9094509250506080880135801515811461321d57600080fd5b8091505092959891949750929550565b60008060006060848603121561324257600080fd5b61324b84612d88565b95602085013595506040909401359392505050565b60008060006040848603121561327557600080fd5b83359250602084013567ffffffffffffffff81111561329357600080fd5b61329f86828701612ddb565b9497909650939450505050565b600080600080600080600060a0888a0312156132c757600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156132ed57600080fd5b6132f98b838c01612ddb565b909750955060608a013591508082111561331257600080fd5b5061331f8a828b01612ddb565b989b979a50959894979596608090950135949350505050565b60008060008060006080868803121561335057600080fd5b61335986612d88565b945060208601359350604086013567ffffffffffffffff8082111561337d57600080fd5b61338989838a01612feb565b9450606088013591508082111561339f57600080fd5b506133ac88828901613003565b969995985093965092949392505050565b803563ffffffff81168114612dac57600080fd5b6000806000606084860312156133e657600080fd5b833592506133f6602085016133bd565b9150613404604085016133bd565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361349c5761349c61343c565b5060010190565b6000606082360312156134b557600080fd5b6134bd612ed7565b823567ffffffffffffffff808211156134d557600080fd5b9084019036601f8301126134e857600080fd5b81356020828211156134fc576134fc612e7e565b61352c817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612efa565b9250818352368183860101111561354257600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b60198110156135a757825167ffffffffffffffff1682526020928301929091019060010161357e565b50505092915050565b600082198211156135c3576135c361343c565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126135fd57600080fd5b83018035915067ffffffffffffffff82111561361857600080fd5b602001915036819003821315612e1d57600080fd5b600181815b8085111561368657817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561366c5761366c61343c565b8085161561367957918102915b93841c9390800290613632565b509250929050565b60008261369d57506001613749565b816136aa57506000613749565b81600181146136c057600281146136ca576136e6565b6001915050613749565b60ff8411156136db576136db61343c565b50506001821b613749565b5060208310610133831016604e8410600b8410161715613709575081810a613749565b613713838361362d565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156137455761374561343c565b0290505b92915050565b6000612a33838361368e565b60008282101561376d5761376d61343c565b500390565b600063ffffffff8381169083168181101561378f5761378f61343c565b039392505050565b600063ffffffff8083168185168083038211156137b6576137b661343c565b01949350505050565b6000845160005b818110156137e057602081880181015185830152016137c6565b818111156137ef576000828501525b509190910192835250602082015260400191905056fea164736f6c634300080f000a"
func init() { func init() {
......
...@@ -20,25 +20,25 @@ import ( ...@@ -20,25 +20,25 @@ import (
) )
const ( const (
methodInitLPP = "initLPP" methodInitLPP = "initLPP"
methodAddLeavesLPP = "addLeavesLPP" methodAddLeavesLPP = "addLeavesLPP"
methodSqueezeLPP = "squeezeLPP" methodSqueezeLPP = "squeezeLPP"
methodLoadKeccak256PreimagePart = "loadKeccak256PreimagePart" methodLoadKeccak256PreimagePart = "loadKeccak256PreimagePart"
methodLoadSha256PreimagePart = "loadSha256PreimagePart" methodLoadSha256PreimagePart = "loadSha256PreimagePart"
methodLoadBlobPreimagePart = "loadBlobPreimagePart" methodLoadBlobPreimagePart = "loadBlobPreimagePart"
methodLoadKZGPointEvaluationPreimagePart = "loadKZGPointEvaluationPreimagePart" methodLoadPrecompilePreimagePart = "loadPrecompilePreimagePart"
methodProposalCount = "proposalCount" methodProposalCount = "proposalCount"
methodProposals = "proposals" methodProposals = "proposals"
methodProposalMetadata = "proposalMetadata" methodProposalMetadata = "proposalMetadata"
methodProposalBlocksLen = "proposalBlocksLen" methodProposalBlocksLen = "proposalBlocksLen"
methodProposalBlocks = "proposalBlocks" methodProposalBlocks = "proposalBlocks"
methodPreimagePartOk = "preimagePartOk" methodPreimagePartOk = "preimagePartOk"
methodMinProposalSize = "minProposalSize" methodMinProposalSize = "minProposalSize"
methodChallengeFirstLPP = "challengeFirstLPP" methodChallengeFirstLPP = "challengeFirstLPP"
methodChallengeLPP = "challengeLPP" methodChallengeLPP = "challengeLPP"
methodChallengePeriod = "challengePeriod" methodChallengePeriod = "challengePeriod"
methodGetTreeRootLPP = "getTreeRootLPP" methodGetTreeRootLPP = "getTreeRootLPP"
methodMinBondSizeLPP = "MIN_BOND_SIZE" methodMinBondSizeLPP = "MIN_BOND_SIZE"
) )
var ( var (
...@@ -107,8 +107,11 @@ func (c *PreimageOracleContract) AddGlobalDataTx(data *types.PreimageOracleData) ...@@ -107,8 +107,11 @@ func (c *PreimageOracleContract) AddGlobalDataTx(data *types.PreimageOracleData)
data.BlobProof, data.BlobProof,
new(big.Int).SetUint64(uint64(data.OracleOffset))) new(big.Int).SetUint64(uint64(data.OracleOffset)))
return call.ToTxCandidate() return call.ToTxCandidate()
case preimage.KZGPointEvaluationKeyType: case preimage.PrecompileKeyType:
call := c.contract.Call(methodLoadKZGPointEvaluationPreimagePart, new(big.Int).SetUint64(uint64(data.OracleOffset)), data.GetPreimageWithoutSize()) call := c.contract.Call(methodLoadPrecompilePreimagePart,
new(big.Int).SetUint64(uint64(data.OracleOffset)),
data.GetPrecompileAddress(),
data.GetPrecompileInput())
return call.ToTxCandidate() return call.ToTxCandidate()
default: default:
return txmgr.TxCandidate{}, fmt.Errorf("%w: %v", ErrUnsupportedKeyType, keyType) return txmgr.TxCandidate{}, fmt.Errorf("%w: %v", ErrUnsupportedKeyType, keyType)
......
...@@ -71,13 +71,14 @@ func TestPreimageOracleContract_AddGlobalDataTx(t *testing.T) { ...@@ -71,13 +71,14 @@ func TestPreimageOracleContract_AddGlobalDataTx(t *testing.T) {
stubRpc.VerifyTxCandidate(tx) stubRpc.VerifyTxCandidate(tx)
}) })
t.Run("KZGPointEvaluation", func(t *testing.T) { t.Run("Precompile", func(t *testing.T) {
stubRpc, oracle := setupPreimageOracleTest(t) stubRpc, oracle := setupPreimageOracleTest(t)
input := testutils.RandomData(rand.New(rand.NewSource(23)), 200) input := testutils.RandomData(rand.New(rand.NewSource(23)), 200)
data := types.NewPreimageOracleData(common.Hash{byte(preimage.KZGPointEvaluationKeyType), 0xcc}.Bytes(), input, uint32(545)) data := types.NewPreimageOracleData(common.Hash{byte(preimage.PrecompileKeyType), 0xcc}.Bytes(), input, uint32(545))
stubRpc.SetResponse(oracleAddr, methodLoadKZGPointEvaluationPreimagePart, batching.BlockLatest, []interface{}{ stubRpc.SetResponse(oracleAddr, methodLoadPrecompilePreimagePart, batching.BlockLatest, []interface{}{
new(big.Int).SetUint64(uint64(data.OracleOffset)), new(big.Int).SetUint64(uint64(data.OracleOffset)),
data.GetPreimageWithoutSize(), data.GetPrecompileAddress(),
data.GetPrecompileInput(),
}, nil) }, nil)
tx, err := oracle.AddGlobalDataTx(data) tx, err := oracle.AddGlobalDataTx(data)
......
...@@ -46,8 +46,8 @@ func (l *preimageLoader) LoadPreimage(proof *proofData) (*types.PreimageOracleDa ...@@ -46,8 +46,8 @@ func (l *preimageLoader) LoadPreimage(proof *proofData) (*types.PreimageOracleDa
switch preimage.KeyType(proof.OracleKey[0]) { switch preimage.KeyType(proof.OracleKey[0]) {
case preimage.BlobKeyType: case preimage.BlobKeyType:
return l.loadBlobPreimage(proof) return l.loadBlobPreimage(proof)
case preimage.KZGPointEvaluationKeyType: case preimage.PrecompileKeyType:
return l.loadKZGPointEvaluationPreimage(proof) return l.loadPrecompilePreimage(proof)
default: default:
return types.NewPreimageOracleData(proof.OracleKey, proof.OracleValue, proof.OracleOffset), nil return types.NewPreimageOracleData(proof.OracleKey, proof.OracleValue, proof.OracleOffset), nil
} }
...@@ -102,7 +102,7 @@ func (l *preimageLoader) loadBlobPreimage(proof *proofData) (*types.PreimageOrac ...@@ -102,7 +102,7 @@ func (l *preimageLoader) loadBlobPreimage(proof *proofData) (*types.PreimageOrac
return types.NewPreimageOracleBlobData(proof.OracleKey, claimWithLength, proof.OracleOffset, requiredFieldElement, commitment, kzgProof[:]), nil return types.NewPreimageOracleBlobData(proof.OracleKey, claimWithLength, proof.OracleOffset, requiredFieldElement, commitment, kzgProof[:]), nil
} }
func (l *preimageLoader) loadKZGPointEvaluationPreimage(proof *proofData) (*types.PreimageOracleData, error) { func (l *preimageLoader) loadPrecompilePreimage(proof *proofData) (*types.PreimageOracleData, error) {
inputKey := preimage.Keccak256Key(proof.OracleKey).PreimageKey() inputKey := preimage.Keccak256Key(proof.OracleKey).PreimageKey()
input, err := l.getPreimage(inputKey) input, err := l.getPreimage(inputKey)
if err != nil { if err != nil {
......
...@@ -152,9 +152,9 @@ func TestPreimageLoader_BlobPreimage(t *testing.T) { ...@@ -152,9 +152,9 @@ func TestPreimageLoader_BlobPreimage(t *testing.T) {
}) })
} }
func TestPreimageLoader_KZGPointEvaluationPreimage(t *testing.T) { func TestPreimageLoader_PrecompilePreimage(t *testing.T) {
input := []byte("test input") input := []byte("test input")
key := preimage.KZGPointEvaluationKey(crypto.Keccak256Hash(input)).PreimageKey() key := preimage.PrecompileKey(crypto.Keccak256Hash(input)).PreimageKey()
proof := &proofData{ proof := &proofData{
OracleKey: key[:], OracleKey: key[:],
} }
......
...@@ -265,8 +265,8 @@ func FirstKeccakPreimageLoad() PreimageOpt { ...@@ -265,8 +265,8 @@ func FirstKeccakPreimageLoad() PreimageOpt {
return FirstPreimageLoadOfType("keccak") return FirstPreimageLoadOfType("keccak")
} }
func FirstKZGPointEvaluationPreimageLoad() PreimageOpt { func FirstPrecompilePreimageLoad() PreimageOpt {
return FirstPreimageLoadOfType("kzg-point-evaluation") return FirstPreimageLoadOfType("precompile")
} }
func PreimageLargerThan(size int) PreimageOpt { func PreimageLargerThan(size int) PreimageOpt {
......
...@@ -54,6 +54,14 @@ func (p *PreimageOracleData) GetPreimageWithSize() []byte { ...@@ -54,6 +54,14 @@ func (p *PreimageOracleData) GetPreimageWithSize() []byte {
return p.oracleData return p.oracleData
} }
func (p *PreimageOracleData) GetPrecompileAddress() common.Address {
return common.BytesToAddress(p.oracleData[8:28])
}
func (p *PreimageOracleData) GetPrecompileInput() []byte {
return p.oracleData[28:]
}
// NewPreimageOracleData creates a new [PreimageOracleData] instance. // NewPreimageOracleData creates a new [PreimageOracleData] instance.
func NewPreimageOracleData(key []byte, data []byte, offset uint32) *PreimageOracleData { func NewPreimageOracleData(key []byte, data []byte, offset uint32) *PreimageOracleData {
return &PreimageOracleData{ return &PreimageOracleData{
......
...@@ -639,8 +639,13 @@ func (g *OutputGameHelper) uploadPreimage(ctx context.Context, data *types.Preim ...@@ -639,8 +639,13 @@ func (g *OutputGameHelper) uploadPreimage(ctx context.Context, data *types.Preim
g.require.NoError(err) g.require.NoError(err)
var tx *gethtypes.Transaction var tx *gethtypes.Transaction
switch data.OracleKey[0] { switch data.OracleKey[0] {
case byte(preimage.KZGPointEvaluationKeyType): case byte(preimage.PrecompileKeyType):
tx, err = boundOracle.LoadKZGPointEvaluationPreimagePart(g.opts, new(big.Int).SetUint64(uint64(data.OracleOffset)), data.GetPreimageWithoutSize()) tx, err = boundOracle.LoadPrecompilePreimagePart(
g.opts,
new(big.Int).SetUint64(uint64(data.OracleOffset)),
data.GetPrecompileAddress(),
data.GetPrecompileInput(),
)
default: default:
tx, err = boundOracle.LoadKeccak256PreimagePart(g.opts, new(big.Int).SetUint64(uint64(data.OracleOffset)), data.GetPreimageWithoutSize()) tx, err = boundOracle.LoadKeccak256PreimagePart(g.opts, new(big.Int).SetUint64(uint64(data.OracleOffset)), data.GetPreimageWithoutSize())
} }
......
...@@ -334,7 +334,7 @@ func TestOutputCannonStepWithKZGPointEvaluation(t *testing.T) { ...@@ -334,7 +334,7 @@ func TestOutputCannonStepWithKZGPointEvaluation(t *testing.T) {
// Now the honest challenger is positioned as the defender of the execution game // Now the honest challenger is positioned as the defender of the execution game
// We then move to challenge it to induce a preimage load // We then move to challenge it to induce a preimage load
preimageLoadCheck := game.CreateStepPreimageLoadCheck(ctx) preimageLoadCheck := game.CreateStepPreimageLoadCheck(ctx)
game.ChallengeToPreimageLoad(ctx, outputRootClaim, sys.Cfg.Secrets.Alice, cannon.FirstKZGPointEvaluationPreimageLoad(), preimageLoadCheck, preloadPreimage) game.ChallengeToPreimageLoad(ctx, outputRootClaim, sys.Cfg.Secrets.Alice, cannon.FirstPrecompilePreimageLoad(), preimageLoadCheck, preloadPreimage)
// The above method already verified the image was uploaded and step called successfully // The above method already verified the image was uploaded and step called successfully
// So we don't waste time resolving the game - that's tested elsewhere. // So we don't waste time resolving the game - that's tested elsewhere.
} }
......
...@@ -40,8 +40,8 @@ const ( ...@@ -40,8 +40,8 @@ const (
Sha256KeyType KeyType = 4 Sha256KeyType KeyType = 4
// BlobKeyType is for blob point pre-images. // BlobKeyType is for blob point pre-images.
BlobKeyType KeyType = 5 BlobKeyType KeyType = 5
// KZGPointEvaluationKeyType is for KZG point-evaluation pre-images. // PrecompileKeyType is for precompile result pre-images.
KZGPointEvaluationKeyType KeyType = 6 PrecompileKeyType KeyType = 6
) )
// LocalIndexKey is a key local to the program, indexing a special program input. // LocalIndexKey is a key local to the program, indexing a special program input.
...@@ -104,20 +104,20 @@ func (k BlobKey) TerminalString() string { ...@@ -104,20 +104,20 @@ func (k BlobKey) TerminalString() string {
return "0x" + hex.EncodeToString(k[:]) return "0x" + hex.EncodeToString(k[:])
} }
// KZGPointEvaluationKey is the hash of a KZG point-evaluation EVM call input-data // PrecompileKey is the hash of precompile address and its input data
type KZGPointEvaluationKey [32]byte type PrecompileKey [32]byte
func (k KZGPointEvaluationKey) PreimageKey() (out [32]byte) { func (k PrecompileKey) PreimageKey() (out [32]byte) {
out = k out = k
out[0] = byte(KZGPointEvaluationKeyType) out[0] = byte(PrecompileKeyType)
return return
} }
func (k KZGPointEvaluationKey) String() string { func (k PrecompileKey) String() string {
return "0x" + hex.EncodeToString(k[:]) return "0x" + hex.EncodeToString(k[:])
} }
func (k KZGPointEvaluationKey) TerminalString() string { func (k PrecompileKey) TerminalString() string {
return "0x" + hex.EncodeToString(k[:]) return "0x" + hex.EncodeToString(k[:])
} }
......
...@@ -66,11 +66,11 @@ func TestPreimageKeyTypes(t *testing.T) { ...@@ -66,11 +66,11 @@ func TestPreimageKeyTypes(t *testing.T) {
t.Run("KZGPointEvaluationKey", func(t *testing.T) { t.Run("KZGPointEvaluationKey", func(t *testing.T) {
fauxHash := [32]byte{} fauxHash := [32]byte{}
fauxHash[31] = 0xFF fauxHash[31] = 0xFF
actual := KZGPointEvaluationKey(fauxHash) actual := PrecompileKey(fauxHash)
// PreimageKey encoding // PreimageKey encoding
expected := [32]byte{} expected := [32]byte{}
expected[0] = byte(KZGPointEvaluationKeyType) expected[0] = byte(PrecompileKeyType)
expected[31] = 0xFF expected[31] = 0xFF
require.Equal(t, expected, actual.PreimageKey()) require.Equal(t, expected, actual.PreimageKey())
......
...@@ -38,8 +38,8 @@ func WithVerification(source PreimageGetter) PreimageGetter { ...@@ -38,8 +38,8 @@ func WithVerification(source PreimageGetter) PreimageGetter {
case BlobKeyType: case BlobKeyType:
// Can't verify an individual field element without having a kzg proof // Can't verify an individual field element without having a kzg proof
return data, nil return data, nil
case KZGPointEvaluationKeyType: case PrecompileKeyType:
// Can't verify the KZG point evaluation result without having a kzg proof // Can't verify precompile result without knowing the input preimage
return data, nil return data, nil
default: default:
return nil, fmt.Errorf("%w: %v", ErrUnsupportedKeyType, key[0]) return nil, fmt.Errorf("%w: %v", ErrUnsupportedKeyType, key[0])
......
...@@ -41,7 +41,7 @@ func TestWithVerification(t *testing.T) { ...@@ -41,7 +41,7 @@ func TestWithVerification(t *testing.T) {
}, },
{ {
name: "KZGPointEvaluationKey NoVerification", name: "KZGPointEvaluationKey NoVerification",
key: KZGPointEvaluationKey([32]byte{1, 2, 3, 4}), key: PrecompileKey([32]byte{1, 2, 3, 4}),
data: []byte{4, 3, 5, 7, 3}, data: []byte{4, 3, 5, 7, 3},
expectedData: []byte{4, 3, 5, 7, 3}, expectedData: []byte{4, 3, 5, 7, 3},
}, },
......
...@@ -17,12 +17,17 @@ const cacheSize = 2000 ...@@ -17,12 +17,17 @@ const cacheSize = 2000
// CachingOracle is an implementation of Oracle that delegates to another implementation, adding caching of all results // CachingOracle is an implementation of Oracle that delegates to another implementation, adding caching of all results
type CachingOracle struct { type CachingOracle struct {
oracle Oracle oracle Oracle
blocks *simplelru.LRU[common.Hash, eth.BlockInfo] blocks *simplelru.LRU[common.Hash, eth.BlockInfo]
txs *simplelru.LRU[common.Hash, types.Transactions] txs *simplelru.LRU[common.Hash, types.Transactions]
rcpts *simplelru.LRU[common.Hash, types.Receipts] rcpts *simplelru.LRU[common.Hash, types.Receipts]
blobs *simplelru.LRU[common.Hash, *eth.Blob] blobs *simplelru.LRU[common.Hash, *eth.Blob]
ptEvals *simplelru.LRU[common.Hash, bool] pcmps *simplelru.LRU[common.Hash, precompileResult]
}
type precompileResult struct {
result []byte
ok bool
} }
func NewCachingOracle(oracle Oracle) *CachingOracle { func NewCachingOracle(oracle Oracle) *CachingOracle {
...@@ -30,14 +35,14 @@ func NewCachingOracle(oracle Oracle) *CachingOracle { ...@@ -30,14 +35,14 @@ func NewCachingOracle(oracle Oracle) *CachingOracle {
txsLRU, _ := simplelru.NewLRU[common.Hash, types.Transactions](cacheSize, nil) txsLRU, _ := simplelru.NewLRU[common.Hash, types.Transactions](cacheSize, nil)
rcptsLRU, _ := simplelru.NewLRU[common.Hash, types.Receipts](cacheSize, nil) rcptsLRU, _ := simplelru.NewLRU[common.Hash, types.Receipts](cacheSize, nil)
blobsLRU, _ := simplelru.NewLRU[common.Hash, *eth.Blob](cacheSize, nil) blobsLRU, _ := simplelru.NewLRU[common.Hash, *eth.Blob](cacheSize, nil)
ptEvals, _ := simplelru.NewLRU[common.Hash, bool](cacheSize, nil) pcmps, _ := simplelru.NewLRU[common.Hash, precompileResult](cacheSize, nil)
return &CachingOracle{ return &CachingOracle{
oracle: oracle, oracle: oracle,
blocks: blockLRU, blocks: blockLRU,
txs: txsLRU, txs: txsLRU,
rcpts: rcptsLRU, rcpts: rcptsLRU,
blobs: blobsLRU, blobs: blobsLRU,
ptEvals: ptEvals, pcmps: pcmps,
} }
} }
...@@ -90,13 +95,12 @@ func (o *CachingOracle) GetBlob(ref eth.L1BlockRef, blobHash eth.IndexedBlobHash ...@@ -90,13 +95,12 @@ func (o *CachingOracle) GetBlob(ref eth.L1BlockRef, blobHash eth.IndexedBlobHash
return blob return blob
} }
func (o *CachingOracle) KZGPointEvaluation(input []byte) bool { func (o *CachingOracle) Precompile(address common.Address, input []byte) ([]byte, bool) {
cacheKey := crypto.Keccak256Hash(input) cacheKey := crypto.Keccak256Hash(append(address.Bytes(), input...))
ptEval, ok := o.ptEvals.Get(cacheKey) if val, ok := o.pcmps.Get(cacheKey); ok {
if ok { return val.result, val.ok
return ptEval
} }
ptEval = o.oracle.KZGPointEvaluation(input) res, ok := o.oracle.Precompile(address, input)
o.ptEvals.Add(cacheKey, ptEval) o.pcmps.Add(cacheKey, precompileResult{res, ok})
return ptEval return res, ok
} }
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"github.com/ethereum-optimism/optimism/op-program/client/l1/test" "github.com/ethereum-optimism/optimism/op-program/client/l1/test"
"github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-service/testutils" "github.com/ethereum-optimism/optimism/op-service/testutils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
...@@ -93,19 +94,23 @@ func TestCachingOracle_GetBlobs(t *testing.T) { ...@@ -93,19 +94,23 @@ func TestCachingOracle_GetBlobs(t *testing.T) {
require.Equal(t, &blob, actualBlob) require.Equal(t, &blob, actualBlob)
} }
func TestCachingOracle_KZGPointEvaluation(t *testing.T) { func TestCachingOracle_Precompile(t *testing.T) {
stub := test.NewStubOracle(t) stub := test.NewStubOracle(t)
oracle := NewCachingOracle(stub) oracle := NewCachingOracle(stub)
input := []byte{0x01, 0x02, 0x03, 0x04} input := []byte{0x01, 0x02, 0x03, 0x04}
output := []byte{0x0a, 0x0b, 0x0c, 0x0d}
addr := common.Address{0x1}
// Initial call retrieves from the stub // Initial call retrieves from the stub
stub.PtEvals[crypto.Keccak256Hash(input)] = true stub.PcmpResults[crypto.Keccak256Hash(append(addr.Bytes(), input...))] = output
actualPtEval := oracle.KZGPointEvaluation(input) actualResult, actualStatus := oracle.Precompile(addr, input)
require.True(t, actualPtEval) require.True(t, actualStatus)
require.EqualValues(t, output, actualResult)
// Later calls should retrieve from cache // Later calls should retrieve from cache
delete(stub.PtEvals, crypto.Keccak256Hash(input)) delete(stub.PcmpResults, crypto.Keccak256Hash(append(addr.Bytes(), input...)))
actualPtEval = oracle.KZGPointEvaluation(input) actualResult, actualStatus = oracle.Precompile(addr, input)
require.True(t, actualPtEval) require.True(t, actualStatus)
require.EqualValues(t, output, actualResult)
} }
...@@ -8,11 +8,11 @@ import ( ...@@ -8,11 +8,11 @@ import (
) )
const ( const (
HintL1BlockHeader = "l1-block-header" HintL1BlockHeader = "l1-block-header"
HintL1Transactions = "l1-transactions" HintL1Transactions = "l1-transactions"
HintL1Receipts = "l1-receipts" HintL1Receipts = "l1-receipts"
HintL1Blob = "l1-blob" HintL1Blob = "l1-blob"
HintL1KZGPointEvaluation = "l1-kzg-point-evaluation" HintL1Precompile = "l1-precompile"
) )
type BlockHeaderHint common.Hash type BlockHeaderHint common.Hash
...@@ -47,10 +47,10 @@ func (l BlobHint) Hint() string { ...@@ -47,10 +47,10 @@ func (l BlobHint) Hint() string {
return HintL1Blob + " " + hexutil.Encode(l) return HintL1Blob + " " + hexutil.Encode(l)
} }
type KZGPointEvaluationHint []byte type PrecompileHint []byte
var _ preimage.Hint = KZGPointEvaluationHint{} var _ preimage.Hint = PrecompileHint{}
func (l KZGPointEvaluationHint) Hint() string { func (l PrecompileHint) Hint() string {
return HintL1KZGPointEvaluation + " " + hexutil.Encode(l) return HintL1Precompile + " " + hexutil.Encode(l)
} }
...@@ -25,11 +25,11 @@ type Oracle interface { ...@@ -25,11 +25,11 @@ type Oracle interface {
// ReceiptsByBlockHash retrieves the receipts from the block with the given hash. // ReceiptsByBlockHash retrieves the receipts from the block with the given hash.
ReceiptsByBlockHash(blockHash common.Hash) (eth.BlockInfo, types.Receipts) ReceiptsByBlockHash(blockHash common.Hash) (eth.BlockInfo, types.Receipts)
// GetBlobField retrieves the field element at the given index from the blob with the given hash. // GetBlob retrieves the blob with the given hash.
GetBlob(ref eth.L1BlockRef, blobHash eth.IndexedBlobHash) *eth.Blob GetBlob(ref eth.L1BlockRef, blobHash eth.IndexedBlobHash) *eth.Blob
// KZGPointEvaluation retriees the result of the Cancun KZG point evaluation precompile for the given input. // Precompile retrieves the result and success indicator of a precompile call for the given input.
KZGPointEvaluation(input []byte) bool Precompile(precompileAddress common.Address, input []byte) ([]byte, bool)
} }
// PreimageOracle implements Oracle using by interfacing with the pure preimage.Oracle // PreimageOracle implements Oracle using by interfacing with the pure preimage.Oracle
...@@ -119,12 +119,13 @@ func (p *PreimageOracle) GetBlob(ref eth.L1BlockRef, blobHash eth.IndexedBlobHas ...@@ -119,12 +119,13 @@ func (p *PreimageOracle) GetBlob(ref eth.L1BlockRef, blobHash eth.IndexedBlobHas
return &blob return &blob
} }
func (p *PreimageOracle) KZGPointEvaluation(input []byte) bool { func (p *PreimageOracle) Precompile(address common.Address, input []byte) ([]byte, bool) {
p.hint.Hint(KZGPointEvaluationHint(input)) hintBytes := append(address.Bytes(), input...)
key := preimage.KZGPointEvaluationKey(crypto.Keccak256Hash(input[:])) p.hint.Hint(PrecompileHint(hintBytes))
key := preimage.PrecompileKey(crypto.Keccak256Hash(hintBytes))
result := p.oracle.Get(key) result := p.oracle.Get(key)
if len(result) != 1 || result[0] > 1 { if len(result) == 0 { // must contain at least the status code
panic(fmt.Errorf("unexpected preimage oracle KZGPointEvaluation behavior, got result: %x", result)) panic(fmt.Errorf("unexpected precompile oracle behavior, got result: %x", result))
} }
return result[0] == 1 return result[1:], result[0] == 1
} }
...@@ -24,18 +24,18 @@ type StubOracle struct { ...@@ -24,18 +24,18 @@ type StubOracle struct {
// Blobs maps indexed blob hash to l1 block ref to blob // Blobs maps indexed blob hash to l1 block ref to blob
Blobs map[eth.L1BlockRef]map[eth.IndexedBlobHash]*eth.Blob Blobs map[eth.L1BlockRef]map[eth.IndexedBlobHash]*eth.Blob
// PtEvals maps hashed input to whether the KZG point evaluation was successful // PcmpResults maps hashed input to the results of precompile calls
PtEvals map[common.Hash]bool PcmpResults map[common.Hash][]byte
} }
func NewStubOracle(t *testing.T) *StubOracle { func NewStubOracle(t *testing.T) *StubOracle {
return &StubOracle{ return &StubOracle{
t: t, t: t,
Blocks: make(map[common.Hash]eth.BlockInfo), Blocks: make(map[common.Hash]eth.BlockInfo),
Txs: make(map[common.Hash]types.Transactions), Txs: make(map[common.Hash]types.Transactions),
Rcpts: make(map[common.Hash]types.Receipts), Rcpts: make(map[common.Hash]types.Receipts),
Blobs: make(map[eth.L1BlockRef]map[eth.IndexedBlobHash]*eth.Blob), Blobs: make(map[eth.L1BlockRef]map[eth.IndexedBlobHash]*eth.Blob),
PtEvals: make(map[common.Hash]bool), PcmpResults: make(map[common.Hash][]byte),
} }
} }
...@@ -75,10 +75,10 @@ func (o StubOracle) GetBlob(ref eth.L1BlockRef, blobHash eth.IndexedBlobHash) *e ...@@ -75,10 +75,10 @@ func (o StubOracle) GetBlob(ref eth.L1BlockRef, blobHash eth.IndexedBlobHash) *e
return blob return blob
} }
func (o StubOracle) KZGPointEvaluation(input []byte) bool { func (o StubOracle) Precompile(addr common.Address, input []byte) ([]byte, bool) {
result, ok := o.PtEvals[crypto.Keccak256Hash(input)] result, ok := o.PcmpResults[crypto.Keccak256Hash(append(addr.Bytes(), input...))]
if !ok { if !ok {
o.t.Fatalf("unknown kzg point evaluation %x", input) o.t.Fatalf("unknown kzg point evaluation %x", input)
} }
return result return result, true
} }
...@@ -40,7 +40,7 @@ type OracleBackedL2Chain struct { ...@@ -40,7 +40,7 @@ type OracleBackedL2Chain struct {
var _ engineapi.EngineBackend = (*OracleBackedL2Chain)(nil) var _ engineapi.EngineBackend = (*OracleBackedL2Chain)(nil)
func NewOracleBackedL2Chain(logger log.Logger, oracle Oracle, kzgOracle engineapi.KZGPointEvaluationOracle, chainCfg *params.ChainConfig, l2OutputRoot common.Hash) (*OracleBackedL2Chain, error) { func NewOracleBackedL2Chain(logger log.Logger, oracle Oracle, precompileOracle engineapi.PrecompileOracle, chainCfg *params.ChainConfig, l2OutputRoot common.Hash) (*OracleBackedL2Chain, error) {
output := oracle.OutputByRoot(l2OutputRoot) output := oracle.OutputByRoot(l2OutputRoot)
outputV0, ok := output.(*eth.OutputV0) outputV0, ok := output.(*eth.OutputV0)
if !ok { if !ok {
...@@ -67,7 +67,7 @@ func NewOracleBackedL2Chain(logger log.Logger, oracle Oracle, kzgOracle engineap ...@@ -67,7 +67,7 @@ func NewOracleBackedL2Chain(logger log.Logger, oracle Oracle, kzgOracle engineap
blocks: make(map[common.Hash]*types.Block), blocks: make(map[common.Hash]*types.Block),
db: NewOracleBackedDB(oracle), db: NewOracleBackedDB(oracle),
vmCfg: vm.Config{ vmCfg: vm.Config{
OptimismPrecompileOverrides: precompileOverrides(kzgOracle), OptimismPrecompileOverrides: engineapi.CreatePrecompileOverrides(precompileOracle),
}, },
}, nil }, nil
} }
...@@ -232,15 +232,3 @@ func (o *OracleBackedL2Chain) SetFinalized(header *types.Header) { ...@@ -232,15 +232,3 @@ func (o *OracleBackedL2Chain) SetFinalized(header *types.Header) {
func (o *OracleBackedL2Chain) SetSafe(header *types.Header) { func (o *OracleBackedL2Chain) SetSafe(header *types.Header) {
o.safe = header o.safe = header
} }
var kzgPointEvaluationPrecompileAddress = common.BytesToAddress([]byte{0xa})
func precompileOverrides(kzgOracle engineapi.KZGPointEvaluationOracle) vm.PrecompileOverrides {
return func(rules params.Rules, address common.Address) (vm.PrecompiledContract, bool) {
// NOTE: Ignoring chain rules for now. We assume that precompile behavior won't change for the foreseeable future
if address != kzgPointEvaluationPrecompileAddress {
return nil, false
}
return &engineapi.OracleKZGPointEvaluation{Oracle: kzgOracle}, true
}
}
...@@ -28,8 +28,17 @@ var fundedKey, _ = crypto.GenerateKey() ...@@ -28,8 +28,17 @@ var fundedKey, _ = crypto.GenerateKey()
var fundedAddress = crypto.PubkeyToAddress(fundedKey.PublicKey) var fundedAddress = crypto.PubkeyToAddress(fundedKey.PublicKey)
var targetAddress = common.HexToAddress("0x001122334455") var targetAddress = common.HexToAddress("0x001122334455")
// Also a valid input to the kzg point evaluation precompile var (
var inputData = common.FromHex("01e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a") kzgInputData = common.FromHex("01e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a")
ecRecoverInputData = common.FromHex("18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549")
bn256PairingInputData = common.FromHex("1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa")
)
var (
ecRecoverReturnValue = []byte{0x1, 0x2}
bn256PairingReturnValue = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
blobPrecompileReturnValue = common.FromHex("000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001")
)
func TestInitialState(t *testing.T) { func TestInitialState(t *testing.T) {
blocks, chain := setupOracleBackedChain(t, 5) blocks, chain := setupOracleBackedChain(t, 5)
...@@ -189,23 +198,54 @@ func TestGetHeaderByNumber(t *testing.T) { ...@@ -189,23 +198,54 @@ func TestGetHeaderByNumber(t *testing.T) {
}) })
} }
func TestKZGPointEvaluationPrecompile(t *testing.T) { func TestPrecompileOracle(t *testing.T) {
blockCount := 3 tests := []struct {
headBlockNumber := 3 name string
logger := testlog.Logger(t, log.LevelDebug) input []byte
chainCfg, blocks, oracle := setupOracle(t, blockCount, headBlockNumber, true) target common.Address
head := blocks[headBlockNumber].Hash() result []byte
stubOutput := eth.OutputV0{BlockHash: head} }{
kzgOracle := new(l2test.StubKZGOracle) {
kzgOracle.PtEvals = map[common.Hash]bool{ name: "EcRecover",
crypto.Keccak256Hash(inputData): true, input: ecRecoverInputData,
target: common.BytesToAddress([]byte{0x1}),
result: ecRecoverReturnValue,
},
{
name: "Bn256Pairing",
input: bn256PairingInputData,
target: common.BytesToAddress([]byte{0x8}),
result: bn256PairingReturnValue,
},
{
name: "KZGPointEvaluation",
input: kzgInputData,
target: common.BytesToAddress([]byte{0xa}),
result: blobPrecompileReturnValue,
},
} }
chain, err := NewOracleBackedL2Chain(logger, oracle, kzgOracle, chainCfg, common.Hash(eth.OutputRoot(&stubOutput)))
require.NoError(t, err)
newBlock := createKZGBlock(t, chain) for _, test := range tests {
require.NoError(t, chain.InsertBlockWithoutSetHead(newBlock)) test := test
require.Equal(t, 1, kzgOracle.Calls) t.Run(test.name, func(t *testing.T) {
blockCount := 3
headBlockNumber := 3
logger := testlog.Logger(t, log.LevelDebug)
chainCfg, blocks, oracle := setupOracle(t, blockCount, headBlockNumber, true)
head := blocks[headBlockNumber].Hash()
stubOutput := eth.OutputV0{BlockHash: head}
precompileOracle := new(l2test.StubPrecompileOracle)
precompileOracle.Results = map[common.Hash]l2test.PrecompileResult{
crypto.Keccak256Hash(append(test.target.Bytes(), test.input...)): {Result: test.result, Ok: true},
}
chain, err := NewOracleBackedL2Chain(logger, oracle, precompileOracle, chainCfg, common.Hash(eth.OutputRoot(&stubOutput)))
require.NoError(t, err)
newBlock := createBlock(t, chain, WithInput(test.input), WithTargetAddress(test.target))
require.NoError(t, chain.InsertBlockWithoutSetHead(newBlock))
require.Equal(t, 1, precompileOracle.Calls)
})
}
} }
func assertBlockDataAvailable(t *testing.T, chain *OracleBackedL2Chain, block *types.Block, blockNumber uint64) { func assertBlockDataAvailable(t *testing.T, chain *OracleBackedL2Chain, block *types.Block, blockNumber uint64) {
...@@ -225,8 +265,8 @@ func setupOracleBackedChainWithLowerHead(t *testing.T, blockCount int, headBlock ...@@ -225,8 +265,8 @@ func setupOracleBackedChainWithLowerHead(t *testing.T, blockCount int, headBlock
chainCfg, blocks, oracle := setupOracle(t, blockCount, headBlockNumber, false) chainCfg, blocks, oracle := setupOracle(t, blockCount, headBlockNumber, false)
head := blocks[headBlockNumber].Hash() head := blocks[headBlockNumber].Hash()
stubOutput := eth.OutputV0{BlockHash: head} stubOutput := eth.OutputV0{BlockHash: head}
kzgOracle := new(l2test.StubKZGOracle) precompileOracle := new(l2test.StubPrecompileOracle)
chain, err := NewOracleBackedL2Chain(logger, oracle, kzgOracle, chainCfg, common.Hash(eth.OutputRoot(&stubOutput))) chain, err := NewOracleBackedL2Chain(logger, oracle, precompileOracle, chainCfg, common.Hash(eth.OutputRoot(&stubOutput)))
require.NoError(t, err) require.NoError(t, err)
return blocks, chain return blocks, chain
} }
...@@ -276,7 +316,33 @@ func setupOracle(t *testing.T, blockCount int, headBlockNumber int, enableEcoton ...@@ -276,7 +316,33 @@ func setupOracle(t *testing.T, blockCount int, headBlockNumber int, enableEcoton
return chainCfg, blocks, oracle return chainCfg, blocks, oracle
} }
func createBlockWithTargetAddress(t *testing.T, chain *OracleBackedL2Chain, target *common.Address) *types.Block { type blockCreateConfig struct {
input []byte
target *common.Address
}
type blockCreateOption func(*blockCreateConfig)
func WithInput(input []byte) blockCreateOption {
return func(opts *blockCreateConfig) {
opts.input = input
}
}
func WithTargetAddress(target common.Address) blockCreateOption {
return func(opts *blockCreateConfig) {
opts.target = &target
}
}
func createBlock(t *testing.T, chain *OracleBackedL2Chain, opts ...blockCreateOption) *types.Block {
cfg := blockCreateConfig{}
for _, o := range opts {
o(&cfg)
}
if cfg.target == nil {
cfg.target = &targetAddress
}
parent := chain.GetBlockByHash(chain.CurrentHeader().Hash()) parent := chain.GetBlockByHash(chain.CurrentHeader().Hash())
parentDB, err := chain.StateAt(parent.Root()) parentDB, err := chain.StateAt(parent.Root())
require.NoError(t, err) require.NoError(t, err)
...@@ -287,11 +353,11 @@ func createBlockWithTargetAddress(t *testing.T, chain *OracleBackedL2Chain, targ ...@@ -287,11 +353,11 @@ func createBlockWithTargetAddress(t *testing.T, chain *OracleBackedL2Chain, targ
rawTx := &types.DynamicFeeTx{ rawTx := &types.DynamicFeeTx{
ChainID: config.ChainID, ChainID: config.ChainID,
Nonce: nonce, Nonce: nonce,
To: target, To: cfg.target,
GasTipCap: big.NewInt(0), GasTipCap: big.NewInt(0),
GasFeeCap: parent.BaseFee(), GasFeeCap: parent.BaseFee(),
Gas: 210_000, Gas: 2_000_000,
Data: inputData, Data: cfg.input,
Value: big.NewInt(1), Value: big.NewInt(1),
} }
tx := types.MustSignNewTx(fundedKey, types.NewLondonSigner(config.ChainID), rawTx) tx := types.MustSignNewTx(fundedKey, types.NewLondonSigner(config.ChainID), rawTx)
...@@ -300,14 +366,6 @@ func createBlockWithTargetAddress(t *testing.T, chain *OracleBackedL2Chain, targ ...@@ -300,14 +366,6 @@ func createBlockWithTargetAddress(t *testing.T, chain *OracleBackedL2Chain, targ
return blocks[0] return blocks[0]
} }
func createBlock(t *testing.T, chain *OracleBackedL2Chain) *types.Block {
return createBlockWithTargetAddress(t, chain, &targetAddress)
}
func createKZGBlock(t *testing.T, chain *OracleBackedL2Chain) *types.Block {
return createBlockWithTargetAddress(t, chain, &kzgPointEvaluationPrecompileAddress)
}
func TestEngineAPITests(t *testing.T) { func TestEngineAPITests(t *testing.T) {
test.RunEngineAPITests(t, func(t *testing.T) engineapi.EngineBackend { test.RunEngineAPITests(t, func(t *testing.T) engineapi.EngineBackend {
_, chain := setupOracleBackedChain(t, 0) _, chain := setupOracleBackedChain(t, 0)
......
// This file contains code of the upstream go-ethereum kzgPointEvaluation implementation. // This file contains code of the upstream go-ethereum kzgPointEvaluation implementation.
// Modifications have been made, primarily to substitute kzg4844.VerifyProof with a preimage oracle call. // Modifications have been made, primarily to substitute kzgPointEvaluation, ecrecover, and runBn256Pairing
// functions to interact with the preimage oracle.
// //
// Original copyright disclaimer, applicable only to this file: // Original copyright disclaimer, applicable only to this file:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
...@@ -22,29 +23,150 @@ ...@@ -22,29 +23,150 @@
package engineapi package engineapi
import ( import (
"bytes"
"errors" "errors"
"fmt" "fmt"
"math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/crypto/kzg4844"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum-optimism/optimism/op-service/eth" "github.com/ethereum-optimism/optimism/op-service/eth"
) )
// OracleKZGPointEvaluation implements the EIP-4844 point evaluation precompile, var (
// using the preimage-oracle to perform the evaluation. ecrecoverPrecompileAddress = common.BytesToAddress([]byte{0x1})
type OracleKZGPointEvaluation struct { bn256PairingPrecompileAddress = common.BytesToAddress([]byte{0x8})
Oracle KZGPointEvaluationOracle kzgPointEvaluationPrecompileAddress = common.BytesToAddress([]byte{0xa})
)
// PrecompileOracle defines the high-level API used to retrieve the result of a precompile call
// The caller is expected to validate the input to the precompile call
type PrecompileOracle interface {
Precompile(address common.Address, input []byte) ([]byte, bool)
}
func CreatePrecompileOverrides(precompileOracle PrecompileOracle) vm.PrecompileOverrides {
return func(rules params.Rules, address common.Address) (vm.PrecompiledContract, bool) {
// NOTE: Ignoring chain rules for now. We assume that precompile behavior won't change for the foreseeable future
switch address {
case ecrecoverPrecompileAddress:
return &ecrecoverOracle{Oracle: precompileOracle}, true
case bn256PairingPrecompileAddress:
return &bn256PairingOracle{Oracle: precompileOracle, rules: rules}, true
case kzgPointEvaluationPrecompileAddress:
return &kzgPointEvaluationOracle{Oracle: precompileOracle}, true
default:
return nil, false
}
}
}
type ecrecoverOracle struct {
Oracle PrecompileOracle
} }
// KZGPointEvaluationOracle defines the high-level API used to retrieve the result of the KZG point evaluation precompile func (c *ecrecoverOracle) RequiredGas(input []byte) uint64 {
type KZGPointEvaluationOracle interface { return params.EcrecoverGas
KZGPointEvaluation(input []byte) bool }
func (c *ecrecoverOracle) Run(input []byte) ([]byte, error) {
// Modification note: the L1 precompile behavior may change, but not in incompatible ways.
// We want to enforce the subset that represents the EVM behavior activated in L2.
// Below is a copy of the Cancun behavior. L1 might expand on that at a later point.
const ecRecoverInputLength = 128
input = common.RightPadBytes(input, ecRecoverInputLength)
// "input" is (hash, v, r, s), each 32 bytes
// but for ecrecover we want (r, s, v)
r := new(big.Int).SetBytes(input[64:96])
s := new(big.Int).SetBytes(input[96:128])
v := input[63] - 27
// tighter sig s values input homestead only apply to tx sigs
if !allZero(input[32:63]) || !crypto.ValidateSignatureValues(v, r, s, false) {
return nil, nil
}
// We must make sure not to modify the 'input', so placing the 'v' along with
// the signature needs to be done on a new allocation
sig := make([]byte, 65)
copy(sig, input[64:128])
sig[64] = v
// v needs to be at the end for libsecp256k1
// Modification note: below replaces the crypto.Ecrecover call
result, ok := c.Oracle.Precompile(ecrecoverPrecompileAddress, input)
if !ok {
return nil, errors.New("invalid ecrecover input")
}
return result, nil
}
func allZero(b []byte) bool {
for _, byte := range b {
if byte != 0 {
return false
}
}
return true
}
type bn256PairingOracle struct {
rules params.Rules
Oracle PrecompileOracle
}
func (b *bn256PairingOracle) RequiredGas(input []byte) uint64 {
// Required gas changed in Istanbul. Note that IsIstanbul is true for Istanbul and all forks after it
// TODO(client-pod#628): Investigate delegating this to the original precompile implementation to avoid reimplementing.
if b.rules.IsIstanbul {
return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul
} else {
return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium
}
}
var (
// true32Byte is returned if the bn256 pairing check succeeds.
true32Byte = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
// false32Byte is returned if the bn256 pairing check fails.
false32Byte = make([]byte, 32)
// errBadPairingInput is returned if the bn256 pairing input is invalid.
errBadPairingInput = errors.New("bad elliptic curve pairing size")
)
func (b *bn256PairingOracle) Run(input []byte) ([]byte, error) {
// Handle some corner cases cheaply
if len(input)%192 > 0 {
return nil, errBadPairingInput
}
// Modification note: below replaces point verification and pairing checks
// Assumes both L2 and the L1 oracle have an identical range of valid points
result, ok := b.Oracle.Precompile(bn256PairingPrecompileAddress, input)
if !ok {
return nil, errors.New("invalid bn256Pairing check")
}
if !bytes.Equal(result, true32Byte) && !bytes.Equal(result, false32Byte) {
panic("unexpected result from bn256Pairing check")
}
return result, nil
}
// kzgPointEvaluationOracle implements the EIP-4844 point evaluation precompile,
// using the preimage-oracle to perform the evaluation.
type kzgPointEvaluationOracle struct {
Oracle PrecompileOracle
} }
// RequiredGas estimates the gas required for running the point evaluation precompile. // RequiredGas estimates the gas required for running the point evaluation precompile.
func (b *OracleKZGPointEvaluation) RequiredGas(input []byte) uint64 { func (b *kzgPointEvaluationOracle) RequiredGas(_ []byte) uint64 {
return params.BlobTxPointEvaluationPrecompileGas return params.BlobTxPointEvaluationPrecompileGas
} }
...@@ -60,7 +182,7 @@ var ( ...@@ -60,7 +182,7 @@ var (
) )
// Run executes the point evaluation precompile. // Run executes the point evaluation precompile.
func (b *OracleKZGPointEvaluation) Run(input []byte) ([]byte, error) { func (b *kzgPointEvaluationOracle) Run(input []byte) ([]byte, error) {
// Modification note: the L1 precompile behavior may change, but not in incompatible ways. // Modification note: the L1 precompile behavior may change, but not in incompatible ways.
// We want to enforce the subset that represents the EVM behavior activated in L2. // We want to enforce the subset that represents the EVM behavior activated in L2.
// Below is a copy of the Cancun behavior. L1 might expand on that at a later point. // Below is a copy of the Cancun behavior. L1 might expand on that at a later point.
...@@ -93,9 +215,12 @@ func (b *OracleKZGPointEvaluation) Run(input []byte) ([]byte, error) { ...@@ -93,9 +215,12 @@ func (b *OracleKZGPointEvaluation) Run(input []byte) ([]byte, error) {
copy(proof[:], input[144:]) copy(proof[:], input[144:])
// Modification note: below replaces the kzg4844.VerifyProof call // Modification note: below replaces the kzg4844.VerifyProof call
ok := b.Oracle.KZGPointEvaluation(input) result, ok := b.Oracle.Precompile(kzgPointEvaluationPrecompileAddress, input)
if !ok { if !ok {
return nil, fmt.Errorf("%w: invalid KZG point evaluation", errBlobVerifyKZGProof) return nil, fmt.Errorf("%w: invalid KZG point evaluation", errBlobVerifyKZGProof)
} }
return common.FromHex(blobPrecompileReturnValue), nil if !bytes.Equal(result, common.FromHex(blobPrecompileReturnValue)) {
panic("unexpected result from KZG point evaluation check")
}
return result, nil
} }
...@@ -124,17 +124,22 @@ func (o *StubStateOracle) CodeByHash(hash common.Hash) []byte { ...@@ -124,17 +124,22 @@ func (o *StubStateOracle) CodeByHash(hash common.Hash) []byte {
return data return data
} }
type StubKZGOracle struct { type StubPrecompileOracle struct {
t *testing.T t *testing.T
PtEvals map[common.Hash]bool Results map[common.Hash]PrecompileResult
Calls int Calls int
} }
func (o *StubKZGOracle) KZGPointEvaluation(input []byte) bool { type PrecompileResult struct {
result, ok := o.PtEvals[crypto.Keccak256Hash(input)] Result []byte
Ok bool
}
func (o *StubPrecompileOracle) Precompile(address common.Address, input []byte) ([]byte, bool) {
result, ok := o.Results[crypto.Keccak256Hash(append(address.Bytes(), input...))]
if !ok { if !ok {
o.t.Fatalf("no value for point evaluation %v", input) o.t.Fatalf("no value for point evaluation %v", input)
} }
o.Calls++ o.Calls++
return result return result.Result, result.Ok
} }
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
"slices"
"strings" "strings"
preimage "github.com/ethereum-optimism/optimism/op-preimage" preimage "github.com/ethereum-optimism/optimism/op-preimage"
...@@ -23,10 +24,16 @@ import ( ...@@ -23,10 +24,16 @@ import (
) )
var ( var (
kzgPointEvaluationSuccess = [1]byte{1} precompileSuccess = [1]byte{1}
kzgPointEvaluationFailure = [1]byte{0} precompileFailure = [1]byte{0}
) )
var acceleratedPrecompiles = []common.Address{
common.BytesToAddress([]byte{0x1}), // ecrecover
common.BytesToAddress([]byte{0x8}), // bn256Pairing
common.BytesToAddress([]byte{0x0a}), // KZG Point Evaluation
}
type L1Source interface { type L1Source interface {
InfoByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, error) InfoByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, error)
InfoAndTxsByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, error) InfoAndTxsByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, error)
...@@ -38,10 +45,6 @@ type L1BlobSource interface { ...@@ -38,10 +45,6 @@ type L1BlobSource interface {
GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error)
} }
type L1PrecompileSource interface {
KZGPointEvaluation(input []byte) ([]byte, error)
}
type L2Source interface { type L2Source interface {
InfoAndTxsByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, error) InfoAndTxsByHash(ctx context.Context, blockHash common.Hash) (eth.BlockInfo, types.Transactions, error)
NodeByHash(ctx context.Context, hash common.Hash) ([]byte, error) NodeByHash(ctx context.Context, hash common.Hash) ([]byte, error)
...@@ -175,22 +178,33 @@ func (p *Prefetcher) prefetch(ctx context.Context, hint string) error { ...@@ -175,22 +178,33 @@ func (p *Prefetcher) prefetch(ctx context.Context, hint string) error {
} }
} }
return nil return nil
case l1.HintL1KZGPointEvaluation: case l1.HintL1Precompile:
precompile := vm.PrecompiledContractsCancun[common.BytesToAddress([]byte{0x0a})] if len(hintBytes) < 20 {
// KZG Point Evaluation precompile also verifies hintBytes length return fmt.Errorf("invalid precompile hint: %x", hint)
_, err := precompile.Run(hintBytes) }
var result [1]byte precompileAddress := common.BytesToAddress(hintBytes[:20])
// For extra safety, avoid accelerating unexpected precompiles
if !slices.Contains(acceleratedPrecompiles, precompileAddress) {
return fmt.Errorf("unsupported precompile address: %s", precompileAddress)
}
// NOTE: We use the precompiled contracts from Cancun because it's the only set that contains the addresses of all accelerated precompiles
// We assume the precompile Run function behavior does not change across EVM upgrades.
// As such, we must not rely on upgrade-specific behavior such as precompile.RequiredGas.
precompile := getPrecompiledContract(precompileAddress)
// KZG Point Evaluation precompile also verifies its input
result, err := precompile.Run(hintBytes[20:])
if err == nil { if err == nil {
result = kzgPointEvaluationSuccess result = append(precompileSuccess[:], result...)
} else { } else {
result = kzgPointEvaluationFailure result = append(precompileFailure[:], result...)
} }
inputHash := crypto.Keccak256Hash(hintBytes) inputHash := crypto.Keccak256Hash(hintBytes)
// Put the input preimage so it can be loaded later // Put the input preimage so it can be loaded later
if err := p.kvStore.Put(preimage.Keccak256Key(inputHash).PreimageKey(), hintBytes); err != nil { if err := p.kvStore.Put(preimage.Keccak256Key(inputHash).PreimageKey(), hintBytes); err != nil {
return err return err
} }
return p.kvStore.Put(preimage.KZGPointEvaluationKey(inputHash).PreimageKey(), result[:]) return p.kvStore.Put(preimage.PrecompileKey(inputHash).PreimageKey(), result)
case l2.HintL2BlockHeader, l2.HintL2Transactions: case l2.HintL2BlockHeader, l2.HintL2Transactions:
if len(hintBytes) != 32 { if len(hintBytes) != 32 {
return fmt.Errorf("invalid L2 header/tx hint: %x", hint) return fmt.Errorf("invalid L2 header/tx hint: %x", hint)
...@@ -283,3 +297,7 @@ func parseHint(hint string) (string, []byte, error) { ...@@ -283,3 +297,7 @@ func parseHint(hint string) (string, []byte, error) {
} }
return hintType, hintBytes, nil return hintType, hintBytes, nil
} }
func getPrecompiledContract(address common.Address) vm.PrecompiledContract {
return vm.PrecompiledContractsCancun[address]
}
...@@ -231,45 +231,92 @@ func TestFetchL1Blob(t *testing.T) { ...@@ -231,45 +231,92 @@ func TestFetchL1Blob(t *testing.T) {
}) })
} }
func TestFetchKZGPointEvaluation(t *testing.T) { func TestFetchPrecompileResult(t *testing.T) {
runTest := func(name string, input []byte, expected bool) { ecRecoverInput := common.FromHex("18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c000000000000000000000000000000000000000000000000000000000000001c73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75feeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549")
t.Run(name, func(t *testing.T) { kzgPointEvalInput := common.FromHex("01e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a")
failure := []byte{0}
success := []byte{1}
tests := []struct {
name string
addr common.Address
input []byte
result []byte
}{
{
name: "EcRecover-Valid",
addr: common.BytesToAddress([]byte{0x1}),
input: ecRecoverInput,
result: append(success, common.FromHex("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b")...),
},
{
name: "Bn256Pairing-Valid",
addr: common.BytesToAddress([]byte{0x8}),
input: []byte{}, // empty is valid
result: append(success, common.FromHex("0000000000000000000000000000000000000000000000000000000000000001")...),
},
{
name: "Bn256Pairing-Invalid",
addr: common.BytesToAddress([]byte{0x8}),
input: []byte{0x1},
result: failure,
},
{
name: "KzgPointEvaluation-Valid",
addr: common.BytesToAddress([]byte{0xa}),
input: kzgPointEvalInput,
result: append(success, common.FromHex("000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001")...),
},
{
name: "KzgPointEvaluation-Invalid",
addr: common.BytesToAddress([]byte{0xa}),
input: []byte{0x0},
result: failure,
},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
prefetcher, _, _, _, _ := createPrefetcher(t) prefetcher, _, _, _, _ := createPrefetcher(t)
oracle := l1.NewPreimageOracle(asOracleFn(t, prefetcher), asHinter(t, prefetcher)) oracle := l1.NewPreimageOracle(asOracleFn(t, prefetcher), asHinter(t, prefetcher))
result := oracle.KZGPointEvaluation(input) result, ok := oracle.Precompile(test.addr, test.input)
require.Equal(t, expected, result) require.Equal(t, test.result[0] == 1, ok)
require.EqualValues(t, test.result[1:], result)
val, err := prefetcher.kvStore.Get(preimage.Keccak256Key(crypto.Keccak256Hash(input)).PreimageKey()) key := crypto.Keccak256Hash(append(test.addr.Bytes(), test.input...))
val, err := prefetcher.kvStore.Get(preimage.Keccak256Key(key).PreimageKey())
require.NoError(t, err) require.NoError(t, err)
require.EqualValues(t, input, val) require.NotEmpty(t, val)
key := preimage.KZGPointEvaluationKey(crypto.Keccak256Hash(input)).PreimageKey() val, err = prefetcher.kvStore.Get(preimage.PrecompileKey(key).PreimageKey())
val, err = prefetcher.kvStore.Get(key)
require.NoError(t, err) require.NoError(t, err)
if expected { require.EqualValues(t, test.result, val)
require.EqualValues(t, kzgPointEvaluationSuccess[:], val)
} else {
require.EqualValues(t, kzgPointEvaluationFailure[:], val)
}
}) })
} }
validInput := common.FromHex("01e798154708fe7789429634053cbf9f99b619f9f084048927333fce637f549b564c0a11a0f704f4fc3e8acfe0f8245f0ad1347b378fbf96e206da11a5d3630624d25032e67a7e6a4910df5834b8fe70e6bcfeeac0352434196bdf4b2485d5a18f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7873033e038326e87ed3e1276fd140253fa08e9fc25fb2d9a98527fc22a2c9612fbeafdad446cbc7bcdbdcd780af2c16a")
runTest("Valid input", validInput, true)
runTest("Invalid input", []byte{0x00}, false)
t.Run("Already Known", func(t *testing.T) { t.Run("Already Known", func(t *testing.T) {
input := []byte("test input") input := []byte("test input")
addr := common.BytesToAddress([]byte{0x1})
result := []byte{0x1}
prefetcher, _, _, _, kv := createPrefetcher(t) prefetcher, _, _, _, kv := createPrefetcher(t)
err := kv.Put(preimage.KZGPointEvaluationKey(crypto.Keccak256Hash(input)).PreimageKey(), kzgPointEvaluationSuccess[:]) err := kv.Put(preimage.PrecompileKey(crypto.Keccak256Hash(append(addr.Bytes(), input...))).PreimageKey(), append([]byte{1}, result...))
require.NoError(t, err) require.NoError(t, err)
oracle := l1.NewPreimageOracle(asOracleFn(t, prefetcher), asHinter(t, prefetcher)) oracle := l1.NewPreimageOracle(asOracleFn(t, prefetcher), asHinter(t, prefetcher))
result := oracle.KZGPointEvaluation(input) actualResult, status := oracle.Precompile(addr, input)
require.True(t, result) require.EqualValues(t, actualResult, result)
require.True(t, status)
}) })
} }
func TestRestrictedPrecompileContracts(t *testing.T) {
for _, addr := range acceleratedPrecompiles {
require.NotNil(t, getPrecompiledContract(addr))
}
}
func TestFetchL2Block(t *testing.T) { func TestFetchL2Block(t *testing.T) {
rng := rand.New(rand.NewSource(123)) rng := rand.New(rand.NewSource(123))
block, rcpts := testutils.RandomBlock(rng, 10) block, rcpts := testutils.RandomBlock(rng, 10)
......
...@@ -314,24 +314,6 @@ ...@@ -314,24 +314,6 @@
"stateMutability": "nonpayable", "stateMutability": "nonpayable",
"type": "function" "type": "function"
}, },
{
"inputs": [
{
"internalType": "uint256",
"name": "_partOffset",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "_input",
"type": "bytes"
}
],
"name": "loadKZGPointEvaluationPreimagePart",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{ {
"inputs": [ "inputs": [
{ {
...@@ -389,6 +371,29 @@ ...@@ -389,6 +371,29 @@
"stateMutability": "nonpayable", "stateMutability": "nonpayable",
"type": "function" "type": "function"
}, },
{
"inputs": [
{
"internalType": "uint256",
"name": "_partOffset",
"type": "uint256"
},
{
"internalType": "address",
"name": "_precompile",
"type": "address"
},
{
"internalType": "bytes",
"name": "_input",
"type": "bytes"
}
],
"name": "loadPrecompilePreimagePart",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{ {
"inputs": [ "inputs": [
{ {
......
...@@ -334,51 +334,63 @@ contract PreimageOracle is IPreimageOracle { ...@@ -334,51 +334,63 @@ contract PreimageOracle is IPreimageOracle {
} }
/// @inheritdoc IPreimageOracle /// @inheritdoc IPreimageOracle
function loadKZGPointEvaluationPreimagePart(uint256 _partOffset, bytes calldata _input) external { function loadPrecompilePreimagePart(uint256 _partOffset, address _precompile, bytes calldata _input) external {
// Prior to Cancun activation, the blob preimage precompile is not available. // Prior to Cancun activation, the blob preimage precompile is not available.
if (block.timestamp < CANCUN_ACTIVATION) revert CancunNotActive(); if (block.timestamp < CANCUN_ACTIVATION) revert CancunNotActive();
bytes32 res; bytes32 res;
bytes32 key; bytes32 key;
bytes32 part; bytes32 part;
uint256 size;
assembly { assembly {
// we leave solidity slots 0x40 and 0x60 untouched, and everything after as scratch-memory. // we leave solidity slots 0x40 and 0x60 untouched, and everything after as scratch-memory.
let ptr := 0x80 let ptr := 0x80
// copy input into memory // copy precompile address and input into memory
calldatacopy(ptr, _input.offset, _input.length) // len(sig) + len(_partOffset) + address-offset-in-slot
calldatacopy(ptr, 48, 20)
calldatacopy(add(20, ptr), _input.offset, _input.length)
// compute the hash // compute the hash
let h := keccak256(ptr, _input.length) let h := keccak256(ptr, add(20, _input.length))
// mask out prefix byte, replace with type 6 byte // mask out prefix byte, replace with type 6 byte
key := or(and(h, not(shl(248, 0xFF))), shl(248, 0x06)) key := or(and(h, not(shl(248, 0xFF))), shl(248, 0x06))
// Verify the KZG proof by calling the point evaluation precompile. // Call the precompile to get the result.
// Capture the verification result
res := res :=
staticcall( staticcall(
gas(), // forward all gas gas(), // forward all gas
0x0A, // point evaluation precompile address _precompile,
ptr, // input ptr add(20, ptr), // input ptr
_input.length, // we may want to load differently sized point-evaluation calls in the future _input.length,
0x00, // output ptr 0x0, // Unused as we don't copy anything
0x00 // output size 0x00 // don't copy anything
) )
// "res" will be 0 on error, and 1 on success, of the KZG Point-evaluation precompile call
// We do have to shift it to the left-most byte of the bytes32 however, since we only read that byte.
res := shl(248, res)
// Reuse the `ptr` to store the preimage part including size prefix. size := add(1, returndatasize())
// put size as big-endian uint64 at the start of pre-image // revert if part offset >= size+8 (i.e. parts must be within bounds)
mstore(ptr, shl(192, 1)) if iszero(lt(_partOffset, add(size, 8))) {
// Store "PartOffsetOOB()"
mstore(0, 0xfe254987)
// Revert with "PartOffsetOOB()"
revert(0x1c, 4)
}
// Reuse the `ptr` to store the preimage part: <sizePrefix ++ precompileStatus ++ returrnData>
// put size as big-endian uint64 at start of pre-image
mstore(ptr, shl(192, size))
ptr := add(ptr, 0x08) ptr := add(ptr, 0x08)
mstore(ptr, res)
// write precompile result status to the first byte of `ptr`
mstore8(ptr, res)
// write precompile return data to the rest of `ptr`
returndatacopy(add(ptr, 0x01), 0x0, returndatasize())
// compute part given ofset // compute part given ofset
part := mload(add(sub(ptr, 0x08), _partOffset)) part := mload(add(sub(ptr, 0x08), _partOffset))
} }
preimagePartOk[key][_partOffset] = true; preimagePartOk[key][_partOffset] = true;
preimageParts[key][_partOffset] = part; preimageParts[key][_partOffset] = part;
// size is always 1 preimageLengths[key] = size;
preimageLengths[key] = 1;
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
......
...@@ -70,7 +70,11 @@ interface IPreimageOracle { ...@@ -70,7 +70,11 @@ interface IPreimageOracle {
) )
external; external;
/// @notice Prepares a point evaluation precompile result to be read by the keccak256 of its input. /// @notice Prepares a precompile result to be read by a precompile key for the specified offset.
/// @param _input The point evaluation precompile input. /// The precompile result data is a concatenation of the precompile call status byte and its return data.
function loadKZGPointEvaluationPreimagePart(uint256 _partOffset, bytes calldata _input) external; /// The preimage key is `6 ++ keccak256(precompile ++ input)[1:]`.
/// @param _partOffset The offset of the precompile result being loaded.
/// @param _precompile The precompile address
/// @param _input The input to the precompile call.
function loadPrecompilePreimagePart(uint256 _partOffset, address _precompile, bytes calldata _input) external;
} }
...@@ -171,6 +171,95 @@ contract PreimageOracle_Test is Test { ...@@ -171,6 +171,95 @@ contract PreimageOracle_Test is Test {
vm.expectRevert("pre-image must exist"); vm.expectRevert("pre-image must exist");
oracle.readPreimage(key, offset); oracle.readPreimage(key, offset);
} }
/// @notice Tests that a precompile pre-image result is correctly set.
function test_loadPrecompilePreimagePart_succeeds() public {
bytes memory input = hex"deadbeef";
uint256 offset = 0;
address precompile = address(bytes20(uint160(0x02))); // sha256
bytes32 key = precompilePreimageKey(precompile, input);
oracle.loadPrecompilePreimagePart(offset, precompile, input);
bytes32 part = oracle.preimageParts(key, offset);
// size prefix - 1-byte result + 32-byte sha return data
assertEq(hex"0000000000000021", bytes8(part));
// precompile result
assertEq(bytes1(0x01), bytes1(part << 64));
// precompile call return data
assertEq(bytes23(sha256(input)), bytes23(part << 72));
// Validate the local data length
uint256 length = oracle.preimageLengths(key);
assertEq(length, 1 + 32);
// Validate that the first local data part is set
bool ok = oracle.preimagePartOk(key, offset);
assertTrue(ok);
}
/// @notice Tests that a precompile pre-image result is correctly set at its return data offset.
function test_loadPrecompilePreimagePart_atReturnOffset_succeeds() public {
bytes memory input = hex"deadbeef";
uint256 offset = 9;
address precompile = address(bytes20(uint160(0x02))); // sha256
bytes32 key = precompilePreimageKey(precompile, input);
oracle.loadPrecompilePreimagePart(offset, precompile, input);
bytes32 part = oracle.preimageParts(key, offset);
// 32-byte sha return data
assertEq(sha256(input), part);
// Validate the local data length
uint256 length = oracle.preimageLengths(key);
assertEq(length, 1 + 32);
// Validate that the first local data part is set
bool ok = oracle.preimagePartOk(key, offset);
assertTrue(ok);
}
/// @notice Tests that a failed precompile call has a zero status byte in preimage
function test_loadPrecompilePreimagePart_failedCall_succeeds() public {
bytes memory input = new bytes(193); // invalid input to induce a failed precompile call
uint256 offset = 0;
address precompile = address(bytes20(uint160(0x08))); // bn256Pairing
bytes32 key = precompilePreimageKey(precompile, input);
oracle.loadPrecompilePreimagePart(offset, precompile, input);
bytes32 part = oracle.preimageParts(key, offset);
// size prefix - 1-byte result + 0-byte sha return data
assertEq(hex"0000000000000001", bytes8(part));
// precompile result
assertEq(bytes1(0x00), bytes1(part << 64));
// precompile call return data
assertEq(bytes23(0), bytes23(part << 72));
// Validate the local data length
uint256 length = oracle.preimageLengths(key);
assertEq(length, 1);
// Validate that the first local data part is set
bool ok = oracle.preimagePartOk(key, offset);
assertTrue(ok);
}
/// @notice Tests that adding a global precompile result at the part boundary reverts.
function test_loadPrecompilePreimagePart_partBoundary_reverts() public {
bytes memory input = hex"deadbeef";
uint256 offset = 41; // 8-byte prefix + 1-byte result + 32-byte sha return data
address precompile = address(bytes20(uint160(0x02))); // sha256
vm.expectRevert(PartOffsetOOB.selector);
oracle.loadPrecompilePreimagePart(offset, precompile, input);
}
/// @notice Tests that a global precompile result cannot be set with an out-of-bounds offset.
function test_loadPrecompilePreimagePart_outOfBoundsOffset_reverts() public {
bytes memory input = hex"deadbeef";
uint256 offset = 42;
address precompile = address(bytes20(uint160(0x02))); // sha256
vm.expectRevert(PartOffsetOOB.selector);
oracle.loadPrecompilePreimagePart(offset, precompile, input);
}
} }
contract PreimageOracle_LargePreimageProposals_Test is Test { contract PreimageOracle_LargePreimageProposals_Test is Test {
...@@ -1268,3 +1357,14 @@ function _setStatusByte(bytes32 _hash, uint8 _status) pure returns (bytes32 out_ ...@@ -1268,3 +1357,14 @@ function _setStatusByte(bytes32 _hash, uint8 _status) pure returns (bytes32 out_
out_ := or(and(not(shl(248, 0xFF)), _hash), shl(248, _status)) out_ := or(and(not(shl(248, 0xFF)), _hash), shl(248, _status))
} }
} }
/// @notice Computes a precompile key for a given precompile address and input.
function precompilePreimageKey(address _precompile, bytes memory _input) pure returns (bytes32 key_) {
bytes memory p = abi.encodePacked(_precompile, _input);
uint256 sz = 20 + _input.length;
assembly {
let h := keccak256(add(0x20, p), sz)
// Mask out prefix byte, replace with type 6 byte
key_ := or(and(h, not(shl(248, 0xFF))), shl(248, 6))
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment