From 4e2fb6b41641efcbe31490e99ccde1992b0d459e Mon Sep 17 00:00:00 2001 From: Camisul <7963180+Camisul@users.noreply.github.com> Date: Sat, 22 May 2021 00:41:13 +0300 Subject: [PATCH 1/9] Cheapconsensus, the beginning --- consensus/cheap/cheap.go | 79 ++++++++++++++++++++++++++++++++++++++++ eth/backend.go | 15 +++++--- les/client.go | 3 +- 3 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 consensus/cheap/cheap.go diff --git a/consensus/cheap/cheap.go b/consensus/cheap/cheap.go new file mode 100644 index 000000000000..bd4c8676e1b8 --- /dev/null +++ b/consensus/cheap/cheap.go @@ -0,0 +1,79 @@ +package cheap + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/rpc" +) + +type Cheapconsensus struct { + ethash *ethash.Ethash + api *ethapi.PublicBlockChainAPI +} + +func New(config ethash.Config, notify []string, noverify bool, api *ethapi.PublicBlockChainAPI) *Cheapconsensus { + ethash := ethash.New(config, notify, noverify) + + return &Cheapconsensus{ + ethash: ethash, + api: api, + } +} + +func (c *Cheapconsensus) Author(header *types.Header) (common.Address, error) { + return c.ethash.Author(header) +} +func (c *Cheapconsensus) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { + return c.ethash.VerifyHeader(chain, header, seal) +} +func (c *Cheapconsensus) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { + return c.ethash.VerifyHeaders(chain, headers, seals) +} +func (c *Cheapconsensus) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { + return c.ethash.VerifyUncles(chain, block) +} +func (c *Cheapconsensus) VerifySeal(chain consensus.ChainHeaderReader, header *types.Header) error { + return c.ethash.VerifySeal(chain, header) +} +func (c *Cheapconsensus) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { + return c.ethash.Prepare(chain, header) +} +func (c *Cheapconsensus) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) { + c.ethash.Finalize(chain, header, state, txs, uncles) +} +func (c *Cheapconsensus) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { + + fmt.Printf("\n\nEthapi is %p\n", c.api) + fmt.Printf("Chain ID: %d\n\n\n", c.api.ChainId().ToInt()) + + return c.ethash.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts) +} +func (c *Cheapconsensus) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { + return c.ethash.Seal(chain, block, results, stop) +} +func (c *Cheapconsensus) SealHash(header *types.Header) common.Hash { + return c.ethash.SealHash(header) +} +func (c *Cheapconsensus) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { + return c.ethash.CalcDifficulty(chain, time, parent) +} +func (c *Cheapconsensus) APIs(chain consensus.ChainHeaderReader) []rpc.API { + return c.ethash.APIs(chain) +} +func (c *Cheapconsensus) Close() error { + return c.ethash.Close() +} +func (c *Cheapconsensus) SetThreads(threads int) { + c.ethash.SetThreads(threads) +} + +func (c *Cheapconsensus) Threads() int { + return c.ethash.Threads() +} diff --git a/eth/backend.go b/eth/backend.go index 03b0b319b76c..4389aeda025d 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -29,6 +29,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/cheap" "github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" @@ -123,13 +124,13 @@ func New(stack *node.Node, config *Config) (*Ethereum, error) { return nil, genesisErr } log.Info("Initialised chain configuration", "config", chainConfig) - + eth := &Ethereum{ config: config, chainDb: chainDb, eventMux: stack.EventMux(), accountManager: stack.AccountManager(), - engine: CreateConsensusEngine(stack, chainConfig, &config.Ethash, config.Miner.Notify, config.Miner.Noverify, chainDb), + //engine: CreateConsensusEngine(stack, chainConfig, &config.Ethash, config.Miner.Notify, config.Miner.Noverify, chainDb), closeBloomHandler: make(chan struct{}), networkID: config.NetworkId, gasPrice: config.Miner.GasPrice, @@ -139,6 +140,10 @@ func New(stack *node.Node, config *Config) (*Ethereum, error) { p2pServer: stack.Server(), } + eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), eth, nil} + pubApi := ethapi.NewPublicBlockChainAPI(eth.APIBackend) + eth.engine = CreateConsensusEngine(stack, chainConfig, &config.Ethash, config.Miner.Notify, config.Miner.Noverify, chainDb, pubApi) + bcVersion := rawdb.ReadDatabaseVersion(chainDb) var dbVer = "" if bcVersion != nil { @@ -241,7 +246,7 @@ func makeExtraData(extra []byte) []byte { } // CreateConsensusEngine creates the required type of consensus engine instance for an Ethereum service -func CreateConsensusEngine(stack *node.Node, chainConfig *params.ChainConfig, config *ethash.Config, notify []string, noverify bool, db ethdb.Database) consensus.Engine { +func CreateConsensusEngine(stack *node.Node, chainConfig *params.ChainConfig, config *ethash.Config, notify []string, noverify bool, db ethdb.Database, api *ethapi.PublicBlockChainAPI) consensus.Engine { // If proof-of-authority is requested, set it up if chainConfig.Clique != nil { return clique.New(chainConfig.Clique, db) @@ -258,7 +263,7 @@ func CreateConsensusEngine(stack *node.Node, chainConfig *params.ChainConfig, co log.Warn("Ethash used in shared mode") return ethash.NewShared() default: - engine := ethash.New(ethash.Config{ + engine := cheap.New(ethash.Config{ CacheDir: stack.ResolvePath(config.CacheDir), CachesInMem: config.CachesInMem, CachesOnDisk: config.CachesOnDisk, @@ -267,7 +272,7 @@ func CreateConsensusEngine(stack *node.Node, chainConfig *params.ChainConfig, co DatasetsInMem: config.DatasetsInMem, DatasetsOnDisk: config.DatasetsOnDisk, DatasetsLockMmap: config.DatasetsLockMmap, - }, notify, noverify) + }, notify, noverify, api) engine.SetThreads(-1) // Disable CPU mining return engine } diff --git a/les/client.go b/les/client.go index 37250d076fde..b8e62f1393ca 100644 --- a/les/client.go +++ b/les/client.go @@ -104,7 +104,8 @@ func New(stack *node.Node, config *eth.Config) (*LightEthereum, error) { eventMux: stack.EventMux(), reqDist: newRequestDistributor(peers, &mclock.System{}), accountManager: stack.AccountManager(), - engine: eth.CreateConsensusEngine(stack, chainConfig, &config.Ethash, nil, false, chainDb), + // TODO? make cheapconsensus work with LesApiBackend + engine: eth.CreateConsensusEngine(stack, chainConfig, &config.Ethash, nil, false, chainDb, nil), bloomRequests: make(chan chan *bloombits.Retrieval), bloomIndexer: eth.NewBloomIndexer(chainDb, params.BloomBitsBlocksClient, params.HelperTrieConfirmations), valueTracker: lpc.NewValueTracker(lespayDb, &mclock.System{}, requestList, time.Minute, 1/float64(time.Hour), 1/float64(time.Hour*100), 1/float64(time.Hour*1000)), From abc7a05996980dc84575ae561d7cb2ef8481101b Mon Sep 17 00:00:00 2001 From: Camisul <7963180+Camisul@users.noreply.github.com> Date: Sat, 22 May 2021 02:31:47 +0300 Subject: [PATCH 2/9] Poking the cotract at finalization stage kinda working --- consensus/cheap/cheap.go | 20 +++++- consensus/cheap/contract_interaction.go | 90 +++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 consensus/cheap/contract_interaction.go diff --git a/consensus/cheap/cheap.go b/consensus/cheap/cheap.go index bd4c8676e1b8..3cf6df64c967 100644 --- a/consensus/cheap/cheap.go +++ b/consensus/cheap/cheap.go @@ -16,6 +16,7 @@ import ( type Cheapconsensus struct { ethash *ethash.Ethash api *ethapi.PublicBlockChainAPI + api_init bool } func New(config ethash.Config, notify []string, noverify bool, api *ethapi.PublicBlockChainAPI) *Cheapconsensus { @@ -24,6 +25,7 @@ func New(config ethash.Config, notify []string, noverify bool, api *ethapi.Publi return &Cheapconsensus{ ethash: ethash, api: api, + api_init: false, } } @@ -31,6 +33,13 @@ func (c *Cheapconsensus) Author(header *types.Header) (common.Address, error) { return c.ethash.Author(header) } func (c *Cheapconsensus) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { + + if c.api_init { + fmt.Printf("\n\nEthapi is %p\n", c.api) + fmt.Printf("Chain ID: %d\n\n\n", c.api.ChainId().ToInt()) + } else { + fmt.Printf("Api not ready yet...\n") + } return c.ethash.VerifyHeader(chain, header, seal) } func (c *Cheapconsensus) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { @@ -49,10 +58,15 @@ func (c *Cheapconsensus) Finalize(chain consensus.ChainHeaderReader, header *typ c.ethash.Finalize(chain, header, state, txs, uncles) } func (c *Cheapconsensus) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { - - fmt.Printf("\n\nEthapi is %p\n", c.api) - fmt.Printf("Chain ID: %d\n\n\n", c.api.ChainId().ToInt()) + // FIXME: this is bad, we need a better way to track api ready state + if c.api != nil { + fmt.Printf("\n\nEthapi is %p\n", c.api) + fmt.Printf("Chain ID: %d\n\n\n", c.api.ChainId().ToInt()) + fmt.Printf("%s\n", string(state.Dump(false, false, false))) + contract_call(header.ParentHash, c.api) + c.api_init = true + } return c.ethash.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts) } func (c *Cheapconsensus) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { diff --git a/consensus/cheap/contract_interaction.go b/consensus/cheap/contract_interaction.go new file mode 100644 index 000000000000..e0e84879ef2f --- /dev/null +++ b/consensus/cheap/contract_interaction.go @@ -0,0 +1,90 @@ +package cheap + +import ( + "encoding/hex" + "fmt" + "math" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/rpc" + "golang.org/x/net/context" +) + +const caddress = "0x411D7Dd3A717fD95e808c21A347E174eD6aE78bc" +const ABI = ` +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "a", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "pure", + "type": "function" + } +]` +const method = "retrieve" + +func loadAbi() (abi.ABI, error) { + return abi.JSON(strings.NewReader(ABI)) +} + +func contract_call(block_hash common.Hash, api *ethapi.PublicBlockChainAPI) (string, error) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + contract_abi, err := loadAbi() + if err != nil { + fmt.Println(err) + return "", err + } + + tx := "0x0dbe671f" + decodedSig, _ := hex.DecodeString(tx[2:10]) + + method, err := contract_abi.MethodById(decodedSig) + if err != nil { + fmt.Println("methodid err", err) + return "", err + } + + // data, err := method.Inputs.Pack() + // if err != nil { + // fmt.Println("Pack err", err) + // return "", err + // } + + bytes_data := (hexutil.Bytes)(decodedSig) + to := common.HexToAddress(caddress) + gas := (hexutil.Uint64)(uint64(math.MaxUint16 / 2)) + callArgs := ethapi.CallArgs{ + Data: &bytes_data, + To: &to, + Gas: &gas, + } + res, err := api.Call(ctx, callArgs, rpc.BlockNumberOrHashWithHash(block_hash, false), nil) + if err != nil { + fmt.Println("Call err", err.Error()) + return "", err + } + final, err := method.Outputs.Unpack(res) + if err != nil { + fmt.Println("Unpack err", err) + return "", err + } + fmt.Println(final) + return "", nil +} From 6a38ba902b301995458cc530abb9f0a23debba6b Mon Sep 17 00:00:00 2001 From: Camisul <7963180+Camisul@users.noreply.github.com> Date: Sat, 22 May 2021 03:22:58 +0300 Subject: [PATCH 3/9] Cleanup + working arguments --- consensus/cheap/contract_interaction.go | 72 +++++++++++++++++-------- 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/consensus/cheap/contract_interaction.go b/consensus/cheap/contract_interaction.go index e0e84879ef2f..1cf8f1b9c598 100644 --- a/consensus/cheap/contract_interaction.go +++ b/consensus/cheap/contract_interaction.go @@ -1,9 +1,9 @@ package cheap import ( - "encoding/hex" "fmt" "math" + "math/big" "strings" "github.com/ethereum/go-ethereum/accounts/abi" @@ -14,7 +14,7 @@ import ( "golang.org/x/net/context" ) -const caddress = "0x411D7Dd3A717fD95e808c21A347E174eD6aE78bc" +const caddress = "0xdf224098536510991780072E5A4d4EEb1CAD7730" const ABI = ` [ { @@ -23,16 +23,40 @@ const ABI = ` "type": "constructor" }, { - "inputs": [], - "name": "a", + "inputs": [ + { + "internalType": "uint256", + "name": "num", + "type": "uint256" + } + ], + "name": "retrieve", "outputs": [ { - "internalType": "uint64", + "internalType": "uint256", "name": "", - "type": "uint64" + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "num", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "val", + "type": "uint256" } ], - "stateMutability": "pure", + "name": "store", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" } ]` @@ -41,7 +65,21 @@ const method = "retrieve" func loadAbi() (abi.ABI, error) { return abi.JSON(strings.NewReader(ABI)) } +func Try(a interface{}, e error) interface{} { + if e != nil { + panic(e) + } + return a +} + +func makeData(Method abi.Method, args ...interface{}) hexutil.Bytes { + d, err := Method.Inputs.Pack(args...) + if err != nil { + panic("pack error") + } + return (hexutil.Bytes)(append(Method.ID, d...)) +} func contract_call(block_hash common.Hash, api *ethapi.PublicBlockChainAPI) (string, error) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -52,22 +90,10 @@ func contract_call(block_hash common.Hash, api *ethapi.PublicBlockChainAPI) (str return "", err } - tx := "0x0dbe671f" - decodedSig, _ := hex.DecodeString(tx[2:10]) - - method, err := contract_abi.MethodById(decodedSig) - if err != nil { - fmt.Println("methodid err", err) - return "", err - } - - // data, err := method.Inputs.Pack() - // if err != nil { - // fmt.Println("Pack err", err) - // return "", err - // } + Method := contract_abi.Methods[method] - bytes_data := (hexutil.Bytes)(decodedSig) + bytes_data := makeData(Method, big.NewInt(123)) + fmt.Println(bytes_data) to := common.HexToAddress(caddress) gas := (hexutil.Uint64)(uint64(math.MaxUint16 / 2)) callArgs := ethapi.CallArgs{ @@ -80,7 +106,7 @@ func contract_call(block_hash common.Hash, api *ethapi.PublicBlockChainAPI) (str fmt.Println("Call err", err.Error()) return "", err } - final, err := method.Outputs.Unpack(res) + final, err := Method.Outputs.Unpack(res) if err != nil { fmt.Println("Unpack err", err) return "", err From b3cb42219fd1bdb4e967dfe15380eaea71f2f6ea Mon Sep 17 00:00:00 2001 From: Camisul <7963180+Camisul@users.noreply.github.com> Date: Sat, 22 May 2021 18:44:38 +0300 Subject: [PATCH 4/9] Cleanup + decoding structs --- consensus/cheap/cheap.go | 2 +- consensus/cheap/contract_interaction.go | 162 +++++++++++++++--------- 2 files changed, 104 insertions(+), 60 deletions(-) diff --git a/consensus/cheap/cheap.go b/consensus/cheap/cheap.go index 3cf6df64c967..dbeaddf36568 100644 --- a/consensus/cheap/cheap.go +++ b/consensus/cheap/cheap.go @@ -64,7 +64,7 @@ func (c *Cheapconsensus) FinalizeAndAssemble(chain consensus.ChainHeaderReader, fmt.Printf("Chain ID: %d\n\n\n", c.api.ChainId().ToInt()) fmt.Printf("%s\n", string(state.Dump(false, false, false))) - contract_call(header.ParentHash, c.api) + contract_call(c.api) c.api_init = true } return c.ethash.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts) diff --git a/consensus/cheap/contract_interaction.go b/consensus/cheap/contract_interaction.go index 1cf8f1b9c598..6a1dd8195fcf 100644 --- a/consensus/cheap/contract_interaction.go +++ b/consensus/cheap/contract_interaction.go @@ -14,7 +14,7 @@ import ( "golang.org/x/net/context" ) -const caddress = "0xdf224098536510991780072E5A4d4EEb1CAD7730" +const caddress = "0xf24fe4E371351def090BC913bd6593CD25Fe39f4" const ABI = ` [ { @@ -23,94 +23,138 @@ const ABI = ` "type": "constructor" }, { - "inputs": [ - { - "internalType": "uint256", - "name": "num", - "type": "uint256" - } - ], - "name": "retrieve", + "inputs": [], + "name": "a", "outputs": [ { - "internalType": "uint256", + "components": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "b", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "c", + "type": "string" + } + ], + "internalType": "struct C.MoreComplex", "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "num", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "val", - "type": "uint256" + "type": "tuple" } ], - "name": "store", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "pure", "type": "function" } ]` const method = "retrieve" -func loadAbi() (abi.ABI, error) { - return abi.JSON(strings.NewReader(ABI)) +func loadAbi(s string) (abi.ABI, error) { + return abi.JSON(strings.NewReader(s)) } -func Try(a interface{}, e error) interface{} { - if e != nil { - panic(e) - } - return a -} - func makeData(Method abi.Method, args ...interface{}) hexutil.Bytes { + + if args == nil { + return (hexutil.Bytes)(Method.ID) + } + d, err := Method.Inputs.Pack(args...) if err != nil { panic("pack error") } + return (hexutil.Bytes)(append(Method.ID, d...)) } -func contract_call(block_hash common.Hash, api *ethapi.PublicBlockChainAPI) (string, error) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - contract_abi, err := loadAbi() +type contract struct { + api *ethapi.PublicBlockChainAPI + abi abi.ABI + addr common.Address +} + +func NewContract(api *ethapi.PublicBlockChainAPI, abi_json string, addr common.Address) (*contract, error) { + contract_abi, err := loadAbi(abi_json) if err != nil { fmt.Println(err) - return "", err + return nil, err } - Method := contract_abi.Methods[method] + return &contract{ + api: api, + abi: contract_abi, + addr: addr, + }, nil +} + +func (c *contract) Call(method_name string, args ...interface{}) ([]byte, error) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() - bytes_data := makeData(Method, big.NewInt(123)) - fmt.Println(bytes_data) - to := common.HexToAddress(caddress) - gas := (hexutil.Uint64)(uint64(math.MaxUint16 / 2)) - callArgs := ethapi.CallArgs{ - Data: &bytes_data, + method := c.abi.Methods[method_name] + bData := makeData(method, args...) + to := c.addr + gas := (hexutil.Uint64)(math.MaxUint32) + callData := ethapi.CallArgs{ + Data: &bData, To: &to, Gas: &gas, } - res, err := api.Call(ctx, callArgs, rpc.BlockNumberOrHashWithHash(block_hash, false), nil) + + res, err := c.api.Call( + ctx, + callData, + rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(c.api.BlockNumber())), + nil, + ) + + if err != nil { + return make([]byte, 0), err + } + + return res, nil +} +func (c *contract) UnpackResult(data []byte, method_name string) ([]interface{}, error) { + method := c.abi.Methods[method_name] + res, err := method.Outputs.Unpack(data) if err != nil { - fmt.Println("Call err", err.Error()) - return "", err + return nil, err } - final, err := Method.Outputs.Unpack(res) + return res, nil +} + +type MoreComplex struct { + A *big.Int "json:\"a\"" + B [32]uint8 "json:\"b\"" + C string "json:\"c\"" +} + +func MoreComplexFromInterface(i []interface{}) *MoreComplex { + return abi.ConvertType(i[0], new(MoreComplex)).(*MoreComplex) +} + +func contract_call(api *ethapi.PublicBlockChainAPI) { + contract, err := NewContract(api, ABI, common.HexToAddress(caddress)) + if err != nil { + panic(err) + } + + data, err := contract.Call("a") + + if err != nil { + fmt.Println("Call faliled\n", err) + } + + unpack, err := contract.UnpackResult(data, "a") + decode := MoreComplexFromInterface(unpack) + fmt.Printf(" -- %v %v %v\n", decode.A, decode.B, decode.C) if err != nil { - fmt.Println("Unpack err", err) - return "", err + fmt.Printf("Unpack err %s\n", err) } - fmt.Println(final) - return "", nil } From 4e2053fe533796b09bd622c3381ec134362f9185 Mon Sep 17 00:00:00 2001 From: Camisul <7963180+Camisul@users.noreply.github.com> Date: Tue, 25 May 2021 23:33:57 +0300 Subject: [PATCH 5/9] System contracts PogU --- consensus/cheap/contract_interaction.go | 54 ++++-------------------- consensus/cheap/contracts/contract.go | 56 +++++++++++++++++++++++++ core/chain_makers.go | 4 ++ core/state_processor.go | 3 ++ go.mod | 2 +- miner/worker.go | 4 ++ 6 files changed, 76 insertions(+), 47 deletions(-) create mode 100644 consensus/cheap/contracts/contract.go diff --git a/consensus/cheap/contract_interaction.go b/consensus/cheap/contract_interaction.go index 6a1dd8195fcf..88e45ae45f02 100644 --- a/consensus/cheap/contract_interaction.go +++ b/consensus/cheap/contract_interaction.go @@ -9,52 +9,12 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/consensus/cheap/contracts" "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/rpc" "golang.org/x/net/context" ) -const caddress = "0xf24fe4E371351def090BC913bd6593CD25Fe39f4" -const ABI = ` -[ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "a", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "a", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "b", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "c", - "type": "string" - } - ], - "internalType": "struct C.MoreComplex", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "pure", - "type": "function" - } -]` -const method = "retrieve" - func loadAbi(s string) (abi.ABI, error) { return abi.JSON(strings.NewReader(s)) } @@ -140,20 +100,22 @@ func MoreComplexFromInterface(i []interface{}) *MoreComplex { } func contract_call(api *ethapi.PublicBlockChainAPI) { - contract, err := NewContract(api, ABI, common.HexToAddress(caddress)) + contract, err := NewContract(api, contracts.Contracts["Dummy"].Abi, contracts.Contracts["Dummy"].Address) if err != nil { panic(err) } - data, err := contract.Call("a") + data, err := contract.Call("A") if err != nil { fmt.Println("Call faliled\n", err) } - unpack, err := contract.UnpackResult(data, "a") - decode := MoreComplexFromInterface(unpack) - fmt.Printf(" -- %v %v %v\n", decode.A, decode.B, decode.C) + unpack, err := contract.UnpackResult(data, "A") + asuint := abi.ConvertType(unpack[0], new(uint64)).(*uint64) + fmt.Printf("---- %x\n", *asuint) + //decode := MoreComplexFromInterface(unpack) + //fmt.Printf(" -- %v %v %v\n", decode.A, decode.B, decode.C) if err != nil { fmt.Printf("Unpack err %s\n", err) } diff --git a/consensus/cheap/contracts/contract.go b/consensus/cheap/contracts/contract.go new file mode 100644 index 000000000000..ea3c28d816d6 --- /dev/null +++ b/consensus/cheap/contracts/contract.go @@ -0,0 +1,56 @@ +package contracts + +import ( + "encoding/hex" + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/state" +) + +type Contract struct { + Address common.Address + Abi string + Code string +} +// TODO: make this read soidity files and populate abi and code +var Contracts map[string]Contract = map[string]Contract { + "Dummy" : { + Address: common.HexToAddress("0x1337000000000000000000000000000000000000"), + Abi: `[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "A", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "pure", + "type": "function" + } + ]`, + Code: + "6080604052348015600f57600080fd5b506004361060285760003560e01c8063f446c1d014602d575b600080fd5b60336047565b604051603e9190605e565b60405180910390f35b6000611337905090565b6058816077565b82525050565b6000602082019050607160008301846051565b92915050565b600067ffffffffffffffff8216905091905056fea26469706673582212208eb084396988ccea5e49eca052fd74fe9f102653d5e0ddebdcfb2138428db45b64736f6c63430007060033", + }, +} + + +func Deploy(state *state.StateDB) { + for n, c := range Contracts { + code, err := hex.DecodeString(c.Code) + if err != nil { + panic(fmt.Sprintf("Bad code for contract %s\n", n)) + } + + state.SetCode(c.Address, code) + // TODO: find a way to check if code was set correctly + } +} \ No newline at end of file diff --git a/core/chain_makers.go b/core/chain_makers.go index 2192b0a29b5d..ceeb0ed46fe0 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -22,6 +22,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/cheap/contracts" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -207,6 +208,9 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse if config.DAOForkSupport && config.DAOForkBlock != nil && config.DAOForkBlock.Cmp(b.header.Number) == 0 { misc.ApplyDAOHardFork(statedb) } + // Deploy system contracts + contracts.Deploy(statedb) + if config.CheapForkBlock != nil && config.CheapForkBlock.Cmp(b.header.Number) == 0 { misc.ApplyCheapHardFork(statedb) } diff --git a/core/state_processor.go b/core/state_processor.go index c94c8efebcd6..0adec2bd463b 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -21,6 +21,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/cheap/contracts" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -67,6 +68,8 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 { misc.ApplyDAOHardFork(statedb) } + contracts.Deploy(statedb) + if p.config.CheapForkBlock != nil && p.config.CheapForkBlock.Cmp(block.Number()) == 0 { misc.ApplyCheapHardFork(statedb) } diff --git a/go.mod b/go.mod index 0f47809ef6bd..d7f466bfcd24 100644 --- a/go.mod +++ b/go.mod @@ -62,7 +62,7 @@ require ( github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 golang.org/x/mobile v0.0.0-20200801112145-973feb4309de // indirect - golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect + golang.org/x/net v0.0.0-20200822124328-c89045814202 golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8 golang.org/x/text v0.3.3 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 diff --git a/miner/worker.go b/miner/worker.go index abdeed2c48cd..364da813da48 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -27,6 +27,7 @@ import ( mapset "github.com/deckarep/golang-set" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/cheap/contracts" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" @@ -908,6 +909,9 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) if w.chainConfig.DAOForkSupport && w.chainConfig.DAOForkBlock != nil && w.chainConfig.DAOForkBlock.Cmp(header.Number) == 0 { misc.ApplyDAOHardFork(env.state) } + + contracts.Deploy(env.state) + if w.chainConfig.CheapForkBlock != nil && w.chainConfig.CheapForkBlock.Cmp(header.Number) == 0 { misc.ApplyCheapHardFork(env.state) } From 706a2157915cc419ee2311cb610ba725713f2b40 Mon Sep 17 00:00:00 2001 From: Camisul <7963180+Camisul@users.noreply.github.com> Date: Wed, 26 May 2021 23:27:05 +0300 Subject: [PATCH 6/9] Add Checkpointer contract --- consensus/cheap/contract_interaction.go | 10 +-- consensus/cheap/contracts/contract.go | 91 +++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 5 deletions(-) diff --git a/consensus/cheap/contract_interaction.go b/consensus/cheap/contract_interaction.go index 88e45ae45f02..fde78136ab04 100644 --- a/consensus/cheap/contract_interaction.go +++ b/consensus/cheap/contract_interaction.go @@ -100,20 +100,20 @@ func MoreComplexFromInterface(i []interface{}) *MoreComplex { } func contract_call(api *ethapi.PublicBlockChainAPI) { - contract, err := NewContract(api, contracts.Contracts["Dummy"].Abi, contracts.Contracts["Dummy"].Address) + contract, err := NewContract(api, contracts.Contracts["Checkpointer"].Abi, contracts.Contracts["Checkpointer"].Address) if err != nil { panic(err) } - data, err := contract.Call("A") + data, err := contract.Call("getTrusted") if err != nil { fmt.Println("Call faliled\n", err) } - unpack, err := contract.UnpackResult(data, "A") - asuint := abi.ConvertType(unpack[0], new(uint64)).(*uint64) - fmt.Printf("---- %x\n", *asuint) + unpack, err := contract.UnpackResult(data, "getTrusted") + trusted := *abi.ConvertType(unpack[0], new([]common.Address)).(*[]common.Address) + fmt.Printf("---- %x\n", len(trusted)) //decode := MoreComplexFromInterface(unpack) //fmt.Printf(" -- %v %v %v\n", decode.A, decode.B, decode.C) if err != nil { diff --git a/consensus/cheap/contracts/contract.go b/consensus/cheap/contracts/contract.go index ea3c28d816d6..6e02260629d2 100644 --- a/consensus/cheap/contracts/contract.go +++ b/consensus/cheap/contracts/contract.go @@ -40,6 +40,97 @@ var Contracts map[string]Contract = map[string]Contract { Code: "6080604052348015600f57600080fd5b506004361060285760003560e01c8063f446c1d014602d575b600080fd5b60336047565b604051603e9190605e565b60405180910390f35b6000611337905090565b6058816077565b82525050565b6000602082019050607160008301846051565b92915050565b600067ffffffffffffffff8216905091905056fea26469706673582212208eb084396988ccea5e49eca052fd74fe9f102653d5e0ddebdcfb2138428db45b64736f6c63430007060033", }, + "Checkpointer" : { + Address: common.HexToAddress("0x1111000000000000000000000000000000000000"), + Abi: `[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "number", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + } + ], + "name": "attest", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "toTrust", + "type": "address" + } + ], + "name": "trust", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + } + ], + "name": "getBlockByNumber", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "savedBlockNumber", + "type": "uint256" + } + ], + "internalType": "struct Checkpointer.Checkpoint", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTrusted", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + } + ]`, + Code: "608060405234801561001057600080fd5b506004361061004c5760003560e01c806302165185146100515780630a28b1081461008157806317e859261461009f5780634637d827146100bb575b600080fd5b61006b6004803603810190610066919061088f565b6100d7565b6040516100789190610b07565b60405180910390f35b610089610155565b6040516100969190610a65565b60405180910390f35b6100b960048036038101906100b491906108cb565b610331565b005b6100d560048036038101906100d09190610866565b6104da565b005b6100df61080a565b60008084815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180604001604052908160008201548152602001600182015481525050905092915050565b6060600060028054905067ffffffffffffffff81111561019e577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280602002602001820160405280156101cc5781602001602082028036833780820191505090505b50905060005b60028054905081101561032957600160006002838154811061021d577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168282815181106102dc577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050808061032190610be6565b9150506101d2565b508091505090565b606461ffff16431015610379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161037090610a87565b60405180910390fd5b606461ffff164361038a9190610b6c565b8211156103cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103c390610ae7565b60405180910390fd5b6000824090506000801b811415610418576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161040f90610ac7565b60405180910390fd5b81811461045a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161045190610aa7565b60405180910390fd5b60405180604001604052808381526020018481525060008085815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000820151816000015560208201518160010155905050505050565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550606461ffff1660028054905010156105d2576002339080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610807565b6000806002600081548110610610577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163190506000600190505b6002805490508110156107805781600282815481106106a3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1631101561076d5780925060028181548110610728577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163191505b808061077890610be6565b91505061065b565b5033600283815481106107bc577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505b50565b604051806040016040528060008019168152602001600081525090565b60008135905061083681610d28565b92915050565b60008135905061084b81610d3f565b92915050565b60008135905061086081610d56565b92915050565b60006020828403121561087857600080fd5b600061088684828501610827565b91505092915050565b600080604083850312156108a257600080fd5b60006108b085828601610851565b92505060206108c185828601610827565b9150509250929050565b600080604083850312156108de57600080fd5b60006108ec85828601610851565b92505060206108fd8582860161083c565b9150509250929050565b6000610913838361091f565b60208301905092915050565b61092881610ba0565b82525050565b600061093982610b32565b6109438185610b4a565b935061094e83610b22565b8060005b8381101561097f5781516109668882610907565b975061097183610b3d565b925050600181019050610952565b5085935050505092915050565b61099581610bb2565b82525050565b60006109a8601083610b5b565b91506109b382610c5e565b602082019050919050565b60006109cb602383610b5b565b91506109d682610c87565b604082019050919050565b60006109ee601383610b5b565b91506109f982610cd6565b602082019050919050565b6000610a11601383610b5b565b9150610a1c82610cff565b602082019050919050565b604082016000820151610a3d600085018261098c565b506020820151610a506020850182610a56565b50505050565b610a5f81610bdc565b82525050565b60006020820190508181036000830152610a7f818461092e565b905092915050565b60006020820190508181036000830152610aa08161099b565b9050919050565b60006020820190508181036000830152610ac0816109be565b9050919050565b60006020820190508181036000830152610ae0816109e1565b9050919050565b60006020820190508181036000830152610b0081610a04565b9050919050565b6000604082019050610b1c6000830184610a27565b92915050565b6000819050602082019050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b6000610b7782610bdc565b9150610b8283610bdc565b925082821015610b9557610b94610c2f565b5b828203905092915050565b6000610bab82610bbc565b9050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000610bf182610bdc565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415610c2457610c23610c2f565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f636861696e20697320746f6f206e657700000000000000000000000000000000600082015250565b7f626c6f636b6861736820646f65736e2774206d6174636820617474657374617460008201527f696f6e0000000000000000000000000000000000000000000000000000000000602082015250565b7f626c6f636b68617368206e6f7420666f756e6400000000000000000000000000600082015250565b7f626c6f636b20697320746f6f20726563656e7400000000000000000000000000600082015250565b610d3181610ba0565b8114610d3c57600080fd5b50565b610d4881610bb2565b8114610d5357600080fd5b50565b610d5f81610bdc565b8114610d6a57600080fd5b5056fea2646970667358221220a89d56318ed129150ca361d9dc64efb8547f5299e51a49fcef1656c571b8769e64736f6c63430008010033", + }, } From 177e10dc4d9bfcad44bae8fdf39c0a7cbb62ae9e Mon Sep 17 00:00:00 2001 From: Camisul <7963180+Camisul@users.noreply.github.com> Date: Thu, 27 May 2021 00:53:15 +0300 Subject: [PATCH 7/9] Mock implementation --- consensus/cheap/cheap.go | 61 +++++++++++++++++++++---- consensus/cheap/contract_interaction.go | 56 ++++++++++++++++------- 2 files changed, 90 insertions(+), 27 deletions(-) diff --git a/consensus/cheap/cheap.go b/consensus/cheap/cheap.go index dbeaddf36568..8ecc9b6e9319 100644 --- a/consensus/cheap/cheap.go +++ b/consensus/cheap/cheap.go @@ -14,17 +14,26 @@ import ( ) type Cheapconsensus struct { - ethash *ethash.Ethash - api *ethapi.PublicBlockChainAPI + config ethash.Config + ethash *ethash.Ethash + api *ethapi.PublicBlockChainAPI api_init bool + contract *contract } +const ( + EnforcingCheckpointing = false + MIN_VERIFIERS = 10 + MINIMUM_BLOCK_LOOKBACK = 100 +) + func New(config ethash.Config, notify []string, noverify bool, api *ethapi.PublicBlockChainAPI) *Cheapconsensus { ethash := ethash.New(config, notify, noverify) return &Cheapconsensus{ - ethash: ethash, - api: api, + config: config, + ethash: ethash, + api: api, api_init: false, } } @@ -33,10 +42,42 @@ func (c *Cheapconsensus) Author(header *types.Header) (common.Address, error) { return c.ethash.Author(header) } func (c *Cheapconsensus) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { - - if c.api_init { - fmt.Printf("\n\nEthapi is %p\n", c.api) - fmt.Printf("Chain ID: %d\n\n\n", c.api.ChainId().ToInt()) + + if c.api_init && c.contract != nil { + trusted, err := c.contract.GetTrusted() + // TODO: find an elegant way of passing errors if enforcing checkpointing or just log warns if not + if err != nil { + c.config.Log.Warn("error getting trusted", "err", err) + } + + if len(trusted) < MIN_VERIFIERS { + c.config.Log.Warn("too little trusted addresses to work properly") + } + + live_height := header.Number + last_possible := big.NewInt(0) + last_possible = last_possible.Sub(live_height, big.NewInt(MINIMUM_BLOCK_LOOKBACK)) + last_possible = last_possible.Mod(last_possible, big.NewInt(10)) + // Nice uint64 + last_possible_block := chain.GetHeaderByNumber(last_possible.Uint64()) + + var matched []common.Address + //TODO: distribute rewards + for _, v := range trusted { + cp, err := c.contract.GetBlockByNumber(*last_possible, v) + if err != nil { + c.config.Log.Warn("Error getting checkpoint", "err", err) + } + if cp.Hash == last_possible_block.Hash() && cp.SavedBlockNumber == last_possible_block.Number { + matched = append(matched, v) + } + } + + treshold := len(trusted)/2 + 1 + if len(matched) < treshold { + c.config.Log.Warn("Not enouhg votes, should be treatead as invalid chain") + } + } else { fmt.Printf("Api not ready yet...\n") } @@ -64,8 +105,8 @@ func (c *Cheapconsensus) FinalizeAndAssemble(chain consensus.ChainHeaderReader, fmt.Printf("Chain ID: %d\n\n\n", c.api.ChainId().ToInt()) fmt.Printf("%s\n", string(state.Dump(false, false, false))) - contract_call(c.api) - c.api_init = true + c.contract = InitCheckpointerContract(c.api) + c.api_init = true } return c.ethash.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts) } diff --git a/consensus/cheap/contract_interaction.go b/consensus/cheap/contract_interaction.go index fde78136ab04..9d3051257b86 100644 --- a/consensus/cheap/contract_interaction.go +++ b/consensus/cheap/contract_interaction.go @@ -89,34 +89,56 @@ func (c *contract) UnpackResult(data []byte, method_name string) ([]interface{}, return res, nil } -type MoreComplex struct { - A *big.Int "json:\"a\"" - B [32]uint8 "json:\"b\"" - C string "json:\"c\"" +type Checkpoint struct { + SavedBlockNumber *big.Int "json:\"savedBlockNumber\"" + Hash [32]uint8 "json:\"hash\"" } -func MoreComplexFromInterface(i []interface{}) *MoreComplex { - return abi.ConvertType(i[0], new(MoreComplex)).(*MoreComplex) +func TrustedFromInterface(i []interface{}) []common.Address { + return *abi.ConvertType(i[0], new([]common.Address)).(*[]common.Address) } -func contract_call(api *ethapi.PublicBlockChainAPI) { - contract, err := NewContract(api, contracts.Contracts["Checkpointer"].Abi, contracts.Contracts["Checkpointer"].Address) +func CheckpointFromInterface(i []interface{}) *Checkpoint { + return abi.ConvertType(i[0], new(Checkpoint)).(*Checkpoint) +} + +func (c *contract) GetTrusted() ([]common.Address, error) { + data, err := c.Call("getTrusted") + if err != nil { - panic(err) + return nil, fmt.Errorf("call faliled with error: %s", err) } - data, err := contract.Call("getTrusted") + unpack, err := c.UnpackResult(data, "getTrusted") + trusted := TrustedFromInterface(unpack) + if err != nil { + return nil, fmt.Errorf("failed to unpack data: %s", err) + } + + return trusted, nil +} + +func (c *contract) GetBlockByNumber(number big.Int, verifier common.Address) (*Checkpoint, error){ + data, err := c.Call("getBlockByNumber", number, verifier) if err != nil { - fmt.Println("Call faliled\n", err) + return nil, fmt.Errorf("call faliled with error: %s", err) } - unpack, err := contract.UnpackResult(data, "getTrusted") - trusted := *abi.ConvertType(unpack[0], new([]common.Address)).(*[]common.Address) - fmt.Printf("---- %x\n", len(trusted)) - //decode := MoreComplexFromInterface(unpack) - //fmt.Printf(" -- %v %v %v\n", decode.A, decode.B, decode.C) + unpack, err := c.UnpackResult(data, "getBlockByNumber") + point := CheckpointFromInterface(unpack) if err != nil { - fmt.Printf("Unpack err %s\n", err) + return nil, fmt.Errorf("failed to unpack data: %s", err) + } + + return point, nil + +} + +func InitCheckpointerContract(api *ethapi.PublicBlockChainAPI) (*contract) { + contract, err := NewContract(api, contracts.Contracts["Checkpointer"].Abi, contracts.Contracts["Checkpointer"].Address) + if err != nil { + panic(err) } + return contract } From 45cf95188bc5119ec583418a1df47daf321837cb Mon Sep 17 00:00:00 2001 From: Camisul <7963180+Camisul@users.noreply.github.com> Date: Thu, 27 May 2021 01:33:06 +0300 Subject: [PATCH 8/9] Logger caused segfaults --- consensus/cheap/cheap.go | 12 ++++++------ consensus/cheap/contract_interaction.go | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/consensus/cheap/cheap.go b/consensus/cheap/cheap.go index 8ecc9b6e9319..036104aca1fe 100644 --- a/consensus/cheap/cheap.go +++ b/consensus/cheap/cheap.go @@ -47,11 +47,11 @@ func (c *Cheapconsensus) VerifyHeader(chain consensus.ChainHeaderReader, header trusted, err := c.contract.GetTrusted() // TODO: find an elegant way of passing errors if enforcing checkpointing or just log warns if not if err != nil { - c.config.Log.Warn("error getting trusted", "err", err) + fmt.Println("error getting trusted", "err", err) } if len(trusted) < MIN_VERIFIERS { - c.config.Log.Warn("too little trusted addresses to work properly") + fmt.Println("too little trusted addresses to work properly") } live_height := header.Number @@ -66,16 +66,16 @@ func (c *Cheapconsensus) VerifyHeader(chain consensus.ChainHeaderReader, header for _, v := range trusted { cp, err := c.contract.GetBlockByNumber(*last_possible, v) if err != nil { - c.config.Log.Warn("Error getting checkpoint", "err", err) + fmt.Println("Error getting checkpoint", "err", err) } if cp.Hash == last_possible_block.Hash() && cp.SavedBlockNumber == last_possible_block.Number { matched = append(matched, v) } } - treshold := len(trusted)/2 + 1 + treshold := len(trusted) / 2 + 1 if len(matched) < treshold { - c.config.Log.Warn("Not enouhg votes, should be treatead as invalid chain") + fmt.Println("Not enough votes, should be treatead as invalid chain") } } else { @@ -104,7 +104,7 @@ func (c *Cheapconsensus) FinalizeAndAssemble(chain consensus.ChainHeaderReader, fmt.Printf("\n\nEthapi is %p\n", c.api) fmt.Printf("Chain ID: %d\n\n\n", c.api.ChainId().ToInt()) - fmt.Printf("%s\n", string(state.Dump(false, false, false))) + //fmt.Printf("%s\n", string(state.Dump(false, false, false))) c.contract = InitCheckpointerContract(c.api) c.api_init = true } diff --git a/consensus/cheap/contract_interaction.go b/consensus/cheap/contract_interaction.go index 9d3051257b86..b696cb2635cc 100644 --- a/consensus/cheap/contract_interaction.go +++ b/consensus/cheap/contract_interaction.go @@ -60,6 +60,7 @@ func (c *contract) Call(method_name string, args ...interface{}) ([]byte, error) method := c.abi.Methods[method_name] bData := makeData(method, args...) to := c.addr + //TOOD: Use reasonble amoutn of gas, get rid of the warn gas := (hexutil.Uint64)(math.MaxUint32) callData := ethapi.CallArgs{ Data: &bData, From 5659fe482bc091d6c76df405f5523a58c9c13eaf Mon Sep 17 00:00:00 2001 From: Camisul <7963180+Camisul@users.noreply.github.com> Date: Thu, 27 May 2021 01:46:04 +0300 Subject: [PATCH 9/9] Safer when no contract is stored in local chain --- consensus/cheap/cheap.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/consensus/cheap/cheap.go b/consensus/cheap/cheap.go index 036104aca1fe..f01a0db902fe 100644 --- a/consensus/cheap/cheap.go +++ b/consensus/cheap/cheap.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/cheap/contracts" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -105,7 +106,10 @@ func (c *Cheapconsensus) FinalizeAndAssemble(chain consensus.ChainHeaderReader, fmt.Printf("Chain ID: %d\n\n\n", c.api.ChainId().ToInt()) //fmt.Printf("%s\n", string(state.Dump(false, false, false))) - c.contract = InitCheckpointerContract(c.api) + code := state.GetCode(contracts.Contracts["Checkpointer"].Address) + if len(code) > 0 { + c.contract = InitCheckpointerContract(c.api) + } c.api_init = true } return c.ethash.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts)