mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 03:16:45 +01:00
Merge pull request #72 from hermeznetwork/feature/pooll2tx-sig
Add PoolL2Tx verify signature needed methods
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
|||||||
eth "github.com/ethereum/go-ethereum/common"
|
eth "github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/hermeznetwork/hermez-node/utils"
|
"github.com/hermeznetwork/hermez-node/utils"
|
||||||
"github.com/iden3/go-iden3-crypto/babyjub"
|
"github.com/iden3/go-iden3-crypto/babyjub"
|
||||||
|
"github.com/iden3/go-iden3-crypto/poseidon"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Nonce represents the nonce value in a uint64, which has the method Bytes that returns a byte array of length 5 (40 bits).
|
// Nonce represents the nonce value in a uint64, which has the method Bytes that returns a byte array of length 5 (40 bits).
|
||||||
@@ -46,7 +47,7 @@ type PoolL2Tx struct {
|
|||||||
Fee FeeSelector `meddler:"fee"`
|
Fee FeeSelector `meddler:"fee"`
|
||||||
Nonce Nonce `meddler:"nonce"` // effective 40 bits used
|
Nonce Nonce `meddler:"nonce"` // effective 40 bits used
|
||||||
State PoolL2TxState `meddler:"state"`
|
State PoolL2TxState `meddler:"state"`
|
||||||
Signature babyjub.Signature `meddler:"signature"` // tx signature
|
Signature *babyjub.Signature `meddler:"signature"` // tx signature
|
||||||
Timestamp time.Time `meddler:"timestamp,utctime"` // time when added to the tx pool
|
Timestamp time.Time `meddler:"timestamp,utctime"` // time when added to the tx pool
|
||||||
// Stored in DB: optional fileds, may be uninitialized
|
// Stored in DB: optional fileds, may be uninitialized
|
||||||
BatchNum BatchNum `meddler:"batch_num,zeroisnull"` // batchNum in which this tx was forged. Presence indicates "forged" state.
|
BatchNum BatchNum `meddler:"batch_num,zeroisnull"` // batchNum in which this tx was forged. Presence indicates "forged" state.
|
||||||
@@ -145,6 +146,31 @@ func (tx *PoolL2Tx) TxCompressedDataV2() (*big.Int, error) {
|
|||||||
return bi, nil
|
return bi, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HashToSign returns the computed Poseidon hash from the *PoolL2Tx that will be signed by the sender.
|
||||||
|
func (tx *PoolL2Tx) HashToSign() (*big.Int, error) {
|
||||||
|
toCompressedData, err := tx.TxCompressedData()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
toEthAddr := EthAddrToBigInt(tx.ToEthAddr)
|
||||||
|
toBjjAy := tx.ToBJJ.Y
|
||||||
|
rqTxCompressedDataV2, err := tx.TxCompressedDataV2()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return poseidon.Hash([]*big.Int{toCompressedData, toEthAddr, toBjjAy, rqTxCompressedDataV2, EthAddrToBigInt(tx.RqToEthAddr), tx.RqToBJJ.Y})
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifySignature returns true if the signature verification is correct for the given PublicKey
|
||||||
|
func (tx *PoolL2Tx) VerifySignature(pk *babyjub.PublicKey) bool {
|
||||||
|
h, err := tx.HashToSign()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return pk.VerifyPoseidon(h, tx.Signature)
|
||||||
|
}
|
||||||
|
|
||||||
func (tx *PoolL2Tx) Tx() *Tx {
|
func (tx *PoolL2Tx) Tx() *Tx {
|
||||||
return &Tx{
|
return &Tx{
|
||||||
TxID: tx.TxID,
|
TxID: tx.TxID,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
ethCommon "github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/iden3/go-iden3-crypto/babyjub"
|
"github.com/iden3/go-iden3-crypto/babyjub"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@@ -73,3 +74,49 @@ func TestTxCompressedData(t *testing.T) {
|
|||||||
assert.Equal(t, "10c000000000b0000000a0009000000000008000000000007", hex.EncodeToString(txCompressedData.Bytes())[1:])
|
assert.Equal(t, "10c000000000b0000000a0009000000000008000000000007", hex.EncodeToString(txCompressedData.Bytes())[1:])
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHashToSign(t *testing.T) {
|
||||||
|
var sk babyjub.PrivateKey
|
||||||
|
_, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
ethAddr := ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370")
|
||||||
|
|
||||||
|
tx := PoolL2Tx{
|
||||||
|
FromIdx: 2,
|
||||||
|
ToIdx: 3,
|
||||||
|
Amount: big.NewInt(4),
|
||||||
|
TokenID: 5,
|
||||||
|
Nonce: 6,
|
||||||
|
ToBJJ: sk.Public(),
|
||||||
|
RqToEthAddr: ethAddr,
|
||||||
|
RqToBJJ: sk.Public(),
|
||||||
|
}
|
||||||
|
toSign, err := tx.HashToSign()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, "14526446928649310956370997581245770629723313742905751117262272426489782809503", toSign.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVerifyTxSignature(t *testing.T) {
|
||||||
|
var sk babyjub.PrivateKey
|
||||||
|
_, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
|
||||||
|
assert.Nil(t, err)
|
||||||
|
ethAddr := ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370")
|
||||||
|
|
||||||
|
tx := PoolL2Tx{
|
||||||
|
FromIdx: 2,
|
||||||
|
ToIdx: 3,
|
||||||
|
Amount: big.NewInt(4),
|
||||||
|
TokenID: 5,
|
||||||
|
Nonce: 6,
|
||||||
|
ToBJJ: sk.Public(),
|
||||||
|
RqToEthAddr: ethAddr,
|
||||||
|
RqToBJJ: sk.Public(),
|
||||||
|
}
|
||||||
|
toSign, err := tx.HashToSign()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, "14526446928649310956370997581245770629723313742905751117262272426489782809503", toSign.String())
|
||||||
|
|
||||||
|
sig := sk.SignPoseidon(toSign)
|
||||||
|
tx.Signature = sig
|
||||||
|
assert.True(t, tx.VerifySignature(sk.Public()))
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
ethCommon "github.com/ethereum/go-ethereum/common"
|
||||||
|
)
|
||||||
|
|
||||||
// SwapEndianness swaps the order of the bytes in the slice.
|
// SwapEndianness swaps the order of the bytes in the slice.
|
||||||
func SwapEndianness(b []byte) []byte {
|
func SwapEndianness(b []byte) []byte {
|
||||||
o := make([]byte, len(b))
|
o := make([]byte, len(b))
|
||||||
@@ -8,3 +14,8 @@ func SwapEndianness(b []byte) []byte {
|
|||||||
}
|
}
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EthAddrToBigInt returns a *big.Int from a given ethereum common.Address.
|
||||||
|
func EthAddrToBigInt(a ethCommon.Address) *big.Int {
|
||||||
|
return new(big.Int).SetBytes(a.Bytes())
|
||||||
|
}
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ func genTxs(n int) []*common.PoolL2Tx {
|
|||||||
Fee: 99,
|
Fee: 99,
|
||||||
Nonce: 28,
|
Nonce: 28,
|
||||||
State: state,
|
State: state,
|
||||||
Signature: *privK.SignPoseidon(big.NewInt(674238462)),
|
Signature: privK.SignPoseidon(big.NewInt(674238462)),
|
||||||
Timestamp: time.Now().UTC(),
|
Timestamp: time.Now().UTC(),
|
||||||
}
|
}
|
||||||
if i%2 == 0 { // Optional parameters: rq
|
if i%2 == 0 { // Optional parameters: rq
|
||||||
|
|||||||
Reference in New Issue
Block a user