mirror of
https://github.com/luxfi/precompile.git
synced 2026-09-24 00:26:21 +00:00
158 lines
4.7 KiB
Go
158 lines
4.7 KiB
Go
// Copyright (C) 2025, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package graph
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/luxfi/database"
|
|
"github.com/luxfi/geth/common"
|
|
"github.com/luxfi/precompile/contract"
|
|
gvm "github.com/luxfi/precompile/graph/graphvm"
|
|
"github.com/luxfi/precompile/modules"
|
|
"github.com/luxfi/precompile/precompileconfig"
|
|
)
|
|
|
|
var _ contract.Configurator = (*configurator)(nil)
|
|
var _ contract.StatefulPrecompiledContract = (*GraphQLContract)(nil)
|
|
|
|
// ConfigKey is the key used in json config files to specify this precompile config.
|
|
const ConfigKey = "graphConfig"
|
|
|
|
// Contract addresses for Graph/Query layer (0x0500-0x05FF)
|
|
// Note: Hashing precompiles (Poseidon2, Pedersen, Blake3) use 0x0500...0001-0004
|
|
// Graph precompiles start at 0x0500...0010 to avoid conflicts
|
|
var (
|
|
ContractGraphQLAddress = common.HexToAddress("0x0500000000000000000000000000000000000010")
|
|
ContractSubscribeAddress = common.HexToAddress("0x0500000000000000000000000000000000000011")
|
|
ContractCacheAddress = common.HexToAddress("0x0500000000000000000000000000000000000012")
|
|
ContractIndexAddress = common.HexToAddress("0x0500000000000000000000000000000000000013")
|
|
)
|
|
|
|
// GraphQLContract wraps GraphQLPrecompile to implement StatefulPrecompiledContract
|
|
type GraphQLContract struct {
|
|
precompile *GraphQLPrecompile
|
|
}
|
|
|
|
// GraphContractInstance is the singleton
|
|
var GraphContractInstance = &GraphQLContract{
|
|
precompile: NewGraphQLPrecompile(nil),
|
|
}
|
|
|
|
// SetGraphVMClient configures the Graph precompile to use a real GraphVM client.
|
|
// This should be called during VM initialization when the database is available.
|
|
func SetGraphVMClient(db database.Database, config *gvm.GConfig) {
|
|
client := NewGraphVMClient(db, config)
|
|
GraphContractInstance.precompile.client = client
|
|
}
|
|
|
|
// SetGraphVMClientWithChainID configures the client for a specific chain.
|
|
func SetGraphVMClientWithChainID(db database.Database, config *gvm.GConfig, chainID uint64) {
|
|
client := NewGraphVMClientWithChainID(db, config, chainID)
|
|
GraphContractInstance.precompile.client = client
|
|
}
|
|
|
|
// Module is the precompile module
|
|
var Module = modules.Module{
|
|
ConfigKey: ConfigKey,
|
|
Address: ContractGraphQLAddress,
|
|
Contract: GraphContractInstance,
|
|
Configurator: &configurator{},
|
|
}
|
|
|
|
type configurator struct{}
|
|
|
|
func init() {
|
|
if err := modules.RegisterModule(Module); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func (*configurator) MakeConfig() precompileconfig.Config {
|
|
return new(GraphConfig)
|
|
}
|
|
|
|
func (*configurator) Configure(
|
|
chainConfig precompileconfig.ChainConfig,
|
|
cfg precompileconfig.Config,
|
|
state contract.StateDB,
|
|
blockContext contract.ConfigurationBlockContext,
|
|
) error {
|
|
config, ok := cfg.(*GraphConfig)
|
|
if !ok {
|
|
return fmt.Errorf("expected config type %T, got %T: %v", &GraphConfig{}, cfg, cfg)
|
|
}
|
|
|
|
// Update precompile configuration
|
|
if config.GChainEndpoint != "" {
|
|
GraphContractInstance.precompile.config.GChainEndpoint = config.GChainEndpoint
|
|
}
|
|
if config.QueryTimeout > 0 {
|
|
GraphContractInstance.precompile.config.QueryTimeout = time.Duration(config.QueryTimeout) * time.Second
|
|
}
|
|
if config.MaxCacheSize > 0 {
|
|
GraphContractInstance.precompile.config.MaxCacheSize = config.MaxCacheSize
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GraphConfig implements the precompileconfig.Config interface
|
|
type GraphConfig struct {
|
|
Upgrade precompileconfig.Upgrade `json:"upgrade"`
|
|
GChainEndpoint string `json:"gChainEndpoint,omitempty"`
|
|
QueryTimeout int `json:"queryTimeout,omitempty"`
|
|
MaxCacheSize int `json:"maxCacheSize,omitempty"`
|
|
}
|
|
|
|
func (c *GraphConfig) Key() string {
|
|
return ConfigKey
|
|
}
|
|
|
|
func (c *GraphConfig) Timestamp() *uint64 {
|
|
return c.Upgrade.Timestamp()
|
|
}
|
|
|
|
func (c *GraphConfig) IsDisabled() bool {
|
|
return c.Upgrade.Disable
|
|
}
|
|
|
|
func (c *GraphConfig) Equal(cfg precompileconfig.Config) bool {
|
|
other, ok := cfg.(*GraphConfig)
|
|
if !ok {
|
|
return false
|
|
}
|
|
return c.Upgrade.Equal(&other.Upgrade) &&
|
|
c.GChainEndpoint == other.GChainEndpoint &&
|
|
c.QueryTimeout == other.QueryTimeout &&
|
|
c.MaxCacheSize == other.MaxCacheSize
|
|
}
|
|
|
|
func (c *GraphConfig) Verify(chainConfig precompileconfig.ChainConfig) error {
|
|
return nil
|
|
}
|
|
|
|
// Run implements StatefulPrecompiledContract
|
|
func (c *GraphQLContract) Run(
|
|
accessibleState contract.AccessibleState,
|
|
caller common.Address,
|
|
addr common.Address,
|
|
input []byte,
|
|
suppliedGas uint64,
|
|
readOnly bool,
|
|
) (ret []byte, remainingGas uint64, err error) {
|
|
requiredGas := c.precompile.RequiredGas(input)
|
|
if suppliedGas < requiredGas {
|
|
return nil, 0, fmt.Errorf("out of gas: required %d, supplied %d", requiredGas, suppliedGas)
|
|
}
|
|
|
|
result, runErr := c.precompile.Run(input)
|
|
if runErr != nil {
|
|
return nil, suppliedGas - requiredGas, runErr
|
|
}
|
|
|
|
return result, suppliedGas - requiredGas, nil
|
|
}
|