mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 03:16:45 +01:00
Update Common & StateDB & ZKInputs to last protocol version
- Add InvalidData flag to L1Tx
- Add BytesDataAvailability to L1Tx
- Update ZKInputs & HashGlobalInputs to last spec of the protocol
(massive migrations)
- TxProcessor check correctness of L1Txs
Compatible with hermeznetwork/commonjs v0.0.4
(c345239bba)
This commit is contained in:
@@ -36,6 +36,11 @@ func (bn BatchNum) Bytes() []byte {
|
||||
return batchNumBytes[:]
|
||||
}
|
||||
|
||||
// BigInt returns a *big.Int representing the BatchNum
|
||||
func (bn BatchNum) BigInt() *big.Int {
|
||||
return big.NewInt(int64(bn))
|
||||
}
|
||||
|
||||
// BatchNumFromBytes returns BatchNum from a []byte
|
||||
func BatchNumFromBytes(b []byte) (BatchNum, error) {
|
||||
if len(b) != batchNumBytesLen {
|
||||
|
||||
@@ -37,10 +37,14 @@ type L1Tx struct {
|
||||
ToIdx Idx `meddler:"to_idx"` // ToIdx is ignored in L1Tx/Deposit, but used in the L1Tx/DepositAndTransfer
|
||||
TokenID TokenID `meddler:"token_id"`
|
||||
Amount *big.Int `meddler:"amount,bigint"`
|
||||
LoadAmount *big.Int `meddler:"load_amount,bigint"`
|
||||
EthBlockNum int64 `meddler:"eth_block_num"` // Ethereum Block Number in which this L1Tx was added to the queue
|
||||
Type TxType `meddler:"type"`
|
||||
BatchNum *BatchNum `meddler:"batch_num"`
|
||||
// EffectiveAmount only applies to L1UserTx.
|
||||
EffectiveAmount *big.Int `meddler:"effective_amount,bigintnull"`
|
||||
LoadAmount *big.Int `meddler:"load_amount,bigint"`
|
||||
// EffectiveLoadAmount only applies to L1UserTx.
|
||||
EffectiveLoadAmount *big.Int `meddler:"effective_load_amount,bigintnull"`
|
||||
EthBlockNum int64 `meddler:"eth_block_num"` // Ethereum Block Number in which this L1Tx was added to the queue
|
||||
Type TxType `meddler:"type"`
|
||||
BatchNum *BatchNum `meddler:"batch_num"`
|
||||
}
|
||||
|
||||
// NewL1Tx returns the given L1Tx with the TxId & Type parameters calculated
|
||||
@@ -117,7 +121,7 @@ func (tx *L1Tx) CalcTxID() (*TxID, error) {
|
||||
|
||||
// Tx returns a *Tx from the L1Tx
|
||||
func (tx L1Tx) Tx() Tx {
|
||||
f := new(big.Float).SetInt(tx.Amount)
|
||||
f := new(big.Float).SetInt(tx.EffectiveAmount)
|
||||
amountFloat, _ := f.Float64()
|
||||
userOrigin := new(bool)
|
||||
*userOrigin = tx.UserOrigin
|
||||
@@ -128,14 +132,14 @@ func (tx L1Tx) Tx() Tx {
|
||||
Position: tx.Position,
|
||||
FromIdx: tx.FromIdx,
|
||||
ToIdx: tx.ToIdx,
|
||||
Amount: tx.Amount,
|
||||
Amount: tx.EffectiveAmount,
|
||||
AmountFloat: amountFloat,
|
||||
TokenID: tx.TokenID,
|
||||
ToForgeL1TxsNum: tx.ToForgeL1TxsNum,
|
||||
UserOrigin: userOrigin,
|
||||
FromEthAddr: tx.FromEthAddr,
|
||||
FromBJJ: tx.FromBJJ,
|
||||
LoadAmount: tx.LoadAmount,
|
||||
LoadAmount: tx.EffectiveLoadAmount,
|
||||
EthBlockNum: tx.EthBlockNum,
|
||||
}
|
||||
if tx.LoadAmount != nil {
|
||||
@@ -183,6 +187,34 @@ func (tx L1Tx) TxCompressedData() (*big.Int, error) {
|
||||
return bi, nil
|
||||
}
|
||||
|
||||
// BytesDataAvailability encodes a L1Tx into []byte for the Data Availability
|
||||
func (tx *L1Tx) BytesDataAvailability(nLevels uint32) ([]byte, error) {
|
||||
idxLen := nLevels / 8 //nolint:gomnd
|
||||
|
||||
b := make([]byte, ((nLevels*2)+16+8)/8) //nolint:gomnd
|
||||
|
||||
fromIdxBytes, err := tx.FromIdx.Bytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(b[0:idxLen], fromIdxBytes[6-idxLen:])
|
||||
toIdxBytes, err := tx.ToIdx.Bytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(b[idxLen:idxLen*2], toIdxBytes[6-idxLen:])
|
||||
|
||||
if tx.EffectiveAmount != nil {
|
||||
amountFloat16, err := NewFloat16(tx.EffectiveAmount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(b[idxLen*2:idxLen*2+2], amountFloat16.Bytes())
|
||||
}
|
||||
// fee = 0 (as is L1Tx) b[10:11]
|
||||
return b[:], nil
|
||||
}
|
||||
|
||||
// BytesGeneric returns the generic representation of a L1Tx. This method is
|
||||
// used to compute the []byte representation of a L1UserTx, and also to compute
|
||||
// the L1TxData for the ZKInputs (at the HashGlobalInputs), using this method
|
||||
|
||||
@@ -65,6 +65,28 @@ func TestL1TxCompressedData(t *testing.T) {
|
||||
assert.Equal(t, "050004000000000003000000000002000100000000", hex.EncodeToString(txCompressedData.Bytes()))
|
||||
}
|
||||
|
||||
func TestBytesDataAvailability(t *testing.T) {
|
||||
tx := L1Tx{
|
||||
FromIdx: 2,
|
||||
ToIdx: 3,
|
||||
Amount: big.NewInt(4),
|
||||
TokenID: 5,
|
||||
}
|
||||
txCompressedData, err := tx.BytesDataAvailability(32)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "0000000200000003000000", hex.EncodeToString(txCompressedData))
|
||||
|
||||
tx = L1Tx{
|
||||
FromIdx: 2,
|
||||
ToIdx: 3,
|
||||
EffectiveAmount: big.NewInt(4),
|
||||
TokenID: 5,
|
||||
}
|
||||
txCompressedData, err = tx.BytesDataAvailability(32)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "0000000200000003000400", hex.EncodeToString(txCompressedData))
|
||||
}
|
||||
|
||||
func TestL1userTxByteParsers(t *testing.T) {
|
||||
var pkComp babyjub.PublicKeyComp
|
||||
pkCompL := []byte("0x56ca90f80d7c374ae7485e9bcc47d4ac399460948da6aeeb899311097925a72c")
|
||||
|
||||
@@ -103,8 +103,8 @@ func L2TxsToPoolL2Txs(txs []L2Tx) []PoolL2Tx {
|
||||
return r
|
||||
}
|
||||
|
||||
// Bytes encodes a L2Tx into []byte
|
||||
func (tx L2Tx) Bytes(nLevels uint32) ([]byte, error) {
|
||||
// BytesDataAvailability encodes a L2Tx into []byte for the Data Availability
|
||||
func (tx L2Tx) BytesDataAvailability(nLevels uint32) ([]byte, error) {
|
||||
idxLen := nLevels / 8 //nolint:gomnd
|
||||
|
||||
b := make([]byte, ((nLevels*2)+16+8)/8) //nolint:gomnd
|
||||
|
||||
@@ -32,7 +32,7 @@ func TestL2TxByteParsers(t *testing.T) {
|
||||
}
|
||||
// Data from the compatibility test
|
||||
expected := "00000101000001002b16c9"
|
||||
encodedData, err := l2Tx.Bytes(32)
|
||||
encodedData, err := l2Tx.BytesDataAvailability(32)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, expected, hex.EncodeToString(encodedData))
|
||||
|
||||
|
||||
@@ -117,7 +117,6 @@ const (
|
||||
)
|
||||
|
||||
// Tx is a struct used by the TxSelector & BatchBuilder as a generic type generated from L1Tx & PoolL2Tx
|
||||
// TODO: this should be changed for "mini Tx"
|
||||
type Tx struct {
|
||||
// Generic
|
||||
IsL1 bool `meddler:"is_l1"`
|
||||
|
||||
34
common/zk.go
34
common/zk.go
@@ -32,9 +32,10 @@ type ZKMetadata struct {
|
||||
// is constant for all circuits: 64)
|
||||
MaxFeeIdxs uint32
|
||||
|
||||
L1TxsData [][]byte
|
||||
L2TxsData [][]byte
|
||||
ChainID uint16
|
||||
L1TxsData [][]byte
|
||||
L1TxsDataAvailability [][]byte
|
||||
L2TxsData [][]byte
|
||||
ChainID uint16
|
||||
|
||||
NewLastIdxRaw Idx
|
||||
NewStateRootRaw *merkletree.Hash
|
||||
@@ -49,6 +50,8 @@ type ZKInputs struct {
|
||||
// General
|
||||
//
|
||||
|
||||
// CurrentNumBatch is the current batch number processed
|
||||
CurrentNumBatch *big.Int `json:"currentNumBatch"` // uint32
|
||||
// inputs for final `hashGlobalInputs`
|
||||
// OldLastIdx is the last index assigned to an account
|
||||
OldLastIdx *big.Int `json:"oldLastIdx"` // uint64 (max nLevels bits)
|
||||
@@ -72,6 +75,9 @@ type ZKInputs struct {
|
||||
TxCompressedData []*big.Int `json:"txCompressedData"` // big.Int (max 251 bits), len: [nTx]
|
||||
// TxCompressedDataV2, only used in L2Txs, in L1Txs is set to 0
|
||||
TxCompressedDataV2 []*big.Int `json:"txCompressedDataV2"` // big.Int (max 193 bits), len: [nTx]
|
||||
// MaxNumBatch is the maximum allowed batch number when the transaction
|
||||
// can be processed
|
||||
MaxNumBatch []*big.Int `json:"maxNumBatch"` // uint32
|
||||
|
||||
// FromIdx
|
||||
FromIdx []*big.Int `json:"fromIdx"` // uint64 (max nLevels bits), len: [nTx]
|
||||
@@ -266,7 +272,7 @@ func (z ZKInputs) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
// NewZKInputs returns a pointer to an initialized struct of ZKInputs
|
||||
func NewZKInputs(nTx, maxL1Tx, maxTx, maxFeeIdxs, nLevels uint32) *ZKInputs {
|
||||
func NewZKInputs(nTx, maxL1Tx, maxTx, maxFeeIdxs, nLevels uint32, currentNumBatch *big.Int) *ZKInputs {
|
||||
zki := &ZKInputs{}
|
||||
zki.Metadata.NTx = nTx
|
||||
zki.Metadata.MaxFeeIdxs = maxFeeIdxs
|
||||
@@ -276,15 +282,17 @@ func NewZKInputs(nTx, maxL1Tx, maxTx, maxFeeIdxs, nLevels uint32) *ZKInputs {
|
||||
zki.Metadata.MaxTx = maxTx
|
||||
|
||||
// General
|
||||
zki.CurrentNumBatch = currentNumBatch
|
||||
zki.OldLastIdx = big.NewInt(0)
|
||||
zki.OldStateRoot = big.NewInt(0)
|
||||
zki.GlobalChainID = big.NewInt(0)
|
||||
zki.GlobalChainID = big.NewInt(0) // TODO pass by parameter
|
||||
zki.FeeIdxs = newSlice(maxFeeIdxs)
|
||||
zki.FeePlanTokens = newSlice(maxFeeIdxs)
|
||||
|
||||
// Txs
|
||||
zki.TxCompressedData = newSlice(nTx)
|
||||
zki.TxCompressedDataV2 = newSlice(nTx)
|
||||
zki.MaxNumBatch = newSlice(nTx)
|
||||
zki.FromIdx = newSlice(nTx)
|
||||
zki.AuxFromIdx = newSlice(nTx)
|
||||
zki.ToIdx = newSlice(nTx)
|
||||
@@ -451,6 +459,12 @@ func (z ZKInputs) ToHashGlobalData() ([]byte, error) {
|
||||
}
|
||||
b = append(b, l1TxsData...)
|
||||
|
||||
var l1TxsDataAvailability []byte
|
||||
for i := 0; i < len(z.Metadata.L1TxsDataAvailability); i++ {
|
||||
l1TxsDataAvailability = append(l1TxsDataAvailability, z.Metadata.L1TxsDataAvailability[i]...)
|
||||
}
|
||||
b = append(b, l1TxsDataAvailability...)
|
||||
|
||||
// [MAX_TX*(2*NLevels + 24) bits] L2TxsData
|
||||
var l2TxsData []byte
|
||||
l2TxDataLen := 2*z.Metadata.NLevels + 24 //nolint:gomnd
|
||||
@@ -463,9 +477,9 @@ func (z ZKInputs) ToHashGlobalData() ([]byte, error) {
|
||||
return nil, fmt.Errorf("len(l2TxsData): %d, expected: %d", len(l2TxsData), expectedL2TxsDataLen)
|
||||
}
|
||||
|
||||
l2TxsPadding := make([]byte, (int(z.Metadata.MaxTx)-len(z.Metadata.L2TxsData))*int(l2TxDataLen)/8) //nolint:gomnd
|
||||
b = append(b, l2TxsPadding...)
|
||||
b = append(b, l2TxsData...)
|
||||
l2TxsPadding := make([]byte, (int(z.Metadata.MaxTx)-len(z.Metadata.L1TxsDataAvailability)-len(z.Metadata.L2TxsData))*int(l2TxDataLen)/8) //nolint:gomnd
|
||||
b = append(b, l2TxsPadding...)
|
||||
|
||||
// [NLevels * MAX_TOKENS_FEE bits] feeTxsData
|
||||
for i := 0; i < len(z.FeeIdxs); i++ {
|
||||
@@ -486,5 +500,11 @@ func (z ZKInputs) ToHashGlobalData() ([]byte, error) {
|
||||
binary.BigEndian.PutUint16(chainID[:], z.Metadata.ChainID)
|
||||
b = append(b, chainID[:]...)
|
||||
|
||||
// [32 bits] currentNumBatch
|
||||
currNumBatchBytes := z.CurrentNumBatch.Bytes()
|
||||
var currNumBatch [4]byte
|
||||
copy(currNumBatch[4-len(currNumBatchBytes):], currNumBatchBytes)
|
||||
b = append(b, currNumBatch[:]...)
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
@@ -2,13 +2,14 @@ package common
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestZKInputs(t *testing.T) {
|
||||
zki := NewZKInputs(100, 16, 512, 24, 32)
|
||||
zki := NewZKInputs(100, 16, 512, 24, 32, big.NewInt(1))
|
||||
_, err := json.Marshal(zki)
|
||||
require.Nil(t, err)
|
||||
// fmt.Println(string(s))
|
||||
|
||||
Reference in New Issue
Block a user