如何在golang中运行abi.encodePacked?
在稳固性方面,我使用keccak256(abi.encodePacked(a, b))
来计算参数的签名。
这是我的合同。
pragma solidity ^0.4.24;
import "openzeppelin-solidity/contracts/ECRecovery.sol";
contract MyContract {
using ECRecovery for bytes32;
address permittedSinger;
function doSomething(
bytes32 id, uint256 amount, bytes sig
) {
bytes32 hash = getHash(msg.sender, id, amount);
address msgSigner = hash.recover(sig);
require(msgSigner == permittedSinger);
}
function getMsgSigner(bytes32 proveHash, bytes sig) public pure returns (address) {
return proveHash.recover(sig);
}
function getHash(
address receiver, bytes32 id, uint256 amount
) pure returns (bytes32) {
return keccak256(abi.encodePacked(receiver, id, amount));
}
}
答案 0 :(得分:2)
终于我成功了。 :)
package main
import (
"math/big"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/accounts/abi"
"log"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto/sha3"
)
func main() {
uint256Ty, _ := abi.NewType("uint256")
bytes32Ty, _ := abi.NewType("bytes32")
addressTy, _ := abi.NewType("address")
arguments := abi.Arguments{
{
Type: addressTy,
},
{
Type: bytes32Ty,
},
{
Type: uint256Ty,
},
}
bytes, _ := arguments.Pack(
common.HexToAddress("0x0000000000000000000000000000000000000000"),
[32]byte{'I','D','1'},
big.NewInt(42),
)
var buf []byte
hash := sha3.NewKeccak256()
hash.Write(bytes)
buf = hash.Sum(buf)
log.Println(hexutil.Encode(buf))
// output:
// 0x1f214438d7c061ad56f98540db9a082d372df1ba9a3c96367f0103aa16c2fe9a
}
答案 1 :(得分:1)
在对已接受答案的评论中说Jakub N
时,Go's arguments.Pack
返回为abi.encode
而不是abi.encodePacked
。在您的情况下,这是可行的,因为所有打包的值都是32个字节,但是如果您还添加一些字符串,则结果将有所不同。
这里是如何使其与与abi.encodePacked
对应的紧密打包编码兼容的方法:
// hash of packed byte array with arguments
hash := crypto.Keccak256Hash(
common.HexToAddress("0x0000000000000000000000000000000000000000").Bytes(),
[32]byte{'I','D','1'},
common.LeftPadBytes(big.NewInt(42).Bytes(), 32),
[]byte("Some other string value"),
)
// normally we sign prefixed hash
// as in solidity with `ECDSA.toEthSignedMessageHash`
prefixedHash := crypto.Keccak256Hash(
[]byte(fmt.Sprintf("\x19Ethereum Signed Message:\n%v", len(hash))),
hash.Bytes(),
)
// sign hash to validate later in Solidity
sig, err := crypto.Sign(prefixedHash.Bytes(), privateKey)
它也更加高效,因为我们不为此打包和分配额外的内存。散列函数会迭代现有值。