diff --git a/core/vm/contracts.go b/core/vm/contracts.go index acdf9e7cf..c691bfbd5 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -160,6 +160,25 @@ var PrecompiledContractsLuban = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{103}): &cometBFTLightBlockValidate{}, } +// PrecompiledContractsPlato contains the default set of pre-compiled Ethereum +// contracts used in the Plato release. +var PrecompiledContractsPlato = map[common.Address]PrecompiledContract{ + common.BytesToAddress([]byte{1}): &ecrecover{}, + common.BytesToAddress([]byte{2}): &sha256hash{}, + common.BytesToAddress([]byte{3}): &ripemd160hash{}, + common.BytesToAddress([]byte{4}): &dataCopy{}, + common.BytesToAddress([]byte{5}): &bigModExp{}, + common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, + common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, + common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, + common.BytesToAddress([]byte{9}): &blake2F{}, + + common.BytesToAddress([]byte{100}): &tmHeaderValidate{}, + common.BytesToAddress([]byte{101}): &iavlMerkleProofValidatePlato{}, + common.BytesToAddress([]byte{102}): &blsSignatureVerify{}, + common.BytesToAddress([]byte{103}): &cometBFTLightBlockValidate{}, +} + // PrecompiledContractsBLS contains the set of pre-compiled Ethereum // contracts specified in EIP-2537. These are exported for testing purposes. var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{ @@ -175,6 +194,7 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{ } var ( + PrecompiledAddressesPlato []common.Address PrecompiledAddressesLuban []common.Address PrecompiledAddressesPlanck []common.Address PrecompiledAddressesMoran []common.Address @@ -210,11 +230,16 @@ func init() { for k := range PrecompiledContractsLuban { PrecompiledAddressesLuban = append(PrecompiledAddressesLuban, k) } + for k := range PrecompiledContractsPlato { + PrecompiledAddressesPlato = append(PrecompiledAddressesPlato, k) + } } // ActivePrecompiles returns the precompiles enabled with the current configuration. func ActivePrecompiles(rules params.Rules) []common.Address { switch { + case rules.IsPlato: + return PrecompiledAddressesPlato case rules.IsLuban: return PrecompiledAddressesLuban case rules.IsPlanck: diff --git a/core/vm/contracts_lightclient.go b/core/vm/contracts_lightclient.go index 693dffbd3..5781569be 100644 --- a/core/vm/contracts_lightclient.go +++ b/core/vm/contracts_lightclient.go @@ -183,6 +183,27 @@ func (c *iavlMerkleProofValidatePlanck) Run(input []byte) (result []byte, err er return c.basicIavlMerkleProofValidate.Run(input) } +type iavlMerkleProofValidatePlato struct { + basicIavlMerkleProofValidate +} + +func (c *iavlMerkleProofValidatePlato) RequiredGas(_ []byte) uint64 { + return params.IAVLMerkleProofValidateGas +} + +func (c *iavlMerkleProofValidatePlato) Run(input []byte) (result []byte, err error) { + c.basicIavlMerkleProofValidate.proofRuntime = v1.Ics23ProofRuntime() + c.basicIavlMerkleProofValidate.verifiers = []merkle.ProofOpVerifier{ + forbiddenAbsenceOpVerifier, + singleValueOpVerifier, + multiStoreOpVerifier, + forbiddenSimpleValueOpVerifier, + } + c.basicIavlMerkleProofValidate.keyVerifier = keyVerifier + c.basicIavlMerkleProofValidate.opsVerifier = proofOpsVerifier + return c.basicIavlMerkleProofValidate.Run(input) +} + func successfulMerkleResult() []byte { result := make([]byte, merkleProofValidateResultLength) binary.BigEndian.PutUint64(result[merkleProofValidateResultLength-uint64TypeLength:], 0x01) diff --git a/core/vm/contracts_lightclient_test.go b/core/vm/contracts_lightclient_test.go index 59cec725e..b5c7749ef 100644 --- a/core/vm/contracts_lightclient_test.go +++ b/core/vm/contracts_lightclient_test.go @@ -153,6 +153,43 @@ func TestIcs23Proof(t *testing.T) { require.Equal(t, expectedResult, success) } +func TestIcs23ProofPlato(t *testing.T) { + appHash, err := hex.DecodeString("ae6d1123fc362b3297bfb19c9f9fabbcbd1e2555b923dead261905b8a2ff6db6") + require.NoError(t, err) + key, err := hex.DecodeString("77696e64") + require.NoError(t, err) + value, err := hex.DecodeString("626c6f7773") + require.NoError(t, err) + proofBytes, err := hex.DecodeString("0a300a0a69637332333a6961766c120477696e641a1c0a1a0a0477696e641205626c6f77731a0b0801180120012a030002040a9d010a0c69637332333a73696d706c6512036962631a87010a84010a036962631220141acb8632cfb808f293f2649cb9aabaca74fc18640900ffd0d48e2994b2a1521a090801180120012a0100222708011201011a205f0ba08283de309300409486e978a3ea59d82bccc838b07c7d39bd87c16a5034222708011201011a20455b81ef5591150bd24d3e57a769f65518b16de93487f0fab02271b3d69e2852") + require.NoError(t, err) + + merkleProofInput := make([]byte, 32+32+len(key)+32+len(value)+32+len(proofBytes)) + copy(merkleProofInput[:32], "ibc") + binary.BigEndian.PutUint64(merkleProofInput[32+24:32+32], uint64(len(key))) + copy(merkleProofInput[32+32:32+32+len(key)], key) + + binary.BigEndian.PutUint64(merkleProofInput[32+32+len(key)+24:32+32+len(key)+32], uint64(len(value))) + copy(merkleProofInput[32+32+len(key)+32:32+32+len(key)+32+len(value)], value) + + copy(merkleProofInput[32+32+len(key)+32+len(value):32+32+len(key)+32+len(value)+32], appHash) + copy(merkleProofInput[32+32+len(key)+32+len(value)+32:], proofBytes) + + totalLengthPrefix := make([]byte, 32) + binary.BigEndian.PutUint64(totalLengthPrefix[0:8], 0) + binary.BigEndian.PutUint64(totalLengthPrefix[8:16], 0) + binary.BigEndian.PutUint64(totalLengthPrefix[16:24], 0) + binary.BigEndian.PutUint64(totalLengthPrefix[24:], uint64(len(merkleProofInput))) + + input := append(totalLengthPrefix, merkleProofInput...) + + validator := iavlMerkleProofValidatePlato{} + success, err := validator.Run(input) + require.NoError(t, err) + expectedResult := make([]byte, 32) + binary.BigEndian.PutUint64(expectedResult[24:], 0x01) + require.Equal(t, expectedResult, success) +} + func TestMerkleProofValidateMoran(t *testing.T) { // Bytest1 is the inputs of exploit tx 0x05356fd06ce56a9ec5b4eaf9c075abd740cae4c21eab1676440ab5cd2fe5c57a bytest1, _ := hex.DecodeString("00000000000000000000000000000000000000000000000000000000000005086962630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00000100380200000000010dd9ac0000000000000000000000000000000000000000000000000000000000000093000000000000000000000000000000000000000000000000000000000000000000f870a0424e4200000000000000000000000000000000000000000000000000000000009400000000000000000000000000000000000000008ad3c21bcecceda100000094489a8756c18c0b8b24ec2a2b9ff3d4d447f79bec94489a8756c18c0b8b24ec2a2b9ff3d4d447f79bec846553f10072cda827a83531ca0fd7ac917a6b65649719aab0836722caafe0603147a523180a8d020a066961766c3a76120e00000100380200000000010dd9ac1af201f0010aed010a2b0802100318b091c73422200c10f902d266c238a4ca9e26fa9bc36483cd3ebee4e263012f5e7f40c22ee4d20a4d0801100218b091c7342220e4fd47bffd1c06e67edad92b2bf9ca63631978676288a2aa99f95c459436ef632a20121a1f9c4eca726c725796c5375fc4158986ced08e498dc8268ef94d8ed1891612001a370a0e0000010038020000000000000002122011056c6919f02d966991c10721684a8d1542e44003f9ffb47032c18995d4ac7f18b091c7341a340a0e00000100380200000000010dd9ac12202c3a561458f8527b002b5ec3cab2d308662798d6245d4588a4e6a80ebdfe30ac18010ad4050a0a6d756c746973746f726512036962631ac005be050abb050a110a066f7261636c6512070a0508b891c7340a0f0a046d61696e12070a0508b891c7340a350a08736c617368696e6712290a2708b891c7341220c8ccf341e6e695e7e1cb0ce4bf347eea0cc16947d8b4e934ec400b57c59d6f860a380a0b61746f6d69635f7377617012290a2708b891c734122042d4ecc9468f71a70288a95d46564bfcaf2c9f811051dcc5593dbef152976b010a110a0662726964676512070a0508b891c7340a300a0364657812290a2708b891c73412201773be443c27f61075cecdc050ce22eb4990c54679089e90afdc4e0e88182a230a2f0a02736312290a2708b891c7341220df7a0484b7244f76861b1642cfb7a61d923794bd2e076c8dbd05fc4ee29f3a670a330a06746f6b656e7312290a2708b891c734122064958c2f76fec1fa5d1828296e51264c259fa264f499724795a740f48fc4731b0a320a057374616b6512290a2708b891c734122015d2c302143bdf029d58fe381cc3b54cedf77ecb8834dfc5dc3e1555d68f19ab0a330a06706172616d7312290a2708b891c734122050abddcb7c115123a5a4247613ab39e6ba935a3d4f4b9123c4fedfa0895c040a0a300a0361636312290a2708b891c734122079fb5aecc4a9b87e56231103affa5e515a1bdf3d0366490a73e087980b7f1f260a0e0a0376616c12070a0508b891c7340a300a0369626312290a2708b891c7341220e09159530585455058cf1785f411ea44230f39334e6e0f6a3c54dbf069df2b620a300a03676f7612290a2708b891c7341220db85ddd37470983b14186e975a175dfb0bf301b43de685ced0aef18d28b4e0420a320a05706169727312290a2708b891c7341220a78b556bc9e73d86b4c63ceaf146db71b12ac80e4c10dd0ce6eb09c99b0c7cfe0a360a0974696d655f6c6f636b12290a2708b891c73412204775dbe01d41cab018c21ba5c2af94720e4d7119baf693670e70a40ba2a52143") diff --git a/core/vm/evm.go b/core/vm/evm.go index 440c47fab..26842900b 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -52,6 +52,8 @@ type ( func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { var precompiles map[common.Address]PrecompiledContract switch { + case evm.chainRules.IsPlato: + precompiles = PrecompiledContractsPlato case evm.chainRules.IsLuban: precompiles = PrecompiledContractsLuban case evm.chainRules.IsPlanck: diff --git a/core/vm/lightclient/v1/multistoreproof.go b/core/vm/lightclient/v1/multistoreproof.go index d07197965..742e8bcdb 100644 --- a/core/vm/lightclient/v1/multistoreproof.go +++ b/core/vm/lightclient/v1/multistoreproof.go @@ -143,3 +143,10 @@ func Ics23CompatibleProofRuntime() (prt *merkle.ProofRuntime) { prt.RegisterOpDecoder(ProofOpSimpleMerkleCommitment, CommitmentOpDecoder) return } + +func Ics23ProofRuntime() (prt *merkle.ProofRuntime) { + prt = merkle.NewProofRuntime() + prt.RegisterOpDecoder(ProofOpIAVLCommitment, CommitmentOpDecoder) + prt.RegisterOpDecoder(ProofOpSimpleMerkleCommitment, CommitmentOpDecoder) + return +} diff --git a/params/config.go b/params/config.go index da7f40128..8c368e513 100644 --- a/params/config.go +++ b/params/config.go @@ -854,6 +854,7 @@ type Rules struct { IsMoran bool IsPlanck bool IsLuban bool + IsPlato bool } // Rules ensures c's ChainID is not nil. @@ -879,5 +880,6 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool) Rules { IsMoran: c.IsMoran(num), IsPlanck: c.IsPlanck(num), IsLuban: c.IsLuban(num), + IsPlato: c.IsPlato(num), } }