2024-05-09 18:54:47 +00:00
|
|
|
package dasigners
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
precopmiles_common "github.com/0glabs/0g-chain/precompiles/common"
|
|
|
|
dasignerskeeper "github.com/0glabs/0g-chain/x/dasigners/v1/keeper"
|
2024-05-10 18:41:14 +00:00
|
|
|
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
2024-05-09 18:54:47 +00:00
|
|
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
|
|
"github.com/ethereum/go-ethereum/core/vm"
|
|
|
|
"github.com/evmos/ethermint/x/evm/statedb"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2024-05-10 18:41:14 +00:00
|
|
|
PrecompileAddress = "0x0000000000000000000000000000000000001000"
|
|
|
|
|
|
|
|
RequiredGasMax uint64 = 1000_000_000
|
2024-05-09 18:54:47 +00:00
|
|
|
|
|
|
|
DASignersFunctionEpochNumber = "epochNumber"
|
|
|
|
DASignersFunctionGetSigner = "getSigner"
|
|
|
|
DASignersFunctionGetSigners = "getSigners"
|
|
|
|
DASignersFunctionUpdateSocket = "updateSocket"
|
|
|
|
DASignersFunctionRegisterNextEpoch = "registerNextEpoch"
|
|
|
|
DASignersFunctionRegisterSigner = "registerSigner"
|
|
|
|
DASignersFunctionGetAggPkG1 = "getAggPkG1"
|
|
|
|
)
|
|
|
|
|
2024-05-10 18:41:14 +00:00
|
|
|
var RequiredGasBasic = map[string]uint64{
|
|
|
|
"epochNumber": 1000,
|
|
|
|
"getSigner": 10000,
|
|
|
|
"getSigners": 1000000,
|
|
|
|
"updateSocket": 50000,
|
|
|
|
"registerNextEpoch": 100000,
|
|
|
|
"registerSigner": 100000,
|
|
|
|
"getAggPkG1": 1000000,
|
|
|
|
}
|
|
|
|
|
|
|
|
var KVGasConfig storetypes.GasConfig = storetypes.GasConfig{
|
|
|
|
HasCost: 0,
|
|
|
|
DeleteCost: 0,
|
|
|
|
ReadCostFlat: 0,
|
|
|
|
ReadCostPerByte: 0,
|
|
|
|
WriteCostFlat: 0,
|
|
|
|
WriteCostPerByte: 0,
|
|
|
|
IterNextCostFlat: 0,
|
|
|
|
}
|
|
|
|
|
2024-05-09 18:54:47 +00:00
|
|
|
var _ vm.PrecompiledContract = &DASignersPrecompile{}
|
|
|
|
|
|
|
|
type DASignersPrecompile struct {
|
|
|
|
abi abi.ABI
|
|
|
|
dasignersKeeper dasignerskeeper.Keeper
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewDASignersPrecompile(dasignersKeeper dasignerskeeper.Keeper) (*DASignersPrecompile, error) {
|
|
|
|
abi, err := abi.JSON(strings.NewReader(DASignersABI))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &DASignersPrecompile{
|
|
|
|
abi: abi,
|
|
|
|
dasignersKeeper: dasignersKeeper,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Address implements vm.PrecompiledContract.
|
|
|
|
func (d *DASignersPrecompile) Address() common.Address {
|
|
|
|
return common.HexToAddress(PrecompileAddress)
|
|
|
|
}
|
|
|
|
|
|
|
|
// RequiredGas implements vm.PrecompiledContract.
|
|
|
|
func (d *DASignersPrecompile) RequiredGas(input []byte) uint64 {
|
2024-05-10 18:41:14 +00:00
|
|
|
method, err := d.abi.MethodById(input[:4])
|
|
|
|
if err != nil {
|
|
|
|
return RequiredGasMax
|
|
|
|
}
|
|
|
|
if gas, ok := RequiredGasBasic[method.Name]; ok {
|
|
|
|
return gas
|
|
|
|
}
|
|
|
|
return RequiredGasMax
|
2024-05-09 18:54:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Run implements vm.PrecompiledContract.
|
|
|
|
func (d *DASignersPrecompile) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) {
|
|
|
|
// parse input
|
|
|
|
if len(contract.Input) < 4 {
|
|
|
|
return nil, vm.ErrExecutionReverted
|
|
|
|
}
|
|
|
|
method, err := d.abi.MethodById(contract.Input[:4])
|
|
|
|
if err != nil {
|
|
|
|
return nil, vm.ErrExecutionReverted
|
|
|
|
}
|
|
|
|
args, err := method.Inputs.Unpack(contract.Input[4:])
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
// get state db and context
|
|
|
|
stateDB, ok := evm.StateDB.(*statedb.StateDB)
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf(precopmiles_common.ErrGetStateDB)
|
|
|
|
}
|
|
|
|
ctx := stateDB.GetContext()
|
2024-05-10 18:41:14 +00:00
|
|
|
// reset gas config
|
|
|
|
ctx = ctx.WithKVGasConfig(KVGasConfig)
|
2024-05-09 18:54:47 +00:00
|
|
|
initialGas := ctx.GasMeter().GasConsumed()
|
|
|
|
|
|
|
|
var bz []byte
|
|
|
|
switch method.Name {
|
|
|
|
// queries
|
|
|
|
case DASignersFunctionEpochNumber:
|
|
|
|
bz, err = d.EpochNumber(ctx, evm, method, args)
|
|
|
|
case DASignersFunctionGetSigner:
|
|
|
|
bz, err = d.GetSigner(ctx, evm, method, args)
|
|
|
|
case DASignersFunctionGetSigners:
|
|
|
|
bz, err = d.GetSigners(ctx, evm, method, args)
|
|
|
|
case DASignersFunctionGetAggPkG1:
|
|
|
|
bz, err = d.GetAggPkG1(ctx, evm, method, args)
|
|
|
|
// txs
|
|
|
|
case DASignersFunctionRegisterSigner:
|
|
|
|
bz, err = d.RegisterSigner(ctx, evm, stateDB, method, args)
|
|
|
|
case DASignersFunctionRegisterNextEpoch:
|
|
|
|
bz, err = d.RegisterNextEpoch(ctx, evm, stateDB, method, args)
|
|
|
|
case DASignersFunctionUpdateSocket:
|
|
|
|
bz, err = d.UpdateSocket(ctx, evm, stateDB, method, args)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
cost := ctx.GasMeter().GasConsumed() - initialGas
|
|
|
|
|
|
|
|
if !contract.UseGas(cost) {
|
|
|
|
return nil, vm.ErrOutOfGas
|
|
|
|
}
|
|
|
|
return bz, nil
|
|
|
|
}
|