diff --git a/api/api.go b/api/api.go index 9b51d28d7..c4a5ca480 100644 --- a/api/api.go +++ b/api/api.go @@ -7,18 +7,22 @@ import ( "encoding/hex" "fmt" "math/big" + "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" "github.com/onflow/cadence" "github.com/onflow/flow-evm-gateway/storage" + "github.com/onflow/flow-go-sdk" "github.com/onflow/flow-go-sdk/access" + "github.com/onflow/flow-go-sdk/access/grpc" + + sdkCrypto "github.com/onflow/flow-go-sdk/crypto" ) const EthNamespace = "eth" @@ -101,7 +105,93 @@ func (api *BlockChainAPI) SendRawTransaction( ctx context.Context, input hexutil.Bytes, ) (common.Hash, error) { - return crypto.Keccak256Hash([]byte("hello world")), nil + gethTx := &types.Transaction{} + encodedLen := uint(len(input)) + err := gethTx.DecodeRLP( + rlp.NewStream( + bytes.NewReader(input), + uint64(encodedLen), + ), + ) + if err != nil { + return common.Hash{}, err + } + + flowClient, err := grpc.NewClient(grpc.EmulatorHost) + if err != nil { + return common.Hash{}, err + } + + script := ` + import EVM from 0xf8d6e0586b0a20c7 + + transaction(encodedTx: [UInt8]) { + let bridgedAccount: &EVM.BridgedAccount + + prepare(signer: auth(Storage) &Account) { + self.bridgedAccount = signer.storage.borrow<&EVM.BridgedAccount>( + from: /storage/evm + ) ?? panic("Could not borrow reference to the bridged account!") + } + + execute { + EVM.run(tx: encodedTx, coinbase: self.bridgedAccount.address()) + log("transaction executed") + } + } + ` + + block, err := flowClient.GetLatestBlock(context.Background(), true) + if err != nil { + return common.Hash{}, err + } + + privateKey, err := sdkCrypto.DecodePrivateKeyHex(sdkCrypto.ECDSA_P256, strings.Replace("2619878f0e2ff438d17835c2a4561cb87b4d24d72d12ec34569acd0dd4af7c21", "0x", "", 1)) + if err != nil { + return common.Hash{}, err + } + + account, err := flowClient.GetAccount(context.Background(), flow.HexToAddress("0xf8d6e0586b0a20c7")) + if err != nil { + return common.Hash{}, err + } + accountKey := account.Keys[0] + signer, err := sdkCrypto.NewInMemorySigner(privateKey, accountKey.HashAlgo) + if err != nil { + return common.Hash{}, err + } + + tx := flow.NewTransaction(). + SetScript([]byte(script)). + SetProposalKey(account.Address, accountKey.Index, accountKey.SequenceNumber). + SetReferenceBlockID(block.ID). + SetPayer(account.Address). + AddAuthorizer(account.Address) + + decodedTx, err := hex.DecodeString(input.String()[2:]) + if err != nil { + return common.Hash{}, err + } + cdcBytes := make([]cadence.Value, 0) + for _, bt := range decodedTx { + cdcBytes = append(cdcBytes, cadence.UInt8(bt)) + } + encodedTx := cadence.NewArray( + cdcBytes, + ).WithType(cadence.NewVariableSizedArrayType(cadence.TheUInt8Type)) + tx.AddArgument(encodedTx) + + err = tx.SignEnvelope(account.Address, accountKey.Index, signer) + if err != nil { + return common.Hash{}, err + } + + err = flowClient.SendTransaction(ctx, *tx) + if err != nil { + return common.Hash{}, err + } + + return gethTx.Hash(), nil } // eth_createAccessList