StateDB ZKInputs generation compatible with circom

- Add SignatureConstant to L1Tx.TxCompressedData
- ZKInputs generation works initial version working and compatible with circom Hermez circuit
    - Lots of small updates for circuits compatibility
- Update version (with new changes) of `go-iden3-crypto` & `go-merkletree`
This commit is contained in:
arnaucube
2020-12-01 22:15:19 +01:00
parent d306f4890a
commit 80cbac24f9
13 changed files with 187 additions and 105 deletions

View File

@@ -167,8 +167,9 @@ func (tx L1Tx) TxCompressedData() (*big.Int, error) {
if err != nil {
return nil, tracerr.Wrap(err)
}
var b [31]byte
// b[0:7] empty: no fee neither nonce
// b[0:7] empty: no ToBJJSign, no fee, no nonce
copy(b[7:11], tx.TokenID.Bytes())
copy(b[11:13], amountFloat16.Bytes())
toIdxBytes, err := tx.ToIdx.Bytes()
@@ -181,8 +182,8 @@ func (tx L1Tx) TxCompressedData() (*big.Int, error) {
return nil, tracerr.Wrap(err)
}
copy(b[19:25], fromIdxBytes[:])
copy(b[25:27], []byte{0, 1}) // TODO this will be generated by the ChainID config parameter
// b[27:] empty: no signature
copy(b[25:27], []byte{0, 0}) // TODO this will be generated by the ChainID config parameter
copy(b[27:31], SignatureConstantBytes[:])
bi := new(big.Int).SetBytes(b[:])
return bi, nil

View File

@@ -60,9 +60,9 @@ func TestL1TxCompressedData(t *testing.T) {
assert.Nil(t, err)
// test vector value generated from javascript implementation
expectedStr := "7307597389635308713748674793997299267460566876160"
expectedStr := "7307597389635308713748674793997299267459594577423"
assert.Equal(t, expectedStr, txCompressedData.String())
assert.Equal(t, "050004000000000003000000000002000100000000", hex.EncodeToString(txCompressedData.Bytes()))
assert.Equal(t, "0500040000000000030000000000020000c60be60f", hex.EncodeToString(txCompressedData.Bytes()))
}
func TestBytesDataAvailability(t *testing.T) {

View File

@@ -107,12 +107,6 @@ func NewPoolL2Tx(poolL2Tx *PoolL2Tx) (*PoolL2Tx, error) {
// [ 32 bits ] signatureConstant // 4 bytes
// Total bits compressed data: 241 bits // 31 bytes in *big.Int representation
func (tx *PoolL2Tx) TxCompressedData() (*big.Int, error) {
// sigconstant
sc, ok := new(big.Int).SetString("3322668559", 10)
if !ok {
return nil, tracerr.Wrap(fmt.Errorf("error parsing SignatureConstant"))
}
amountFloat16, err := NewFloat16(tx.Amount)
if err != nil {
return nil, tracerr.Wrap(err)
@@ -141,8 +135,8 @@ func (tx *PoolL2Tx) TxCompressedData() (*big.Int, error) {
return nil, tracerr.Wrap(err)
}
copy(b[19:25], fromIdxBytes[:])
copy(b[25:27], []byte{0, 1}) // TODO this will be generated by the ChainID config parameter
copy(b[27:31], sc.Bytes())
copy(b[25:27], []byte{0, 0}) // TODO this will be generated by the ChainID config parameter
copy(b[27:31], SignatureConstantBytes[:])
bi := new(big.Int).SetBytes(b[:])
return bi, nil

View File

@@ -38,9 +38,9 @@ func TestTxCompressedData(t *testing.T) {
txCompressedData, err := tx.TxCompressedData()
assert.Nil(t, err)
// test vector value generated from javascript implementation
expectedStr := "1766847064778421992193717128424891165872736891548909569553540449389241871"
expectedStr := "1766847064778421992193717128424891165872736891548909569553540445094274575"
assert.Equal(t, expectedStr, txCompressedData.String())
assert.Equal(t, "010000000000060000000500040000000000030000000000020001c60be60f", hex.EncodeToString(txCompressedData.Bytes()))
assert.Equal(t, "010000000000060000000500040000000000030000000000020000c60be60f", hex.EncodeToString(txCompressedData.Bytes()))
tx = PoolL2Tx{
RqFromIdx: 7,
RqToIdx: 8,
@@ -112,18 +112,16 @@ func TestHashToSign(t *testing.T) {
_, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
assert.Nil(t, err)
tx := PoolL2Tx{
FromIdx: 2,
ToIdx: 3,
Amount: big.NewInt(4),
TokenID: 5,
Nonce: 6,
ToBJJ: sk.Public(),
RqToEthAddr: ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"),
RqToBJJ: sk.Public(),
FromIdx: 2,
ToIdx: 3,
Amount: big.NewInt(4),
TokenID: 5,
Nonce: 6,
ToEthAddr: ethCommon.HexToAddress("0xc58d29fA6e86E4FAe04DDcEd660d45BCf3Cb2370"),
}
toSign, err := tx.HashToSign()
assert.Nil(t, err)
assert.Equal(t, "13412877307445712067533842795279849753265998687662992184595695642580679868064", toSign.String())
assert.Equal(t, "1469900657138253851938022936440971384682713995864967090251961124784132925291", toSign.String())
}
func TestVerifyTxSignature(t *testing.T) {
@@ -142,7 +140,7 @@ func TestVerifyTxSignature(t *testing.T) {
}
toSign, err := tx.HashToSign()
assert.Nil(t, err)
assert.Equal(t, "13412877307445712067533842795279849753265998687662992184595695642580679868064", toSign.String())
assert.Equal(t, "18645218094210271622244722988708640202588315450486586312909439859037906375295", toSign.String())
sig := sk.SignPoseidon(toSign)
tx.Signature = sig.Compress()

View File

@@ -34,6 +34,13 @@ const (
TxIDLen = 12
)
var (
// SignatureConstantBytes contains the SignatureConstant in byte array
// format, which is equivalent to 3322668559 as uint32 in byte array in
// big endian representation.
SignatureConstantBytes = []byte{198, 11, 230, 15}
)
// TxID is the identifier of a Hermez network transaction
type TxID [TxIDLen]byte

View File

@@ -3,11 +3,21 @@ package common
import (
"database/sql"
"database/sql/driver"
"encoding/binary"
"encoding/hex"
"testing"
"github.com/stretchr/testify/assert"
)
func TestSignatureConstant(t *testing.T) {
signatureConstant := uint32(3322668559)
var signatureConstantBytes [4]byte
binary.BigEndian.PutUint32(signatureConstantBytes[:], signatureConstant)
assert.Equal(t, SignatureConstantBytes, signatureConstantBytes[:])
assert.Equal(t, "c60be60f", hex.EncodeToString(SignatureConstantBytes))
}
func TestTxIDScannerValue(t *testing.T) {
txid0 := &TxID{}
txid1 := &TxID{}

View File

@@ -58,14 +58,16 @@ type ZKInputs struct {
OldLastIdx *big.Int `json:"oldLastIdx"` // uint64 (max nLevels bits)
// OldStateRoot is the current state merkle tree root
OldStateRoot *big.Int `json:"oldStateRoot"` // Hash
// GlobalChainID is the blockchain ID (0 for Ethereum mainnet). This value can be get from the smart contract.
// GlobalChainID is the blockchain ID (0 for Ethereum mainnet). This
// value can be get from the smart contract.
GlobalChainID *big.Int `json:"globalChainID"` // uint16
// FeeIdxs is an array of merkle tree indexes where the coordinator will receive the accumulated fees
// FeeIdxs is an array of merkle tree indexes where the coordinator
// will receive the accumulated fees
FeeIdxs []*big.Int `json:"feeIdxs"` // uint64 (max nLevels bits), len: [maxFeeIdxs]
// accumulate fees
// FeePlanTokens contains all the tokenIDs for which the fees are being accumulated
FeePlanTokens []*big.Int `json:"feePlanTokens"` // uint32 (max 32 bits), len: [maxFeeIdxs]
FeePlanTokens []*big.Int `json:"feePlanTokens"` // uint32 (max nLevels bits), len: [maxFeeIdxs]
//
// Txs (L1&L2)
@@ -87,7 +89,9 @@ type ZKInputs struct {
// ToIdx
ToIdx []*big.Int `json:"toIdx"` // uint64 (max nLevels bits), len: [nTx]
// AuxToIdx is the Idx of the Tx that has 'toIdx==0', is the coordinator who will find which Idx corresponds to the 'toBJJAy' or 'toEthAddr'
// AuxToIdx is the Idx of the Tx that has 'toIdx==0', is the
// coordinator who will find which Idx corresponds to the 'toBJJAy' or
// 'toEthAddr'
AuxToIdx []*big.Int `json:"auxToIdx"` // uint64 (max nLevels bits), len: [nTx]
// ToBJJAy
ToBJJAy []*big.Int `json:"toBjjAy"` // big.Int, len: [nTx]
@@ -136,7 +140,9 @@ type ZKInputs struct {
// State MerkleTree Leafs transitions
//
// state 1, value of the sender (from) account leaf
// state 1, value of the sender (from) account leaf. The values at the
// moment pre-smtprocessor of the update (before updating the Sender
// leaf).
TokenID1 []*big.Int `json:"tokenID1"` // uint32, len: [nTx]
Nonce1 []*big.Int `json:"nonce1"` // uint64 (max 40 bits), len: [nTx]
Sign1 []*big.Int `json:"sign1"` // bool, len: [nTx]