From dfd49164f467f0b214fe5ec4092ac748a16d8fa1 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Wed, 3 Mar 2021 11:35:50 +0100 Subject: [PATCH] Add NewFloor40Floor helper method Also added tracerr.Wrap(...) to missing places. --- common/float40.go | 39 +++++++++++++++++++++++++++++++------- common/float40_test.go | 40 ++++++++++++++++++++++++++++++++++++++- common/l1tx.go | 2 +- common/tx.go | 6 +++--- coordinator/pipeline.go | 10 +++++----- coordinator/txmanager.go | 2 +- db/historydb/historydb.go | 4 ++-- db/kvdb/kvdb.go | 2 +- node/node.go | 2 +- 9 files changed, 85 insertions(+), 22 deletions(-) diff --git a/common/float40.go b/common/float40.go index e1406f8..432824a 100644 --- a/common/float40.go +++ b/common/float40.go @@ -32,6 +32,8 @@ var ( // ErrFloat40NotEnoughPrecission is used when the given *big.Int can // not be represented as Float40 due not enough precission ErrFloat40NotEnoughPrecission = errors.New("Float40 error, not enough precission") + + thres = big.NewInt(0x08_00_00_00_00) ) // Float40 represents a float in a 64 bit format @@ -68,7 +70,7 @@ func (f40 Float40) BigInt() (*big.Int, error) { var f40Uint64 uint64 = uint64(f40) & 0x00_00_00_FF_FF_FF_FF_FF f40Bytes, err := f40.Bytes() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } e := f40Bytes[0] & 0xF8 >> 3 // take first 5 bits @@ -79,25 +81,48 @@ func (f40 Float40) BigInt() (*big.Int, error) { return r, nil } -// NewFloat40 encodes a *big.Int integer as a Float40, returning error in case -// of loss during the encoding. -func NewFloat40(f *big.Int) (Float40, error) { +// newFloat40ME takes a *big.Int integer and returns the m (mantissa) & e +// (exponent) from the Float40 representation +func newFloat40ME(f *big.Int) (*big.Int, *big.Int) { m := f e := big.NewInt(0) zero := big.NewInt(0) ten := big.NewInt(10) - thres := big.NewInt(0x08_00_00_00_00) for new(big.Int).Mod(m, ten).Cmp(zero) == 0 && m.Cmp(thres) >= 0 { m = new(big.Int).Div(m, ten) e = new(big.Int).Add(e, big.NewInt(1)) } + return m, e +} + +// NewFloat40 encodes a *big.Int integer as a Float40, returning error in case +// of loss during the encoding. +func NewFloat40(f *big.Int) (Float40, error) { + m, e := newFloat40ME(f) if e.Int64() > 31 { - return 0, ErrFloat40E31 + return 0, tracerr.Wrap(ErrFloat40E31) } if m.Cmp(thres) >= 0 { - return 0, ErrFloat40NotEnoughPrecission + return 0, tracerr.Wrap(ErrFloat40NotEnoughPrecission) } r := new(big.Int).Add(m, new(big.Int).Mul(e, thres)) return Float40(r.Uint64()), nil } + +// NewFloat40Floor encodes a *big.Int integer as a Float40, rounding down in +// case of loss during the encoding. It returns an error in case that the number +// is too big (e>31). Warning: this method should not be used inside the +// hermez-node, it's a helper for external usage to generate valid Float40 +// values. +func NewFloat40Floor(f *big.Int) (Float40, error) { + m, e := newFloat40ME(f) + if e.Int64() > 31 { + return 0, tracerr.Wrap(ErrFloat40E31) + } + + r := new(big.Int).Add(m, + new(big.Int).Mul(e, thres)) + + return Float40(r.Uint64()), nil +} diff --git a/common/float40_test.go b/common/float40_test.go index 50f2c71..0089332 100644 --- a/common/float40_test.go +++ b/common/float40_test.go @@ -4,6 +4,7 @@ import ( "math/big" "testing" + "github.com/hermeznetwork/tracerr" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -55,7 +56,44 @@ func TestExpectError(t *testing.T) { bi, ok := new(big.Int).SetString(test, 10) require.True(t, ok) _, err := NewFloat40(bi) - assert.Equal(t, testVector[test], err) + assert.Equal(t, testVector[test], tracerr.Unwrap(err)) + } +} + +func TestNewFloat40Floor(t *testing.T) { + testVector := map[string][]uint64{ + // []int contains [Float40 value, Flot40 Floor value], when + // Float40 value is expected to be 0, is because is expected to + // be an error + "9922334455000000000000000000000000000000": {1040714485495, 1040714485495}, + "9922334455000000000000000000000000000001": {0, 6846188881046405121}, + "9922334454999999999999999999999999999999": {0, 6846188881046405119}, + "42949672950000000000000000000000000000000": {1069446856703, 1069446856703}, + "99223344556573838487575": {0, 16754928163869896727}, + "992233445500000000000000000000000000000000": {0, 0}, + "343597383670000000000000000000000000000000": {1099511627775, 1099511627775}, + "343597383680000000000000000000000000000000": {0, 1099511627776}, + "343597383690000000000000000000000000000000": {0, 1099511627777}, + "343597383700000000000000000000000000000000": {0, 0}, + } + for test := range testVector { + bi, ok := new(big.Int).SetString(test, 10) + require.True(t, ok) + f40, err := NewFloat40(bi) + if f40 == 0 { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + assert.Equal(t, testVector[test][0], uint64(f40)) + + f40, err = NewFloat40Floor(bi) + if f40 == 0 { + assert.Equal(t, ErrFloat40E31, tracerr.Unwrap(err)) + } else { + assert.NoError(t, err) + } + assert.Equal(t, testVector[test][1], uint64(f40)) } } diff --git a/common/l1tx.go b/common/l1tx.go index c8d8d4f..1a2ec43 100644 --- a/common/l1tx.go +++ b/common/l1tx.go @@ -259,7 +259,7 @@ func L1TxFromDataAvailability(b []byte, nLevels uint32) (*L1Tx, error) { } l1tx.ToIdx = toIdx l1tx.EffectiveAmount, err = Float40FromBytes(amountBytes).BigInt() - return &l1tx, err + return &l1tx, tracerr.Wrap(err) } // BytesGeneric returns the generic representation of a L1Tx. This method is diff --git a/common/tx.go b/common/tx.go index 4c74004..e889572 100644 --- a/common/tx.go +++ b/common/tx.go @@ -15,12 +15,12 @@ import ( ) const ( - // TXIDPrefixL1UserTx is the prefix that determines that the TxID is - // for a L1UserTx + // TxIDPrefixL1UserTx is the prefix that determines that the TxID is for + // a L1UserTx //nolinter:gomnd TxIDPrefixL1UserTx = byte(0) - // TXIDPrefixL1CoordTx is the prefix that determines that the TxID is + // TxIDPrefixL1CoordTx is the prefix that determines that the TxID is // for a L1CoordinatorTx //nolinter:gomnd TxIDPrefixL1CoordTx = byte(1) diff --git a/coordinator/pipeline.go b/coordinator/pipeline.go index 2e11490..c8b2108 100644 --- a/coordinator/pipeline.go +++ b/coordinator/pipeline.go @@ -210,7 +210,7 @@ func (p *Pipeline) handleForgeBatch(ctx context.Context, return nil, ctx.Err() } else if err != nil { log.Errorw("proversPool.Get", "err", err) - return nil, err + return nil, tracerr.Wrap(err) } defer func() { // If we encounter any error (notice that this function returns @@ -240,7 +240,7 @@ func (p *Pipeline) handleForgeBatch(ctx context.Context, } else { log.Errorw("forgeBatch", "err", err) } - return nil, err + return nil, tracerr.Wrap(err) } // 3. Send the ZKInputs to the proof server @@ -249,7 +249,7 @@ func (p *Pipeline) handleForgeBatch(ctx context.Context, return nil, ctx.Err() } else if err != nil { log.Errorw("sendServerProof", "err", err) - return nil, err + return nil, tracerr.Wrap(err) } return batchInfo, nil } @@ -427,7 +427,7 @@ func (p *Pipeline) forgeBatch(batchNum common.BatchNum) (batchInfo *BatchInfo, e // If we haven't reached the ForgeDelay, skip forging the batch if slotCommitted && now.Sub(p.lastForgeTime) < p.cfg.ForgeDelay { - return nil, errForgeBeforeDelay + return nil, tracerr.Wrap(errForgeBeforeDelay) } // 1. Decide if we forge L2Tx or L1+L2Tx @@ -485,7 +485,7 @@ func (p *Pipeline) forgeBatch(batchNum common.BatchNum) (batchInfo *BatchInfo, e if err := p.txSelector.Reset(batchInfo.BatchNum-1, false); err != nil { return nil, tracerr.Wrap(err) } - return nil, errForgeNoTxsBeforeDelay + return nil, tracerr.Wrap(errForgeNoTxsBeforeDelay) } } diff --git a/coordinator/txmanager.go b/coordinator/txmanager.go index 1976a20..bb97a4b 100644 --- a/coordinator/txmanager.go +++ b/coordinator/txmanager.go @@ -67,7 +67,7 @@ func NewTxManager(ctx context.Context, cfg *Config, ethClient eth.ClientInterfac } accNonce, err := ethClient.EthNonceAt(ctx, *address, nil) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } log.Infow("TxManager started", "nonce", accNonce) return &TxManager{ diff --git a/db/historydb/historydb.go b/db/historydb/historydb.go index de3339c..cfb1b18 100644 --- a/db/historydb/historydb.go +++ b/db/historydb/historydb.go @@ -179,7 +179,7 @@ func (hdb *HistoryDB) GetBatch(batchNum common.BatchNum) (*common.Batch, error) batch.slot_num, batch.total_fees_usd FROM batch WHERE batch_num = $1;`, batchNum, ) - return &batch, err + return &batch, tracerr.Wrap(err) } // GetAllBatches retrieve all batches from the DB @@ -235,7 +235,7 @@ func (hdb *HistoryDB) GetLastBatch() (*common.Batch, error) { batch.num_accounts, batch.last_idx, batch.exit_root, batch.forge_l1_txs_num, batch.slot_num, batch.total_fees_usd FROM batch ORDER BY batch_num DESC LIMIT 1;`, ) - return &batch, err + return &batch, tracerr.Wrap(err) } // GetLastL1BatchBlockNum returns the blockNum of the latest forged l1Batch diff --git a/db/kvdb/kvdb.go b/db/kvdb/kvdb.go index a367bf3..86f5acd 100644 --- a/db/kvdb/kvdb.go +++ b/db/kvdb/kvdb.go @@ -458,7 +458,7 @@ func (k *KVDB) CheckpointExists(batchNum common.BatchNum) (bool, error) { if _, err := os.Stat(source); os.IsNotExist(err) { return false, nil } else if err != nil { - return false, err + return false, tracerr.Wrap(err) } return true, nil } diff --git a/node/node.go b/node/node.go index bfd7036..681a32c 100644 --- a/node/node.go +++ b/node/node.go @@ -268,7 +268,7 @@ func NewNode(mode Mode, cfg *config.Node) (*Node, error) { if err := auth.Sign(func(msg []byte) ([]byte, error) { return keyStore.SignHash(feeAccount, msg) }, chainIDU16, cfg.SmartContracts.Rollup); err != nil { - return nil, err + return nil, tracerr.Wrap(err) } coordAccount := &txselector.CoordAccount{ Addr: cfg.Coordinator.FeeAccount.Address,