http://www.7klian.com

以太坊生意业务签名理会源码解读

    sig[64] = V //①
    if Vb.BitLen() > 8 {
    V.Sub(V, big8)
types.Sender要领中焦点挪用了EIP155签名器的Sender要领,其源码如下。
    “fmt”
    if tx.ChainId().Cmp(s.chainId) != 0 {//②
func main() {
    fmt.Println(“sig: “, common.Bytes2Hex(sig))
二、签名理会
    }
    // 还原生意业务工具
recoverPlain源码如下所示。
    pub, err := crypto.Ecrecover(sighash[:], sig) //②

上篇文章《生意业务签名进程源码理会[1]》从源码角度阐明白一个合约挪用的的签名进程,签名后的生意业务发送到以太坊节点后,节点需要从签名生意业务中还原出公钥(从公钥中单向计较出账号地点),进而将生意业务放入生意业务池中。本文从go-ethereum源码的出发,看看如何从签名生意业务中还原出公钥。
•①,按照R、S、V拼接获得的sign,hex值为:41c4a2eb073e6df89c3f467b3516e9c313590d8d57f7c217fe7e72a7b4a6b8ed5f20a758396a5e681ce1ab4cec749f8560e28c9eb91072ec7a8acc002a11bb1d00
    }
)
•encodedTxStr是上篇文章获得的具有签名的生意业务工具的rlp编码
    copy(sig[64-len(s):64], s)
•最终还原获得的from值为0xA2088F51Ea1f9BA308F5014150961e5a6E0A4E13,正是签名私钥对应的账号地点(私钥单向生成公钥,公钥单向生成地点)
•③按照V的计较要领还原recid为27(37-1*2-8),在recoverPlain要了解凭据homestead签名方法继承理会签名。
    fmt.Println(“from: “, from.Hex())
•bool范例的homestead,值为true
    r, s := R.Bytes(), S.Bytes()
    // encode the signature in uncompressed format
    jsonTx, _ := tx.MarshalJSON()
    “github.com/ethereum/go-ethereum/core/types”
    “github.com/ethereum/go-ethereum/rlp”
    fmt.Println(“pub: “, common.Bytes2Hex(pub))
        return HomesteadSigner{}.Sender(tx)
    sig := make([]byte, crypto.SignatureLength)
•R,,hex值为41c4a2eb073e6df89c3f467b3516e9c313590d8d57f7c217fe7e72a7b4a6b8ed
}
•②接着判定了生意业务中的链ID与签名器的链ID是否一致,假如纷歧致则返回清闲点
    if err != nil {
    if len(pub) == 0 || pub[0] != 4 {
// go-ethereum/core/types/transaction_signing.go
我们利用上文中最后获得的签名生意业务串来举办理会,这里我写的理会代码如下所示。
个中:
        return
    fmt.Println(“tx: “, string(jsonTx))
    }
    copy(sig[32-len(r):32], r)
    if !tx.Protected() {//①
    // rlp解码
    “github.com/ethereum/go-ethereum/common/hexutil”
    signer := types.NewEIP155Signer(big.NewInt(1))
    }
    }
    V := byte(Vb.Uint64() – 27)
一、筹备事情
•①首先判定了生意业务是否是受掩护的(是否是EIP155签名器举办的签名),假如不是,则利用HomesteadSigner签名器校验
    // 利用签名器从已签名的生意业务中还原账户公钥
    return addr, nil
}
    if !crypto.ValidateSignatureValues(V, R, S, homestead) {
•sighash是生意业务工具tx的rlp编码,hex值为0x9ef7f101dae55081553998d52d0ce57c4cf37271f800b70c0863c4a749977ef1,与我们上文中需要签名的生意业务hash是一致的。
        fmt.Println(“rlp.DecodeBytes failed: “, err.Error())
    var addr common.Address
    tx := new(types.Transaction)
    }
References
    }
        return common.Address{}, ErrInvalidSig
•③,按照公钥计较账号地点,取公钥pub第一位之后的值计较Keccak256,然后在取后12位今后,获得的账号地点为:0xA2088F51Ea1f9BA308F5014150961e5a6E0A4E13
    “math/big”
    }
[1]
以太坊生意业务签名进程源码理会: https://learnblockchain.cn/article/1225

        return common.Address{}, ErrInvalidSig
        fmt.Println(“hexutil.Decode failed: “, err.Error())
    //③
func (s EIP155Signer) Sender(tx *Transaction) (common.Address, error) {
        return common.Address{}, errors.New(“invalid public key”)
    copy(addr[:], crypto.Keccak256(pub[1:])[12:])//③
        return
•Vb,十进制值为27
至此,我们已经从签名中还原出了账号地点(公钥)。假如需要校验签名是否正确,可以通过挪用secp256k1包中的VerifySignature要领,传入公钥、生意业务hash和签名,通过比对R值是否一致举办验证。
}
    // chainId为1的EIP155签名器
在recoverPlain要领中:
    // recover the public key from the signature
func recoverPlain(sighash common.Hash, R, S, Vb *big.Int, homestead bool) (common.Address, error) {
    if err != nil {
    return recoverPlain(s.Hash(tx), tx.data.R, tx.data.S, V, true)
    }
Sender要领中:
// go-ethereum/core/types/transaction_signing.go
•②,挪用加密包中的Ecrecover要领按照签名还原公钥,该要了解挪用secp256k1包中的RecoverPubkey要领。还原获得的公钥hex值为045762d11bad6617b5eef31fefd6aff1391dab0a2380817eaf882874b1d50823b13e4934f923f4b7e6a3d19219e92a04678a8fb7029c2ecf7256672b57a6cb77b0 。
    encodedTxStr := “0xf889188504a817c800832dc6c09405e56888360ae54acf2a389bab39bd41e3934d2b80a4ee919d50000000000000000000000000000000000000000000000000000000000000007b25a041c4a2eb073e6df89c3f467b3516e9c313590d8d57f7c217fe7e72a7b4a6b8eda05f20a758396a5e681ce1ab4cec749f8560e28c9eb91072ec7a8acc002a11bb1d”
        return common.Address{}, err
    if err != nil {
•S hex值为5f20a758396a5e681ce1ab4cec749f8560e28c9eb91072ec7a8acc002a11bb1d
    from, err := types.Sender(signer, tx)
        return
个中recoverPlain要领的参数别离为:
    V := new(big.Int).Sub(tx.data.V, s.chainIdMul)
    if err := rlp.DecodeBytes(encodedTx, tx); err != nil {
import (
        return common.Address{}, ErrInvalidChainId
        fmt.Println(“types.Sender: “, err.Error())
package main
    encodedTx, err := hexutil.Decode(encodedTxStr)
•签名理会焦点利用的是Sender要领

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

相关文章阅读