package main import ( "crypto/ecdsa" "encoding/json" "fmt" "log" "math/big" "net/http" "strings" "github.com/ethereum/go-ethereum/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/rpc" ) // SimpleStorage 是从 Solidity 合约生成的绑定。 type SimpleStorage struct { *bind.BoundContract } // NewSimpleStorage 创建一个与 SimpleStorage 合约绑定的新实例。 func NewSimpleStorage(address common.Address, backend bind.ContractBackend) (*SimpleStorage, error) { parsed, err := abi.JSON(strings.NewReader(simpleStorageABI)) if err != nil { return nil, err } contract := bind.NewBoundContract(address, parsed, backend, backend, backend) return &SimpleStorage{contract}, nil } // Set 调用合约的 set 方法。 func (s *SimpleStorage) Set(opts *bind.TransactOpts, key string, value *big.Int) (*types.Transaction, error) { return s.Transact(opts, "set", key, value) } // Get 调用合约的 get 方法。 func (s *SimpleStorage) Get(opts *bind.CallOpts, key string) (*big.Int, error) { var res []interface{} err := s.Call(opts, &res, "get", key) if err != nil { return nil, err } decoded, ok := res[0].(*big.Int) if !ok { return nil, fmt.Errorf("failed to decode result") } return decoded, nil } var simpleStorageABI = `[{"constant":false,"inputs":[{"name":"key","type":"string"},{"name":"value","type":"uint256"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"key","type":"string"}],"name":"get","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]` var simpleStorageBytecode = "0x608060405234801561001057600080fd5b5060c08061001f6000396000f3fe60806040526004361061004e576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632e1a7d4d14610053575b600080fd5b34801561005f57600080fd5b5061006c600480360381019080803590602001909291905050506100a2565b6040518082815260200191505060405180910390f35b60008160008190555056fea26469706673582212209c6b1e4d375b6083c4d98b45a74086c425c7f89f2f0f8e0f40d1b28b1dfb3d4664736f6c634300080a0033" var contractAddress = common.HexToAddress("0x5FbDB2315678afecb367f032d93F642f64180aa3") // 替换为实际的合约地址 func main() { // 使用 WebSocket 连接到本地运行的 Geth 实例 rpcClient, err := rpc.Dial("ws://localhost:8546") if err != nil { log.Fatalf("Failed to connect to the Ethereum client: %v", err) } defer rpcClient.Close() client := ethclient.NewClient(rpcClient) // 生成一个新的随机账户 privateKey, err := crypto.GenerateKey() if err != nil { log.Fatalf("Failed to generate private key: %v", err) } publicKey := privateKey.Public() // publicKeyECDSA 已删除,因为未使用 fromAddress := crypto.PubkeyToAddress(publicKey.(ecdsa.PublicKey)) // 创建交易选项 auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1337)) if err != nil { log.Fatalf("Failed to create transactor: %v", err) } auth.Nonce = big.NewInt(0) // 设置初始 nonce auth.Value = big.NewInt(0) // 没有转账价值 auth.GasLimit = uint64(300000) // 设置 gas limit auth.GasPrice = big.NewInt(1) // 设置 gas 价格 // 创建合约实例 instance, err := NewSimpleStorage(contractAddress, client) if err != nil { log.Fatalf("Failed to instantiate contract: %v", err) } http.HandleFunc("/set", func(w http.ResponseWriter, r *http.Request) { valueStr := r.URL.Query().Get("value") key := r.URL.Query().Get("key") if valueStr == "" || key == "" { http.Error(w, "Missing 'value' or 'key' parameter", http.StatusBadRequest) return } value, ok := new(big.Int).SetString(valueStr, 10) if !ok { http.Error(w, "Invalid 'value' parameter", http.StatusBadRequest) return } tx, err := instance.Set(auth, key, value) if err != nil { http.Error(w, fmt.Sprintf("Failed to set value: %v", err), http.StatusInternalServerError) return } fmt.Fprintf(w, "Transaction sent: %s\n", tx.Hash().Hex()) }) http.HandleFunc("/get", func(w http.ResponseWriter, r *http.Request) { key := r.URL.Query().Get("key") if key == "" { http.Error(w, "Missing 'key' parameter", http.StatusBadRequest) return } value, err := instance.Get(&bind.CallOpts{}, key) if err != nil { http.Error(w, fmt.Sprintf("Failed to get value: %v", err), http.StatusInternalServerError) return } json.NewEncoder(w).Encode(map[string]interface{}{ "key": key, "value": value, }) }) log.Println("Starting server on :8081...") if err := http.ListenAndServe(":8081", nil); err != nil { log.Fatalf("Failed to start server: %v", err) } }