From 494d69c269544e434b8196cb260b088e5e04e85d Mon Sep 17 00:00:00 2001 From: chanhle Date: Wed, 25 Oct 2023 09:50:04 -0400 Subject: [PATCH] add precompiled contract to get info from Algorand chain --- core/vm/algorand/input.go | 114 ++++++++++++++++++ core/vm/algorand/input_test.go | 43 +++++++ core/vm/algorand/output.go | 41 +++++++ core/vm/algorand/precompiled.go | 81 +++++++++++++ core/vm/contracts.go | 20 +-- demos/algorand/contracts/AlgorandInfo.sol | 22 ++++ demos/algorand/txs/1_deploy/alloc.json | 10 ++ demos/algorand/txs/1_deploy/env.json | 12 ++ demos/algorand/txs/1_deploy/txn.json | 11 ++ demos/algorand/txs/1_deploy/txs.json | 1 + .../txs/2_call_getAccountBalance/alloc.json | 14 +++ .../txs/2_call_getAccountBalance/env.json | 12 ++ .../txs/2_call_getAccountBalance/txn.json | 12 ++ .../txs/2_call_getAccountBalance/txs.json | 1 + demos/sign_txn/main.go | 59 +++++++++ go.mod | 3 + go.sum | 12 ++ params/protocol_params.go | 2 + 18 files changed, 461 insertions(+), 9 deletions(-) create mode 100644 core/vm/algorand/input.go create mode 100644 core/vm/algorand/input_test.go create mode 100644 core/vm/algorand/output.go create mode 100644 core/vm/algorand/precompiled.go create mode 100644 demos/algorand/contracts/AlgorandInfo.sol create mode 100644 demos/algorand/txs/1_deploy/alloc.json create mode 100644 demos/algorand/txs/1_deploy/env.json create mode 100644 demos/algorand/txs/1_deploy/txn.json create mode 100644 demos/algorand/txs/1_deploy/txs.json create mode 100644 demos/algorand/txs/2_call_getAccountBalance/alloc.json create mode 100644 demos/algorand/txs/2_call_getAccountBalance/env.json create mode 100644 demos/algorand/txs/2_call_getAccountBalance/txn.json create mode 100644 demos/algorand/txs/2_call_getAccountBalance/txs.json create mode 100644 demos/sign_txn/main.go diff --git a/core/vm/algorand/input.go b/core/vm/algorand/input.go new file mode 100644 index 0000000000..d47b00af75 --- /dev/null +++ b/core/vm/algorand/input.go @@ -0,0 +1,114 @@ +// Copyright 2023 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package algorand + +import ( + "fmt" + "reflect" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" +) + +type CmdType = uint8 + +const ( + // AccountCmd is the type of the command to get account information. + AccountCmd CmdType = iota +) + +// Input is the interface for the input of the Algorand precompiled contract. +type Input interface { + GetCmdType() CmdType // GetCmdType returns the command type. + GetFieldName() string // GetFieldName returns the name of the field to get. +} + +// AccountInput is the input for the command to get account information. +type AccountInput struct { + Cmd CmdType // Command type. + FieldName string // Name of the field to get. + Address string // Address of the account. +} + +// GetCmdType returns the command type. +func (input *AccountInput) GetCmdType() CmdType { + return input.Cmd +} + +// GetFieldName returns the name of the field to get. +func (input *AccountInput) GetFieldName() string { + return input.FieldName +} + +// getCmdTypeFromRawInput gets the command type from the raw input. +func getCmdTypeFromRawInput(inputBytes []byte) (CmdType, error) { + cmd := new(CmdType) + err := unpack(inputBytes, cmd) + if err != nil { + return 0, err + } + return *cmd, nil +} + +// UnpackInput decodes the raw input into the input of the Algorand precompiled contract. +func UnpackInput(inputBytes []byte) (Input, error) { + cmd, err := getCmdTypeFromRawInput(inputBytes) + if err != nil { + return nil, err + } + switch cmd { + case AccountCmd: + input := new(AccountInput) + err = unpack(inputBytes, input) + if err != nil { + return nil, err + } + return input, nil + default: + return nil, fmt.Errorf("unknown command type: %d", cmd) + } +} + +// abiType returns the ABI of the given name and type. +func abiType(name string, typ reflect.Type) string { + if typ.Kind() == reflect.Ptr { + return abiType(name, typ.Elem()) + } else if typ.Kind() == reflect.Struct { + var fields []string + for i := 0; i < typ.NumField(); i++ { + fields = append(fields, abiType(typ.Field(i).Name, typ.Field(i).Type)) + } + return strings.Join(fields, ", ") + } else { + return fmt.Sprintf(`{"name": "%s", "type": "%s"}`, name, typ.String()) + } +} + +// unpack decodes the raw data into the given output interface. +func unpack(rawData []byte, output interface{}) error { + typ := reflect.TypeOf(output) + defn := fmt.Sprintf(`[{"type": "function", "outputs": [%s]}]`, abiType("", typ)) + abi, err := abi.JSON(strings.NewReader(defn)) + if err != nil { + return err + } + err = abi.UnpackIntoInterface(output, "", rawData) + if err != nil { + return err + } + return nil +} diff --git a/core/vm/algorand/input_test.go b/core/vm/algorand/input_test.go new file mode 100644 index 0000000000..95b7bf99ed --- /dev/null +++ b/core/vm/algorand/input_test.go @@ -0,0 +1,43 @@ +// Copyright 2023 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package algorand + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestGetCmdType(t *testing.T) { + data, err := common.ParseHexOrString("0x0000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + cmd, err := getCmdTypeFromRawInput(data) + require.NoError(t, err) + require.Equal(t, AccountCmd, CmdType(cmd)) +} + +func TestDecodeInput(t *testing.T) { + data, err := common.ParseHexOrString("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000006416d6f756e740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003a3733373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737375546454a324349000000000000") + require.NoError(t, err) + input, err := UnpackInput(data) + require.NoError(t, err) + require.Equal(t, AccountCmd, input.GetCmdType()) + // 737777777777777777777777777777777777777777777777777UFEJ2CI is the address of RewardsPool in the Algorand mainnet. + require.Equal(t, "737777777777777777777777777777777777777777777777777UFEJ2CI", input.(*AccountInput).Address) + require.Equal(t, "Amount", input.(*AccountInput).FieldName) +} diff --git a/core/vm/algorand/output.go b/core/vm/algorand/output.go new file mode 100644 index 0000000000..f8df444677 --- /dev/null +++ b/core/vm/algorand/output.go @@ -0,0 +1,41 @@ +// Copyright 2023 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package algorand + +import ( + "fmt" + "reflect" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" +) + +func pack(value reflect.Value) ([]byte, error) { + defn := fmt.Sprintf(`[{"type": "constructor", "inputs": [%s]}]`, abiType("", value.Type())) + abi, err := abi.JSON(strings.NewReader(defn)) + if err != nil { + return nil, err + } + data, err := abi.Pack("", value.Interface()) + if err != nil { + return nil, err + } + log.Info("Pack", "data", common.Bytes2Hex(data)) + return data, nil +} diff --git a/core/vm/algorand/precompiled.go b/core/vm/algorand/precompiled.go new file mode 100644 index 0000000000..50ed73ede2 --- /dev/null +++ b/core/vm/algorand/precompiled.go @@ -0,0 +1,81 @@ +// Copyright 2023 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package algorand + +import ( + "context" + "fmt" + "os" + "reflect" + + "github.com/algorand/go-algorand-sdk/client/v2/algod" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" +) + +// Algorand implements the precompile to access the Algorand blockchain. +type Algorand struct { + algodAddress string + algodToken string + algodClient *algod.Client +} + +// New creates a new Algorand precompiled contract with a client to access Algorand blockchain. +func New() *Algorand { + algodAddress := os.Getenv("ALGOD_ADDRESS") + algodToken := os.Getenv("ALGOD_TOKEN") + algorand := &Algorand{ + algodAddress: algodAddress, + algodToken: algodToken, + } + algodClient, err := algod.MakeClient(algodAddress, algodToken) + if err == nil { + algorand.algodClient = algodClient + } + return algorand +} + +// RequiredGas estimates the gas required for running the point evaluation precompile. +func (a *Algorand) RequiredGas(input []byte) uint64 { + return params.AlgorandPrecompileGas +} + +// Run executes the Algorand precompile with the given input. +func (a *Algorand) Run(input []byte) ([]byte, error) { + if a.algodClient == nil { + return nil, fmt.Errorf("cannot connect to Algorand node") + } + + params, err := UnpackInput(input) + if err != nil { + return nil, err + } + var info interface{} + switch params.GetCmdType() { + case AccountCmd: + info, err = a.algodClient.AccountInformation(params.(*AccountInput).Address).Do(context.Background()) + if err != nil { + return nil, err + } + } + log.Info("Algorand.Run", "info", info) + value := reflect.ValueOf(info).FieldByName(params.GetFieldName()) + if !value.IsValid() { + return nil, fmt.Errorf("field %s does not exist", params.GetFieldName()) + } + return pack(value) +} diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 574bb9bef6..a7707c6a52 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/core/vm/algorand" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/blake2b" "github.com/ethereum/go-ethereum/crypto/bls12381" @@ -81,15 +82,16 @@ var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{ // PrecompiledContractsBerlin contains the default set of pre-compiled Ethereum // contracts used in the Berlin release. var PrecompiledContractsBerlin = 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{eip2565: true}, - common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, - common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, - common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, - common.BytesToAddress([]byte{9}): &blake2F{}, + 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{eip2565: true}, + common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, + common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, + common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, + common.BytesToAddress([]byte{9}): &blake2F{}, + common.BytesToAddress([]byte{0xff}): algorand.New(), // An instance of the Algorand precompiled contract } // PrecompiledContractsCancun contains the default set of pre-compiled Ethereum diff --git a/demos/algorand/contracts/AlgorandInfo.sol b/demos/algorand/contracts/AlgorandInfo.sol new file mode 100644 index 0000000000..392837c11e --- /dev/null +++ b/demos/algorand/contracts/AlgorandInfo.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +contract AlgorandInfo { + event Log(string message, uint256 value); + + enum CmdType { + AccountCmd + } + + function getAccountBalance( + string memory accountAddress + ) public returns (uint256) { + (bool ok, bytes memory data) = address(0xff).call( + abi.encode(CmdType.AccountCmd, "Amount", accountAddress) + ); + require(ok, "failed to get account balance"); + uint256 balance = abi.decode(data, (uint256)); + emit Log("balance", balance); + return balance; + } +} diff --git a/demos/algorand/txs/1_deploy/alloc.json b/demos/algorand/txs/1_deploy/alloc.json new file mode 100644 index 0000000000..46438c4708 --- /dev/null +++ b/demos/algorand/txs/1_deploy/alloc.json @@ -0,0 +1,10 @@ +{ + "0x7ea155883a46dccf117972cb1e438fe5ec1c353c": { + "balance": "0xffffffff", + "nonce": "0x0" + }, + "0xc207a7021fbef833a19f3688a5e7a8cf1e331391": { + "balance": "0xffff", + "nonce": "0x0" + } +} diff --git a/demos/algorand/txs/1_deploy/env.json b/demos/algorand/txs/1_deploy/env.json new file mode 100644 index 0000000000..3b959873e8 --- /dev/null +++ b/demos/algorand/txs/1_deploy/env.json @@ -0,0 +1,12 @@ +{ + "currentCoinbase": "0xc207a7021fbef833a19f3688a5e7a8cf1e331391", + "currentDifficulty": "0x1", + "currentGasLimit": "0x05f5e100", + "currentBaseFee": "0x1", + "currentNumber": "0x01", + "currentTimestamp": "0x03e8", + "previousHash": "0xe729de3fec21e30bea3d56adb01ed14bc107273c2775f9355afb10f594a10d9e", + "blockHashes": { + "0": "0xe729de3fec21e30bea3d56adb01ed14bc107273c2775f9355afb10f594a10d9e" + } +} diff --git a/demos/algorand/txs/1_deploy/txn.json b/demos/algorand/txs/1_deploy/txn.json new file mode 100644 index 0000000000..f8910516f3 --- /dev/null +++ b/demos/algorand/txs/1_deploy/txn.json @@ -0,0 +1,11 @@ +{ + "from": "0x7ea155883a46dccf117972cb1e438fe5ec1c353c", + "gas": "0xEFFFFF", + "gasPrice": "0x1", + "nonce": "0x0", + "value": "0x0", + "input": "0x608060405234801561001057600080fd5b506106bd806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c82b4dbb14610030575b600080fd5b61004a600480360381019061004591906102e8565b610060565b604051610057919061034a565b60405180910390f35b600080600060ff73ffffffffffffffffffffffffffffffffffffffff166000856040516020016100919291906104a7565b6040516020818303038152906040526040516100ad9190610531565b6000604051808303816000865af19150503d80600081146100ea576040519150601f19603f3d011682016040523d82523d6000602084013e6100ef565b606091505b509150915081610134576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161012b90610594565b60405180910390fd5b60008180602001905181019061014a91906105e0565b90507fdd970dd9b5bfe707922155b058a407655cb18288b807e2216442bca8ad83d6b58160405161017b9190610659565b60405180910390a1809350505050919050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6101f5826101ac565b810181811067ffffffffffffffff82111715610214576102136101bd565b5b80604052505050565b600061022761018e565b905061023382826101ec565b919050565b600067ffffffffffffffff821115610253576102526101bd565b5b61025c826101ac565b9050602081019050919050565b82818337600083830152505050565b600061028b61028684610238565b61021d565b9050828152602081018484840111156102a7576102a66101a7565b5b6102b2848285610269565b509392505050565b600082601f8301126102cf576102ce6101a2565b5b81356102df848260208601610278565b91505092915050565b6000602082840312156102fe576102fd610198565b5b600082013567ffffffffffffffff81111561031c5761031b61019d565b5b610328848285016102ba565b91505092915050565b6000819050919050565b61034481610331565b82525050565b600060208201905061035f600083018461033b565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600181106103a5576103a4610365565b5b50565b60008190506103b682610394565b919050565b60006103c6826103a8565b9050919050565b6103d6816103bb565b82525050565b600082825260208201905092915050565b7f416d6f756e740000000000000000000000000000000000000000000000000000600082015250565b60006104236006836103dc565b915061042e826103ed565b602082019050919050565b600081519050919050565b60005b83811015610462578082015181840152602081019050610447565b60008484015250505050565b600061047982610439565b61048381856103dc565b9350610493818560208601610444565b61049c816101ac565b840191505092915050565b60006060820190506104bc60008301856103cd565b81810360208301526104cd81610416565b905081810360408301526104e1818461046e565b90509392505050565b600081519050919050565b600081905092915050565b600061050b826104ea565b61051581856104f5565b9350610525818560208601610444565b80840191505092915050565b600061053d8284610500565b915081905092915050565b7f6661696c656420746f20676574206163636f756e742062616c616e6365000000600082015250565b600061057e601d836103dc565b915061058982610548565b602082019050919050565b600060208201905081810360008301526105ad81610571565b9050919050565b6105bd81610331565b81146105c857600080fd5b50565b6000815190506105da816105b4565b92915050565b6000602082840312156105f6576105f5610198565b5b6000610604848285016105cb565b91505092915050565b7f62616c616e636500000000000000000000000000000000000000000000000000600082015250565b60006106436007836103dc565b915061064e8261060d565b602082019050919050565b6000604082019050818103600083015261067281610636565b9050610681602083018461033b565b9291505056fea2646970667358221220c3e34f0989dd6a37b0ef1efd133f9204e87676e4f623bd2ed7bdc6b7495c955464736f6c63430008150033", + "r": "0x0", + "s": "0x0", + "v": "0x0" +} diff --git a/demos/algorand/txs/1_deploy/txs.json b/demos/algorand/txs/1_deploy/txs.json new file mode 100644 index 0000000000..9c5f72a265 --- /dev/null +++ b/demos/algorand/txs/1_deploy/txs.json @@ -0,0 +1 @@ +[{"type":"0x0","chainId":"0x3039","nonce":"0x0","to":null,"gas":"0xefffff","gasPrice":"0x1","maxPriorityFeePerGas":null,"maxFeePerGas":null,"value":"0x0","input":"0x608060405234801561001057600080fd5b506106bd806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c82b4dbb14610030575b600080fd5b61004a600480360381019061004591906102e8565b610060565b604051610057919061034a565b60405180910390f35b600080600060ff73ffffffffffffffffffffffffffffffffffffffff166000856040516020016100919291906104a7565b6040516020818303038152906040526040516100ad9190610531565b6000604051808303816000865af19150503d80600081146100ea576040519150601f19603f3d011682016040523d82523d6000602084013e6100ef565b606091505b509150915081610134576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161012b90610594565b60405180910390fd5b60008180602001905181019061014a91906105e0565b90507fdd970dd9b5bfe707922155b058a407655cb18288b807e2216442bca8ad83d6b58160405161017b9190610659565b60405180910390a1809350505050919050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6101f5826101ac565b810181811067ffffffffffffffff82111715610214576102136101bd565b5b80604052505050565b600061022761018e565b905061023382826101ec565b919050565b600067ffffffffffffffff821115610253576102526101bd565b5b61025c826101ac565b9050602081019050919050565b82818337600083830152505050565b600061028b61028684610238565b61021d565b9050828152602081018484840111156102a7576102a66101a7565b5b6102b2848285610269565b509392505050565b600082601f8301126102cf576102ce6101a2565b5b81356102df848260208601610278565b91505092915050565b6000602082840312156102fe576102fd610198565b5b600082013567ffffffffffffffff81111561031c5761031b61019d565b5b610328848285016102ba565b91505092915050565b6000819050919050565b61034481610331565b82525050565b600060208201905061035f600083018461033b565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600181106103a5576103a4610365565b5b50565b60008190506103b682610394565b919050565b60006103c6826103a8565b9050919050565b6103d6816103bb565b82525050565b600082825260208201905092915050565b7f416d6f756e740000000000000000000000000000000000000000000000000000600082015250565b60006104236006836103dc565b915061042e826103ed565b602082019050919050565b600081519050919050565b60005b83811015610462578082015181840152602081019050610447565b60008484015250505050565b600061047982610439565b61048381856103dc565b9350610493818560208601610444565b61049c816101ac565b840191505092915050565b60006060820190506104bc60008301856103cd565b81810360208301526104cd81610416565b905081810360408301526104e1818461046e565b90509392505050565b600081519050919050565b600081905092915050565b600061050b826104ea565b61051581856104f5565b9350610525818560208601610444565b80840191505092915050565b600061053d8284610500565b915081905092915050565b7f6661696c656420746f20676574206163636f756e742062616c616e6365000000600082015250565b600061057e601d836103dc565b915061058982610548565b602082019050919050565b600060208201905081810360008301526105ad81610571565b9050919050565b6105bd81610331565b81146105c857600080fd5b50565b6000815190506105da816105b4565b92915050565b6000602082840312156105f6576105f5610198565b5b6000610604848285016105cb565b91505092915050565b7f62616c616e636500000000000000000000000000000000000000000000000000600082015250565b60006106436007836103dc565b915061064e8261060d565b602082019050919050565b6000604082019050818103600083015261067281610636565b9050610681602083018461033b565b9291505056fea2646970667358221220c3e34f0989dd6a37b0ef1efd133f9204e87676e4f623bd2ed7bdc6b7495c955464736f6c63430008150033","v":"0x6095","r":"0x9cd962349de5242d0c06a7497d9af10fff0093a2e0d89a84a510dedf542c98db","s":"0xbf35c832b9bb95aeea1dcef91fed916e8df4bb853fff7def884570019004aab","hash":"0x1eb22482ecccb5056cb8813539eae824649309b019c5fa4d211e0c1ef550ecdf"}] \ No newline at end of file diff --git a/demos/algorand/txs/2_call_getAccountBalance/alloc.json b/demos/algorand/txs/2_call_getAccountBalance/alloc.json new file mode 100644 index 0000000000..097da82264 --- /dev/null +++ b/demos/algorand/txs/2_call_getAccountBalance/alloc.json @@ -0,0 +1,14 @@ +{ + "0x6feaf11191837029e00915a6cd877dc334f6dce4": { + "code": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063c82b4dbb14610030575b600080fd5b61004a600480360381019061004591906102e8565b610060565b604051610057919061034a565b60405180910390f35b600080600060ff73ffffffffffffffffffffffffffffffffffffffff166000856040516020016100919291906104a7565b6040516020818303038152906040526040516100ad9190610531565b6000604051808303816000865af19150503d80600081146100ea576040519150601f19603f3d011682016040523d82523d6000602084013e6100ef565b606091505b509150915081610134576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161012b90610594565b60405180910390fd5b60008180602001905181019061014a91906105e0565b90507fdd970dd9b5bfe707922155b058a407655cb18288b807e2216442bca8ad83d6b58160405161017b9190610659565b60405180910390a1809350505050919050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6101f5826101ac565b810181811067ffffffffffffffff82111715610214576102136101bd565b5b80604052505050565b600061022761018e565b905061023382826101ec565b919050565b600067ffffffffffffffff821115610253576102526101bd565b5b61025c826101ac565b9050602081019050919050565b82818337600083830152505050565b600061028b61028684610238565b61021d565b9050828152602081018484840111156102a7576102a66101a7565b5b6102b2848285610269565b509392505050565b600082601f8301126102cf576102ce6101a2565b5b81356102df848260208601610278565b91505092915050565b6000602082840312156102fe576102fd610198565b5b600082013567ffffffffffffffff81111561031c5761031b61019d565b5b610328848285016102ba565b91505092915050565b6000819050919050565b61034481610331565b82525050565b600060208201905061035f600083018461033b565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600181106103a5576103a4610365565b5b50565b60008190506103b682610394565b919050565b60006103c6826103a8565b9050919050565b6103d6816103bb565b82525050565b600082825260208201905092915050565b7f416d6f756e740000000000000000000000000000000000000000000000000000600082015250565b60006104236006836103dc565b915061042e826103ed565b602082019050919050565b600081519050919050565b60005b83811015610462578082015181840152602081019050610447565b60008484015250505050565b600061047982610439565b61048381856103dc565b9350610493818560208601610444565b61049c816101ac565b840191505092915050565b60006060820190506104bc60008301856103cd565b81810360208301526104cd81610416565b905081810360408301526104e1818461046e565b90509392505050565b600081519050919050565b600081905092915050565b600061050b826104ea565b61051581856104f5565b9350610525818560208601610444565b80840191505092915050565b600061053d8284610500565b915081905092915050565b7f6661696c656420746f20676574206163636f756e742062616c616e6365000000600082015250565b600061057e601d836103dc565b915061058982610548565b602082019050919050565b600060208201905081810360008301526105ad81610571565b9050919050565b6105bd81610331565b81146105c857600080fd5b50565b6000815190506105da816105b4565b92915050565b6000602082840312156105f6576105f5610198565b5b6000610604848285016105cb565b91505092915050565b7f62616c616e636500000000000000000000000000000000000000000000000000600082015250565b60006106436007836103dc565b915061064e8261060d565b602082019050919050565b6000604082019050818103600083015261067281610636565b9050610681602083018461033b565b9291505056fea2646970667358221220c3e34f0989dd6a37b0ef1efd133f9204e87676e4f623bd2ed7bdc6b7495c955464736f6c63430008150033", + "balance": "0x0", + "nonce": "0x1" + }, + "0x7ea155883a46dccf117972cb1e438fe5ec1c353c": { + "balance": "0xfff98817", + "nonce": "0x1" + }, + "0xc207a7021fbef833a19f3688a5e7a8cf1e331391": { + "balance": "0xffff" + } +} \ No newline at end of file diff --git a/demos/algorand/txs/2_call_getAccountBalance/env.json b/demos/algorand/txs/2_call_getAccountBalance/env.json new file mode 100644 index 0000000000..3b959873e8 --- /dev/null +++ b/demos/algorand/txs/2_call_getAccountBalance/env.json @@ -0,0 +1,12 @@ +{ + "currentCoinbase": "0xc207a7021fbef833a19f3688a5e7a8cf1e331391", + "currentDifficulty": "0x1", + "currentGasLimit": "0x05f5e100", + "currentBaseFee": "0x1", + "currentNumber": "0x01", + "currentTimestamp": "0x03e8", + "previousHash": "0xe729de3fec21e30bea3d56adb01ed14bc107273c2775f9355afb10f594a10d9e", + "blockHashes": { + "0": "0xe729de3fec21e30bea3d56adb01ed14bc107273c2775f9355afb10f594a10d9e" + } +} diff --git a/demos/algorand/txs/2_call_getAccountBalance/txn.json b/demos/algorand/txs/2_call_getAccountBalance/txn.json new file mode 100644 index 0000000000..83d77602a2 --- /dev/null +++ b/demos/algorand/txs/2_call_getAccountBalance/txn.json @@ -0,0 +1,12 @@ +{ + "from": "0x7ea155883a46dccf117972cb1e438fe5ec1c353c", + "to": "0x6feaf11191837029e00915a6cd877dc334f6dce4", + "gas": "0xEFFFFF", + "gasPrice": "0x1", + "nonce": "0x1", + "value": "0x0", + "input": "0xc82b4dbb0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003a3733373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737375546454a324349000000000000", + "r": "0x0", + "s": "0x0", + "v": "0x0" +} diff --git a/demos/algorand/txs/2_call_getAccountBalance/txs.json b/demos/algorand/txs/2_call_getAccountBalance/txs.json new file mode 100644 index 0000000000..90b93c3ce3 --- /dev/null +++ b/demos/algorand/txs/2_call_getAccountBalance/txs.json @@ -0,0 +1 @@ +[{"type":"0x0","chainId":"0x3039","nonce":"0x1","to":"0x6feaf11191837029e00915a6cd877dc334f6dce4","gas":"0xefffff","gasPrice":"0x1","maxPriorityFeePerGas":null,"maxFeePerGas":null,"value":"0x0","input":"0xc82b4dbb0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003a3733373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737375546454a324349000000000000","v":"0x6096","r":"0x9e77098cdb2ca3193be26b0cf21b39a1596594c7b2b5daf5d39bea36a1ff4e42","s":"0x37a89f4cc4a32c3a5311d63a9c74b9839dc765e0c1c9c3ea26e8173d8dbe626f","hash":"0x7f7910dd079df505fcdb23d3856d7aae0500ce38659a2ff2d801ae8b55952022"}] \ No newline at end of file diff --git a/demos/sign_txn/main.go b/demos/sign_txn/main.go new file mode 100644 index 0000000000..c25e138e60 --- /dev/null +++ b/demos/sign_txn/main.go @@ -0,0 +1,59 @@ +package main + +import ( + "encoding/json" + "flag" + "math/big" + "os" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +func main() { + keystorePath := flag.String("keystore", "", "Keystore path") + txnPath := flag.String("txn", "", "Unsigned transaction") + chainIDArg := flag.String("chainid", "", "Chain ID") + signer := flag.String("signer", "", "Signer") + password := flag.String("password", "", "Password") + + flag.Parse() + + ks := keystore.NewKeyStore(*keystorePath, keystore.StandardScryptN, keystore.StandardScryptP) + + account, err := ks.Find(accounts.Account{Address: common.HexToAddress(*signer)}) + if err != nil { + panic(err) + } + + txnData, err := os.ReadFile(*txnPath) + if err != nil { + panic(err) + } + + var txn types.Transaction + if err := txn.UnmarshalJSON(txnData); err != nil { + panic(err) + } + + chainID, ok := new(big.Int).SetString(*chainIDArg, 10) + if !ok { + panic("invalid chain ID") + } + + signedTxn, err := ks.SignTxWithPassphrase(account, *password, &txn, chainID) + if err != nil { + panic(err) + } + txs := []*types.Transaction{signedTxn} + txsData, err := json.Marshal(txs) + if err != nil { + panic(err) + } + err = os.WriteFile("txs.json", txsData, 0644) + if err != nil { + panic(err) + } +} diff --git a/go.mod b/go.mod index 4901030311..3291fcf5ca 100644 --- a/go.mod +++ b/go.mod @@ -80,6 +80,9 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect github.com/DataDog/zstd v1.4.5 // indirect github.com/StackExchange/wmi v1.2.1 // indirect + github.com/algorand/avm-abi v0.2.0 // indirect + github.com/algorand/go-algorand-sdk v1.24.0 // indirect + github.com/algorand/go-codec/codec v1.1.10 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37 // indirect diff --git a/go.sum b/go.sum index 6017c9f77e..abfdfe71b9 100644 --- a/go.sum +++ b/go.sum @@ -63,6 +63,12 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/algorand/avm-abi v0.2.0 h1:bkjsG+BOEcxUcnGSALLosmltE0JZdg+ZisXKx0UDX2k= +github.com/algorand/avm-abi v0.2.0/go.mod h1:+CgwM46dithy850bpTeHh9MC99zpn2Snirb3QTl2O/g= +github.com/algorand/go-algorand-sdk v1.24.0 h1:mi8vqjXMC5nU87snq4vxHi+NgPR0thtZHRLA16FKZMM= +github.com/algorand/go-algorand-sdk v1.24.0/go.mod h1:WEeJcctOHMzDFTgVJ6GT8BLUo9DbFTT47S+Kzx7ffXQ= +github.com/algorand/go-codec/codec v1.1.10 h1:zmWYU1cp64jQVTOG8Tw8wa+k0VfwgXIPbnDfiVa+5QA= +github.com/algorand/go-codec/codec v1.1.10/go.mod h1:YkEx5nmr/zuCeaDYOIhlDg92Lxju8tj2d2NrYqP7g7k= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= @@ -559,6 +565,7 @@ github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobt github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -600,6 +607,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -653,6 +661,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= @@ -694,6 +703,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= @@ -771,6 +781,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -850,6 +861,7 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= diff --git a/params/protocol_params.go b/params/protocol_params.go index 8a5c011849..baf6eb2863 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -174,6 +174,8 @@ const ( BlobTxTargetBlobGasPerBlock = 3 * BlobTxBlobGasPerBlob // Target consumable blob gas for data blobs per block (for 1559-like pricing) MaxBlobGasPerBlock = 6 * BlobTxBlobGasPerBlob // Maximum consumable blob gas for data blobs per block + + AlgorandPrecompileGas = 1000 // Gas price for the Algorand precompile. ) // Gas discount table for BLS12-381 G1 and G2 multi exponentiation operations