From 6b4b1a496b820d96a5a90e6b95a7a6e260b863df Mon Sep 17 00:00:00 2001 From: andOneBasketball Date: Sat, 23 Nov 2024 17:06:19 +0800 Subject: [PATCH] update --- accountBalance.go | 9 ++ calculateContractAddress.go | 40 ++++++++ deployContract.go | 93 +++++++++++++++++ deployToken.go | 103 +++++++++++++++++++ getWalletAddress.go | 37 +++++++ go.mod | 4 +- go.sum | 5 + monitorBlock.go | 67 +++++++++++++ queryUniswapTxInfo.go | 195 ++++++++++++++++++++++++++++++++++++ signOpt.go | 83 +++++++++++++++ wordGenerationAccount.go | 2 +- 11 files changed, 635 insertions(+), 3 deletions(-) create mode 100644 calculateContractAddress.go create mode 100644 deployContract.go create mode 100644 deployToken.go create mode 100644 getWalletAddress.go create mode 100644 monitorBlock.go create mode 100644 queryUniswapTxInfo.go create mode 100644 signOpt.go diff --git a/accountBalance.go b/accountBalance.go index 6a91113..7224b4e 100644 --- a/accountBalance.go +++ b/accountBalance.go @@ -26,6 +26,15 @@ func main() { } fmt.Println(balance) // 25893180161173005034 + // 获取最新区块上的 nonce 值 + nonce, err := client.NonceAt(context.Background(), account, nil) + if err != nil { + log.Fatal(err) + } + + // 打印 nonce 值 + fmt.Printf("Nonce value: %d\n", nonce) + blockNumber := big.NewInt(37) balanceAt, err := client.BalanceAt(context.Background(), account, blockNumber) if err != nil { diff --git a/calculateContractAddress.go b/calculateContractAddress.go new file mode 100644 index 0000000..5c15363 --- /dev/null +++ b/calculateContractAddress.go @@ -0,0 +1,40 @@ +package main + +// 计算合约部署的地址 + +import ( + "fmt" + "log" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/rlp" +) + +// Keccak256 is a utility function to perform a Keccak-256 hash +func Keccak256(data []byte) []byte { + hash := crypto.Keccak256Hash(data) + return hash.Bytes() +} + +// CreateAddress generates an Ethereum contract address from an account address and nonce +func CreateAddress(b common.Address, nonce uint64) common.Address { + // RLP encode the account address and nonce + data, err := rlp.EncodeToBytes([]interface{}{b, nonce}) + if err != nil { + log.Fatalf("Failed to RLP encode: %v", err) + } + + // Perform Keccak256 hashing and take the last 20 bytes (160-bit address) + hash := Keccak256(data) + return common.BytesToAddress(hash[12:]) // Take the last 20 bytes +} + +func main() { + // Example usage + address := common.HexToAddress("f39fd6e51aad88f6f4ce6ab8827279cfffb92266") + nonce := uint64(29) // Example nonce + + contractAddress := CreateAddress(address, nonce) + fmt.Println("Contract Address:", contractAddress.Hex()) +} diff --git a/deployContract.go b/deployContract.go new file mode 100644 index 0000000..88ace88 --- /dev/null +++ b/deployContract.go @@ -0,0 +1,93 @@ +package main + +import ( + "bytes" + "context" + "crypto/ecdsa" + "fmt" + "log" + "math/big" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" +) + +// 合约字节码,假设你有已编译的合约字节码 +var contractBytecode = common.FromHex("608060405234801561001057600080fd5b5060405161013838038061013883398181016040528101906100329190610051565b8060009080519060200190610044929190610051565b50610119565b828054610058906100bd565b90600052602060002090601f01602090048101928261007a57600085556100c1565b82601f1061009357805160ff19168380011785556100c1565b828001600101855582156100c1579182015b828111156100c05782518255916020019190600101906100a5565b5b5090506100ce91906100d2565b5090565b5b808211156100eb5760008160009055506001016100d3565b5090565b600080fd5b6100ff61010e565b61010781610109565b50565b5b5600a165627a7a72305820f89cba2e7c907b4b08c263ff6ba7dd0fcf93871db44c930e5be435e8968c27a40029") // 一个简单的合约字节码 + +// Create2Address 根据创建者地址、盐值和合约字节码计算合约地址 +func Create2Address(deployer common.Address, salt [32]byte, bytecode []byte) common.Address { + // 将数据拼接 + data := append([]byte{0xff}, deployer.Bytes()...) // 0xff 常量 + data = append(data, salt[:]...) // 盐值 + data = append(data, crypto.Keccak256(bytecode)...) // 合约字节码的 keccak256 哈希值 + + // 计算 keccak256 并返回最后 20 字节(地址) + return common.BytesToAddress(crypto.Keccak256(data)[12:]) +} + +func main() { + // 创建以太坊客户端 + client, err := ethclient.Dial("http://localhost:8545") + if err != nil { + log.Fatalf("Failed to connect to the Ethereum client: %v", err) + } + + // 使用私钥生成一个新账户(用来部署合约) + privateKey, err := crypto.HexToECDSA("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80") + if err != nil { + log.Fatalf("Failed to generate key: %v", err) + } + publicKey := privateKey.Public() + publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) + if !ok { + log.Fatalf("Cannot cast public key to ECDSA") + } + fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA) + + // 设置部署合约时的盐值 + var salt [32]byte + copy(salt[:], []byte("my_salt_value")) + + // 计算合约地址 + contractAddress := Create2Address(fromAddress, salt, contractBytecode) + fmt.Println("Expected contract address:", contractAddress.Hex()) + + // 获取合约 ABI(在这个例子中我们使用一个空的 ABI) + parsedABI, err := abi.JSON(bytes.NewReader([]byte("[]"))) // 空的 ABI + if err != nil { + log.Fatalf("Failed to parse ABI: %v", err) + } + + // 获取合约部署者的 nonce + nonce, err := client.PendingNonceAt(context.Background(), fromAddress) + if err != nil { + log.Fatalf("Failed to get nonce: %v", err) + } + + // 设置 gasPrice 和 gasLimit + gasPrice, err := client.SuggestGasPrice(context.Background()) + if err != nil { + log.Fatalf("Failed to get gas price: %v", err) + } + + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1)) // 使用 Go-Ethereum 的 bind 包 + if err != nil { + log.Fatalf("Failed to create transactor: %v", err) + } + auth.Nonce = big.NewInt(int64(nonce)) + auth.Value = big.NewInt(0) // 部署合约无需发送 ETH + auth.GasLimit = uint64(3000000) // Gas limit + auth.GasPrice = gasPrice + + // 部署合约(使用 create2 部署) + tx, _, _, err := bind.DeployContract(auth, parsedABI, contractBytecode, client, salt[:]) + if err != nil { + log.Fatalf("Failed to deploy contract: %v", err) + } + + fmt.Printf("Contract deployed! tx hash: %s\n", tx.Hex()) +} diff --git a/deployToken.go b/deployToken.go new file mode 100644 index 0000000..9539969 --- /dev/null +++ b/deployToken.go @@ -0,0 +1,103 @@ +package main + +import ( + "context" + "crypto/ecdsa" + "fmt" + "log" + "math/big" + + "github.com/andOneBasketball/Test-Go-ETH/contracts/Token" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" +) + +func main() { + client, err := ethclient.Dial("http://127.0.0.1:8545/") + if err != nil { + log.Fatal(err) + } + + // 私钥初始化 + privateKey, err := crypto.HexToECDSA("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80") + if err != nil { + log.Fatal(err) + } + + // 公私钥账户地址转换 + publicKey := privateKey.Public() + publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) + if !ok { + log.Fatal("error casting public key to ECDSA") + } + fmt.Printf("publicKey is: %x\n", crypto.CompressPubkey(publicKeyECDSA)) + fmt.Printf("privateKey is: %x\n", crypto.FromECDSA(privateKey)) + + fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA) + fmt.Printf("address is: %x\n", fromAddress) + nonce, err := client.PendingNonceAt(context.Background(), fromAddress) + //nonce, err := client.NonceAt(context.Background(), fromAddress, big.NewInt(25)) + if err != nil { + log.Fatal(err) + } + log.Printf("nonce: %d\n", nonce) + + gasPrice, err := client.SuggestGasPrice(context.Background()) + if err != nil { + log.Fatal(err) + } + + auth := bind.NewKeyedTransactor(privateKey) + auth.Nonce = big.NewInt(int64(nonce)) + auth.Value = big.NewInt(0) // in wei + // auth.GasLimit = uint64(300000) // in units + auth.GasPrice = gasPrice + + //account := common.HexToAddress("0x5639Bc2D96c7bA37EECA625599B183241A2bBE6c") + address, tx, instance, err := Token.DeployToken(auth, client) + if err != nil { + log.Fatal(err) + } + fmt.Println("contract address: ", address.Hex()) + log.Printf("tx hash: %s", tx.Hash().Hex()) + log.Printf("chainID: %s", tx.ChainId()) + log.Printf("type: %d", tx.Type()) + log.Printf("gas limit: %d", tx.Gas()) + log.Printf("gas price: %d", tx.GasPrice()) + log.Printf("gas fee cap: %s", tx.GasFeeCap()) + log.Printf("gas tip cap: %s", tx.GasTipCap()) + + countAddress, err := instance.Counter(&bind.CallOpts{}) + if err != nil { + log.Fatal(err) + } + fmt.Printf("count address is: %s\n", countAddress.Hex()) // 0x0 + + // 需要重新获取 nonce 才能发交易 + nonce, err = client.PendingNonceAt(context.Background(), fromAddress) + if err != nil { + log.Fatal(err) + } + log.Printf("second nonce: %d\n", nonce) + auth.Nonce = big.NewInt(int64(nonce)) + + accountB := common.HexToAddress("0xde05927035b51C5f6dE27b427e4649123723e141") + tx, err = instance.Transfer(auth, accountB, big.NewInt(100)) + if err != nil { + log.Fatal("Transfer failed: ", err) + } + + balance, err := instance.BalanceOf(&bind.CallOpts{}, fromAddress) + if err != nil { + log.Fatal(err) + } + fmt.Printf("account %s balance is: %v\n", fromAddress.Hex(), balance) // 25893180161173005034 + + balance, err = instance.BalanceOf(&bind.CallOpts{}, accountB) + if err != nil { + log.Fatal(err) + } + fmt.Printf("accountB %s balance is: %v\n", accountB.Hex(), balance) // 25893180161173005034 +} diff --git a/getWalletAddress.go b/getWalletAddress.go new file mode 100644 index 0000000..f388865 --- /dev/null +++ b/getWalletAddress.go @@ -0,0 +1,37 @@ +package main + +import ( + "crypto/ecdsa" + "fmt" + "log" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + "golang.org/x/crypto/sha3" +) + +func main() { + privateKey, err := crypto.HexToECDSA("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80") + if err != nil { + log.Fatal(err) + } + + privateKeyBytes := crypto.FromECDSA(privateKey) + fmt.Println(hexutil.Encode(privateKeyBytes)[2:]) // ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + + publicKey := privateKey.Public() + publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) + if !ok { + log.Fatal("cannot assert type: publicKey is not of type *ecdsa.PublicKey") + } + + publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA) + fmt.Println(hexutil.Encode(publicKeyBytes)[4:]) // 8318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5 + + address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex() + fmt.Println(address) // 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 + + hash := sha3.NewLegacyKeccak256() + hash.Write(publicKeyBytes[1:]) + fmt.Println(hexutil.Encode(hash.Sum(nil)[12:])) // 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 +} diff --git a/go.mod b/go.mod index 6255db0..5e0a968 100644 --- a/go.mod +++ b/go.mod @@ -35,9 +35,9 @@ require ( github.com/supranational/blst v0.3.13 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect - golang.org/x/crypto v0.22.0 // indirect + golang.org/x/crypto v0.29.0 // indirect golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.22.0 // indirect + golang.org/x/sys v0.27.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 81775f0..401f7fa 100644 --- a/go.sum +++ b/go.sum @@ -174,6 +174,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -188,9 +190,12 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= diff --git a/monitorBlock.go b/monitorBlock.go new file mode 100644 index 0000000..3096f5c --- /dev/null +++ b/monitorBlock.go @@ -0,0 +1,67 @@ +package main + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" +) + +const Confirmations = 6 // 等待 6 个确认区块 + +func main() { + client, err := ethclient.Dial("https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID") + if err != nil { + log.Fatal(err) + } + + // 创建一个用于监听新区块的通道 + headers := make(chan *types.Header) + sub, err := client.SubscribeNewHead(context.Background(), headers) + if err != nil { + log.Fatal(err) + } + + // 缓存区块及其确认数 + blockCache := make(map[uint64]*types.Block) + + fmt.Println("Listening for new blocks...") + + for { + select { + case err := <-sub.Err(): + log.Fatal(err) + case header := <-headers: + block, err := client.BlockByHash(context.Background(), header.Hash()) + if err != nil { + log.Fatal(err) + } + + blockNumber := block.Number().Uint64() + fmt.Printf("New block received: %d\n", blockNumber) + + // 将新接收到的区块缓存 + blockCache[blockNumber] = block + + // 检查之前未确认的区块是否已经得到了6个确认 + for blockNumber, cachedBlock := range blockCache { + latestBlockNumber, err := client.BlockNumber(context.Background()) + if err != nil { + log.Fatal(err) + } + + if latestBlockNumber >= blockNumber+Confirmations { + // 该区块已确认6个区块,可以安全处理 + fmt.Printf("Block %d has been confirmed after 6 blocks\n", blockNumber) + // 在这里处理业务逻辑 + delete(blockCache, blockNumber) // 移除已处理的区块 + } + } + } + // 暂停短时间,以防止频繁查询最新区块号 + time.Sleep(time.Second * 2) + } +} diff --git a/queryUniswapTxInfo.go b/queryUniswapTxInfo.go new file mode 100644 index 0000000..ed93798 --- /dev/null +++ b/queryUniswapTxInfo.go @@ -0,0 +1,195 @@ +package main + +// 分析 Uniswap 交易对合约的事件日志和交易详情 + +import ( + "context" + "fmt" + "log" + "math/big" + "strings" + + "github.com/andOneBasketball/Test-Go-ETH/contracts/UniswapV2/UniswapV2Factory" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" +) + +const uniswapV2PairABI = `[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0Out","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1Out","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Swap","type":"event"}]` + +func main() { + // 连接到以太坊客户端(例如 Infura 或本地节点) + client, err := ethclient.Dial("https://eth-mainnet.g.alchemy.com/v2/hU4c850dMHnn1PfF2SRLLjtTps_kMmmG") + if err != nil { + log.Fatal(err) + } + + uniswapV2FactoryBlockBegin := int64(10000835) + uniswapV2FactoryAddress := common.HexToAddress("0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f") + uniswapV2FactoryInstance, err := UniswapV2Factory.NewUniswapV2Factory(uniswapV2FactoryAddress, client) + if err != nil { + log.Fatal(err) + } + + feeTo, err := uniswapV2FactoryInstance.FeeTo(&bind.CallOpts{}) + if err != nil { + log.Fatal("get feeTo failed, err: %v", err) + } + log.Printf("FeeTo: %s", feeTo.String()) + + feeToSetter, err := uniswapV2FactoryInstance.FeeToSetter(&bind.CallOpts{}) + if err != nil { + log.Fatal("get feeToSetter failed, err: %v", err) + } + log.Printf("FeeToSetter: %s", feeToSetter.String()) + + // 获取所有交易对地址 + allPairLength, err := uniswapV2FactoryInstance.AllPairsLength(&bind.CallOpts{}) + if err != nil { + log.Fatal(err) + } else { + log.Printf("All Pairs Length: %v", allPairLength.Int64()) + } + header, err := client.HeaderByNumber(context.Background(), nil) + if err != nil { + log.Fatal(err) + } + log.Printf("current block number is %d", header.Number.Uint64()) + + blockBatch := int64(2000) + addressBatch := int64(500) + j := int64(0) + k := int64(0) + addresses := make([]common.Address, allPairLength.Int64()) + for i := int64(0); i < allPairLength.Int64(); i++ { + pairAddress, err := uniswapV2FactoryInstance.AllPairs(&bind.CallOpts{}, big.NewInt(i)) + if err != nil { + log.Fatal(err) + continue + } + addresses[i] = pairAddress + + if i != 0 && i%addressBatch == 0 { + log.Printf("the %dth Pair Address: %s", i, pairAddress.String()) + for { + header, err := client.HeaderByNumber(context.Background(), nil) + if err != nil { + log.Fatal(err) + } + if uniswapV2FactoryBlockBegin+(k+1)*blockBatch > int64(header.Number.Uint64()) { + log.Printf("the current block number is %d", header.Number.Uint64()) + break + } + + beginBlock := uniswapV2FactoryBlockBegin + k*blockBatch + endBlock := uniswapV2FactoryBlockBegin + (k+1)*blockBatch + // log.Printf("begin find swap in block in %d to %d, the current block number is %d", beginBlock, endBlock, header.Number.Uint64()) + if k != 0 && k*blockBatch%3000000 == 0 { + log.Printf("begin find swap in block in %d to %d, the current block number is %d", beginBlock, endBlock, header.Number.Uint64()) + } + query := ethereum.FilterQuery{ + FromBlock: big.NewInt(beginBlock), // 指定uniswapV2Factory最早的区块为起始区块 + ToBlock: big.NewInt(endBlock), // 指定结束区块 + Addresses: addresses[j : j+addressBatch], + } + j += addressBatch + k++ + + // 获取事件日志 + logs, err := client.FilterLogs(context.Background(), query) + if err != nil { + log.Fatal(err) + } + + // 解析合约 ABI + contractAbi, err := abi.JSON(strings.NewReader(uniswapV2PairABI)) + if err != nil { + log.Fatal(err) + } + + for _, vLog := range logs { + fmt.Printf("Log Block Number: %v\n", vLog.BlockNumber) + fmt.Printf("Log Index: %v\n", vLog.Index) + + // 解析日志中的 Swap 事件 + var swapEvent struct { + Sender common.Address + Amount0In *big.Int + Amount1In *big.Int + Amount0Out *big.Int + Amount1Out *big.Int + To common.Address + } + + err := contractAbi.UnpackIntoInterface(&swapEvent, "Swap", vLog.Data) + if err != nil { + log.Fatal(err) + } + + fmt.Printf("Swap Event: %+v\n", swapEvent) + } + } + } + } + + /* + // 指定 Uniswap 交易对合约地址 + pairAddress := common.HexToAddress("0xE4610c983877480a50eeA0D53E313eDa423eC678") // 替换为实际的 Uniswap Pair 地址 + + // 创建查询参数 + query := ethereum.FilterQuery{ + FromBlock: big.NewInt(12345678), // 指定起始区块 + ToBlock: big.NewInt(12345688), // 指定结束区块 + Addresses: []common.Address{pairAddress}, + } + + // 获取事件日志 + logs, err := client.FilterLogs(context.Background(), query) + if err != nil { + log.Fatal(err) + } + + // 解析合约 ABI + contractAbi, err := abi.JSON(strings.NewReader(uniswapV2PairABI)) + if err != nil { + log.Fatal(err) + } + + for _, vLog := range logs { + fmt.Printf("Log Block Number: %v\n", vLog.BlockNumber) + fmt.Printf("Log Index: %v\n", vLog.Index) + + // 解析日志中的 Swap 事件 + var swapEvent struct { + Sender common.Address + Amount0In *big.Int + Amount1In *big.Int + Amount0Out *big.Int + Amount1Out *big.Int + To common.Address + } + + err := contractAbi.UnpackIntoInterface(&swapEvent, "Swap", vLog.Data) + if err != nil { + log.Fatal(err) + } + + fmt.Printf("Swap Event: %+v\n", swapEvent) + } + + // 根据交易哈希获取交易详情 + txHash := common.HexToHash("0xYourTxHash") // 替换为实际的交易哈希 + tx, isPending, err := client.TransactionByHash(context.Background(), txHash) + if err != nil { + log.Fatal(err) + } + + if isPending { + fmt.Println("Transaction is still pending") + } else { + fmt.Printf("Transaction details: %+v\n", tx) + } + */ +} diff --git a/signOpt.go b/signOpt.go new file mode 100644 index 0000000..9d91a85 --- /dev/null +++ b/signOpt.go @@ -0,0 +1,83 @@ +/* +ethereum.enable() +account = "0x5639Bc2D96c7bA37EECA625599B183241A2bBE6c" +message = "Hello, please sign this message to authenticate." +ethereum.request({method: "personal_sign", params: [account, message]}) +0x956fb26bf2700ef02b584c348d98bc6948ba09966e6841fe9fe08ed0cb1f0a02789c014bfe6e9d5f9827260f9d983c1c2b046fe69e03ab7d7880c21bc2c50dd11b +*/ + +package main + +import ( + "bytes" + "encoding/hex" + "fmt" + "log" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" +) + +func verifySignature(address string, message string, signature string) (bool, error) { + // Step 1: Format the message with Ethereum's prefix + prefixedMessage := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(message), message) + + // Step 2: Hash the prefixed message + messageHash := crypto.Keccak256([]byte(prefixedMessage)) + + // Step 3: Decode the signature + signatureBytes, err := hex.DecodeString(signature[2:]) // Remove "0x" prefix + if err != nil { + return false, fmt.Errorf("invalid signature format: %v", err) + } + if len(signatureBytes) != 65 { + return false, fmt.Errorf("invalid signature length") + } + + // Extract r, s, and v from the signature + //r := signatureBytes[:32] + //s := signatureBytes[32:64] + v := signatureBytes[64] + + // Adjust v value for recovery (27 or 28 are valid) + if v < 27 { + v += 27 + } + + // Append v back into the signature + fullSignature := append(signatureBytes[:64], v-27) // Remove 27 offset for go-ethereum + + // Step 4: Recover the public key + publicKey, err := crypto.SigToPub(messageHash, fullSignature) + if err != nil { + return false, fmt.Errorf("failed to recover public key: %v", err) + } + + // Step 5: Derive the address from the public key + recoveredAddress := crypto.PubkeyToAddress(*publicKey) + + // Step 6: Compare the recovered address with the expected address + log.Printf("address is %s", recoveredAddress.Hex()) + if bytes.Equal(recoveredAddress.Bytes(), common.HexToAddress(address).Bytes()) { + return true, nil + } + return false, fmt.Errorf("address mismatch: got %s, expected %s", recoveredAddress.Hex(), address) +} + +func main() { + // Example data + account := "0x5639Bc2D96c7bA37EECA625599B183241A2bBE6c" + message := "127.0.0.10x5639Bc2D96c7bA37EECA625599B183241A2bBE6cSign in to Anime Petitionlogin59144696942531731825448" + signature := "0xc43b720062b2db3b20204ddb07ecdfc384e7814d31b7351256f4261c7d311eec7588aaa708ae5cc80e9c024b9ace24b522f9f90e6675e0455fc1c96c6efa37e51c" + + // Verify the signature + valid, err := verifySignature(account, message, signature) + if err != nil { + log.Fatalf("Error verifying signature: %v", err) + } + if valid { + fmt.Println("Signature is valid!") + } else { + fmt.Println("Signature is invalid!") + } +} diff --git a/wordGenerationAccount.go b/wordGenerationAccount.go index 47e9dc8..80de33a 100644 --- a/wordGenerationAccount.go +++ b/wordGenerationAccount.go @@ -19,7 +19,7 @@ import ( func main() { // 助记词存在12(128位熵、主流)、15(160)、18(192)、21(224)、24(256位熵、安全性最强)个单词 // 生成 BIP-39 助记词 - entropy, err := bip39.NewEntropy(128) // 128位熵,生成12个单词的助记词 + entropy, err := bip39.NewEntropy(256) // 128位熵,生成12个单词的助记词 if err != nil { log.Fatal(err) }