diff --git a/.gitignore b/.gitignore index af1d9745d..b25dbe2a5 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,6 @@ vendor deployment/dependency deployment/configs deployment/.zkbnb -run_*.sh \ No newline at end of file +run_*.sh + +own* \ No newline at end of file diff --git a/Makefile b/Makefile index c2681ead6..572c7676a 100644 --- a/Makefile +++ b/Makefile @@ -36,6 +36,7 @@ tools: build: api-server build-only lint: + go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.50.0 golangci-lint run ./... build-only: diff --git a/README.md b/README.md index b993db286..eac295576 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,6 @@ ZkBNB achieves the following goals: cryptographic. Users do not have to trust any third parties or keep monitoring the Rollup blocks in order to prevent fraud. - **L1<>L2 Communication**. BNB, and BEP20/BEP721/BEP1155 created on BSC or ZkBNB can flow freely between BSC and ZkBNB. -- **Built-in instant AMM swap**. It allows digital assets to be traded without permission and automatically by using - liquidity pools. - **Built-in NFT marketplace**. Developer can build marketplace for crypto collectibles and non-fungible tokens (NFTs) out of box on ZkBNB. - **Fast transaction speed and faster finality**. @@ -35,7 +33,6 @@ ZkBNB starts its development based on [Zecrey](https://github.com/bnb-chain/zecr - [Key Features](#Key-Features) + [Digital Asset Management](#Digital-Asset-Management) + [NFT Management and Marketplace](#NFT-Management-and-Marketplace) - + [AMM Exchange](#AMM-Exchange) + [Native Name Service](#Native-Name-Service) + [Seamless L1 Wallet Management](#Seamless-L1-Wallet-Management) @@ -59,7 +56,7 @@ ZkBNB starts its development based on [Zecrey](https://github.com/bnb-chain/zecr - **prover**. Prover generates cryptographic proof based on the witness materials. - **sender**. The sender rollups the compressed l2 blocks to L1, and submit proof to verify it. - **api server**. The api server is the access endpoints for most users, it provides rich data, including - digital assets, blocks, transactions, swap info, gas fees. + digital assets, blocks, transactions, gas fees. - **recovery**. A tool to recover the sparse merkle tree in kv-rocks based on the state world in postgresql. @@ -105,16 +102,6 @@ being sent to the ZkBNB. Once the offer is matched, an **AtomicMatch** transacti will be sent to ZkBNB to make the trade happen. Users can also cancel an offer manually by sending a cancel offer transaction to disable the backend cached offer. -### AMM Exchange - -Automated market makers (AMM) are decentralized exchanges that pool liquidity from users and price the assets within -the pool using algorithms. - -ZkBNB follows the similar mechanic as [UniSwap V2](https://docs.uniswap.org/protocol/V2/concepts/protocol-overview/how-uniswap-works). -Anyone can become a liquidity provider (LP) for a pool by depositing an equivalent value of each underlying token in -return for pool tokens. The different from UniSwap is that the LP token on ZkBNB can not transfer or trade. Users can -simply list a swap pair by calling the rollup contract on BSC. - ### Native Name Service No more copying and pasting long addresses on ZkBNB. Every account on ZkBNB gets its short name, user can use that to store funds and receive any cryptocurrency, token, or NFT. diff --git a/common/chain/balance_helper.go b/common/chain/balance_helper.go index 056818fe5..676957ff4 100644 --- a/common/chain/balance_helper.go +++ b/common/chain/balance_helper.go @@ -36,7 +36,6 @@ func ComputeNewBalance(assetType int64, balance string, balanceDelta string) (ne return "", err } assetInfo.Balance = ffmath.Add(assetInfo.Balance, assetDelta.Balance) - assetInfo.LpAmount = ffmath.Add(assetInfo.LpAmount, assetDelta.LpAmount) if assetDelta.OfferCanceledOrFinalized == nil { assetDelta.OfferCanceledOrFinalized = types.ZeroBigInt } @@ -44,28 +43,6 @@ func ComputeNewBalance(assetType int64, balance string, balanceDelta string) (ne assetInfo.OfferCanceledOrFinalized = assetDelta.OfferCanceledOrFinalized } newBalance = assetInfo.String() - case types.LiquidityAssetType: - // balance: LiquidityInfo - liquidityInfo, err := types.ParseLiquidityInfo(balance) - if err != nil { - return "", err - } - deltaLiquidity, err := types.ParseLiquidityInfo(balanceDelta) - if err != nil { - return "", err - } - liquidityInfo.AssetAId = deltaLiquidity.AssetAId - liquidityInfo.AssetBId = deltaLiquidity.AssetBId - liquidityInfo.AssetA = ffmath.Add(liquidityInfo.AssetA, deltaLiquidity.AssetA) - liquidityInfo.AssetB = ffmath.Add(liquidityInfo.AssetB, deltaLiquidity.AssetB) - liquidityInfo.LpAmount = ffmath.Add(liquidityInfo.LpAmount, deltaLiquidity.LpAmount) - if deltaLiquidity.KLast.Cmp(types.ZeroBigInt) != 0 { - liquidityInfo.KLast = deltaLiquidity.KLast - } - liquidityInfo.FeeRate = deltaLiquidity.FeeRate - liquidityInfo.TreasuryAccountIndex = deltaLiquidity.TreasuryAccountIndex - liquidityInfo.TreasuryRate = deltaLiquidity.TreasuryRate - newBalance = liquidityInfo.String() case types.NftAssetType: // just set the old one as the new one newBalance = balanceDelta diff --git a/common/chain/liquidity_helper.go b/common/chain/liquidity_helper.go deleted file mode 100644 index 14f725db1..000000000 --- a/common/chain/liquidity_helper.go +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright © 2021 ZkBNB Protocol - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package chain - -import ( - "errors" - "math/big" - - "github.com/bnb-chain/zkbnb-crypto/ffmath" - "github.com/bnb-chain/zkbnb-crypto/util" - "github.com/bnb-chain/zkbnb/common" - "github.com/bnb-chain/zkbnb/types" -) - -func ComputeEmptyLpAmount( - assetAAmount *big.Int, - assetBAmount *big.Int, -) (lpAmount *big.Int, err error) { - lpSquare := ffmath.Multiply(assetAAmount, assetBAmount) - lpFloat := ffmath.FloatSqrt(ffmath.IntToFloat(lpSquare)) - lpAmount, err = common.CleanPackedAmount(ffmath.FloatToInt(lpFloat)) - if err != nil { - return nil, err - } - return lpAmount, nil -} - -func ComputeLpAmount(liquidityInfo *types.LiquidityInfo, assetAAmount *big.Int) (lpAmount *big.Int, err error) { - // lp = assetAAmount / poolA * LpAmount - sLp, err := ComputeSLp(liquidityInfo.AssetA, liquidityInfo.AssetB, liquidityInfo.KLast, liquidityInfo.FeeRate, liquidityInfo.TreasuryRate) - if err != nil { - return nil, err - } - poolLpAmount := ffmath.Sub(liquidityInfo.LpAmount, sLp) - lpAmount, err = common.CleanPackedAmount(ffmath.Div(ffmath.Multiply(assetAAmount, poolLpAmount), liquidityInfo.AssetA)) - if err != nil { - return nil, err - } - return lpAmount, nil -} - -func ComputeRemoveLiquidityAmount(liquidityInfo *types.LiquidityInfo, lpAmount *big.Int) (assetAAmount, assetBAmount *big.Int, err error) { - sLp, err := ComputeSLp(liquidityInfo.AssetA, liquidityInfo.AssetB, liquidityInfo.KLast, liquidityInfo.FeeRate, liquidityInfo.TreasuryRate) - if err != nil { - return nil, nil, err - } - lpAmount, err = common.CleanPackedAmount(lpAmount) - if err != nil { - return nil, nil, err - } - poolLp := ffmath.Sub(liquidityInfo.LpAmount, sLp) - assetAAmount = ffmath.Multiply(lpAmount, liquidityInfo.AssetA) - assetAAmount, _ = util.CleanPackedAmount(ffmath.Div(assetAAmount, poolLp)) - assetBAmount = ffmath.Multiply(lpAmount, liquidityInfo.AssetB) - assetBAmount, _ = util.CleanPackedAmount(ffmath.Div(assetBAmount, poolLp)) - return assetAAmount, assetBAmount, nil -} - -func ComputeDelta( - assetAAmount *big.Int, - assetBAmount *big.Int, - assetAId int64, assetBId int64, assetId int64, isFrom bool, - deltaAmount *big.Int, - feeRate int64, -) (assetAmount *big.Int, toAssetId int64, err error) { - - if isFrom { - if assetAId == assetId { - delta, err := ComputeInputPrice(assetAAmount, assetBAmount, deltaAmount, feeRate) - if err != nil { - return nil, 0, err - } - return delta, assetBId, nil - } else if assetBId == assetId { - delta, err := ComputeInputPrice(assetBAmount, assetAAmount, deltaAmount, feeRate) - if err != nil { - return nil, 0, err - } - return delta, assetAId, nil - } else { - return types.ZeroBigInt, 0, errors.New("[ComputeDelta]: invalid asset id") - } - } else { - if assetAId == assetId { - delta, err := ComputeOutputPrice(assetAAmount, assetBAmount, deltaAmount, feeRate) - if err != nil { - return nil, 0, err - } - return delta, assetBId, nil - } else if assetBId == assetId { - delta, err := ComputeOutputPrice(assetBAmount, assetAAmount, deltaAmount, feeRate) - if err != nil { - return nil, 0, err - } - return delta, assetAId, nil - } else { - return types.ZeroBigInt, 0, errors.New("[ComputeDelta]: invalid asset id") - } - } -} - -// ComputeInputPrice InputPrice = (9970 * deltaX * y) / (10000 * x + 9970 * deltaX) -func ComputeInputPrice(x *big.Int, y *big.Int, inputX *big.Int, feeRate int64) (*big.Int, error) { - rFeeR := big.NewInt(types.FeeRateBase - feeRate) - res, err := util.CleanPackedAmount(ffmath.Div(ffmath.Multiply(rFeeR, ffmath.Multiply(inputX, y)), ffmath.Add(ffmath.Multiply(big.NewInt(types.FeeRateBase), x), ffmath.Multiply(rFeeR, inputX)))) - if err != nil { - return nil, err - } - return res, nil -} - -// ComputeOutputPrice OutputPrice = (10000 * x * deltaY) / (9970 * (y - deltaY)) + 1 -func ComputeOutputPrice(x *big.Int, y *big.Int, inputY *big.Int, feeRate int64) (*big.Int, error) { - rFeeR := big.NewInt(types.FeeRateBase - feeRate) - res, err := common.CleanPackedAmount(ffmath.Add(ffmath.Div(ffmath.Multiply(big.NewInt(types.FeeRateBase), ffmath.Multiply(x, inputY)), ffmath.Multiply(rFeeR, ffmath.Sub(y, inputY))), big.NewInt(1))) - if err != nil { - return nil, err - } - return res, nil -} - -func ComputeSLp(poolA, poolB *big.Int, kLast *big.Int, feeRate, treasuryRate int64) (*big.Int, error) { - kCurrent := ffmath.Multiply(poolA, poolB) - if kCurrent.Cmp(types.ZeroBigInt) == 0 { - return types.ZeroBigInt, nil - } - kCurrent.Sqrt(kCurrent) - kLast.Sqrt(kLast) - l := ffmath.Multiply(ffmath.Sub(kCurrent, kLast), big.NewInt(types.FeeRateBase)) - r := ffmath.Multiply(ffmath.Sub(ffmath.Multiply(big.NewInt(types.FeeRateBase), ffmath.Div(big.NewInt(feeRate), big.NewInt(treasuryRate))), big.NewInt(types.FeeRateBase)), kCurrent) - r = ffmath.Add(r, ffmath.Multiply(big.NewInt(types.FeeRateBase), kLast)) - res, err := common.CleanPackedAmount(ffmath.Div(l, r)) - if err != nil { - return nil, err - } - return res, nil -} diff --git a/common/chain/liquidity_helper_test.go b/common/chain/liquidity_helper_test.go deleted file mode 100644 index a56479e8a..000000000 --- a/common/chain/liquidity_helper_test.go +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright © 2021 ZkBNB Protocol - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package chain - -import ( - "math/big" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/bnb-chain/zkbnb/types" -) - -func TestComputeDeltaY(t *testing.T) { - poolA := big.NewInt(1000) - poolB := big.NewInt(1000) - deltaY, assetId, err := ComputeDelta( - poolA, poolB, - 0, 2, 0, false, big.NewInt(500), - 30, - ) - if err != nil { - t.Fatal(err) - } - assert.Equal(t, deltaY.String(), "1004") - assert.Equal(t, assetId, int64(2)) -} - -func TestComputeRemoveLiquidityAmount(t *testing.T) { - liquidityInfo := &types.LiquidityInfo{ - PairIndex: 0, - AssetAId: 0, - AssetA: big.NewInt(99901), - AssetBId: 2, - AssetB: big.NewInt(100100), - LpAmount: big.NewInt(100000), - KLast: big.NewInt(10000000000), - FeeRate: 30, - TreasuryAccountIndex: 0, - TreasuryRate: 5, - } - aAmount, bAmount, _ := ComputeRemoveLiquidityAmount( - liquidityInfo, - big.NewInt(100), - ) - assert.Equal(t, aAmount.Int64(), int64(99)) - assert.Equal(t, bAmount.Int64(), int64(100)) -} - -func TestComputeInputPrice(t *testing.T) { - poolA := big.NewInt(1000) - poolB := big.NewInt(1000) - deltaY, _ := ComputeInputPrice( - poolA, poolB, - big.NewInt(500), 30, - ) - assert.Equal(t, deltaY.Int64(), int64(332)) -} - -func TestComputeOutputPrice(t *testing.T) { - poolA := big.NewInt(1000) - poolB := big.NewInt(1000) - deltaY, _ := ComputeOutputPrice( - poolA, poolB, - big.NewInt(500), 30, - ) - assert.Equal(t, deltaY.Int64(), int64(1004)) -} diff --git a/common/chain/pubdata_helper.go b/common/chain/pubdata_helper.go index 9d8d6d33f..659bedc70 100644 --- a/common/chain/pubdata_helper.go +++ b/common/chain/pubdata_helper.go @@ -61,50 +61,6 @@ func ParseRegisterZnsPubData(pubData []byte) (tx *txtypes.RegisterZnsTxInfo, err return tx, nil } -func ParseCreatePairPubData(pubData []byte) (tx *txtypes.CreatePairTxInfo, err error) { - if len(pubData) != types.CreatePairPubDataSize { - return nil, errors.New("[ParseCreatePairPubData] invalid size") - } - offset := 0 - offset, txType := common2.ReadUint8(pubData, offset) - offset, pairIndex := common2.ReadUint16(pubData, offset) - offset, assetAId := common2.ReadUint16(pubData, offset) - offset, assetBId := common2.ReadUint16(pubData, offset) - offset, feeRate := common2.ReadUint16(pubData, offset) - offset, treasuryAccountIndex := common2.ReadUint32(pubData, offset) - _, treasuryRate := common2.ReadUint16(pubData, offset) - tx = &txtypes.CreatePairTxInfo{ - TxType: txType, - PairIndex: int64(pairIndex), - AssetAId: int64(assetAId), - AssetBId: int64(assetBId), - FeeRate: int64(feeRate), - TreasuryAccountIndex: int64(treasuryAccountIndex), - TreasuryRate: int64(treasuryRate), - } - return tx, nil -} - -func ParseUpdatePairRatePubData(pubData []byte) (tx *txtypes.UpdatePairRateTxInfo, err error) { - if len(pubData) != types.UpdatePairRatePubdataSize { - return nil, errors.New("[ParseUpdatePairRatePubData] invalid size") - } - offset := 0 - offset, txType := common2.ReadUint8(pubData, offset) - offset, pairIndex := common2.ReadUint16(pubData, offset) - offset, feeRate := common2.ReadUint16(pubData, offset) - offset, treasuryAccountIndex := common2.ReadUint32(pubData, offset) - _, treasuryRate := common2.ReadUint16(pubData, offset) - tx = &txtypes.UpdatePairRateTxInfo{ - TxType: txType, - PairIndex: int64(pairIndex), - FeeRate: int64(feeRate), - TreasuryAccountIndex: int64(treasuryAccountIndex), - TreasuryRate: int64(treasuryRate), - } - return tx, nil -} - func ParseDepositPubData(pubData []byte) (tx *txtypes.DepositTxInfo, err error) { /* struct Deposit { @@ -140,7 +96,6 @@ func ParseDepositNftPubData(pubData []byte) (tx *txtypes.DepositNftTxInfo, err e } offset := 0 offset, txType := common2.ReadUint8(pubData, offset) - offset, isNewNft := common2.ReadUint8(pubData, offset) offset, accountIndex := common2.ReadUint32(pubData, offset) offset, nftIndex := common2.ReadUint40(pubData, offset) offset, nftL1Address := common2.ReadAddress(pubData, offset) @@ -152,7 +107,6 @@ func ParseDepositNftPubData(pubData []byte) (tx *txtypes.DepositNftTxInfo, err e _, collectionId := common2.ReadUint16(pubData, offset) tx = &txtypes.DepositNftTxInfo{ TxType: txType, - IsNewNft: isNewNft, AccountIndex: int64(accountIndex), NftIndex: nftIndex, NftL1Address: nftL1Address, diff --git a/common/pack.go b/common/pack.go index 945a98e79..613e5d386 100644 --- a/common/pack.go +++ b/common/pack.go @@ -11,15 +11,7 @@ func ToPackedAmount(amount *big.Int) (res int64, err error) { return util.ToPackedAmount(amount) } -func CleanPackedAmount(amount *big.Int) (nAmount *big.Int, err error) { - return util.CleanPackedAmount(amount) -} - // ToPackedFee : convert big int to 16 bit, 5 bits for 10^x, 11 bits for a * 10^x func ToPackedFee(amount *big.Int) (res int64, err error) { return util.ToPackedFee(amount) } - -func CleanPackedFee(amount *big.Int) (nAmount *big.Int, err error) { - return util.CleanPackedFee(amount) -} diff --git a/common/prove/add_liquidity.go b/common/prove/add_liquidity.go deleted file mode 100644 index c230057f4..000000000 --- a/common/prove/add_liquidity.go +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright © 2021 ZkBNB Protocol - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package prove - -import ( - "github.com/consensys/gnark-crypto/ecc/bn254/twistededwards/eddsa" - - cryptoTypes "github.com/bnb-chain/zkbnb-crypto/circuit/types" - "github.com/bnb-chain/zkbnb-crypto/wasm/txtypes" - "github.com/bnb-chain/zkbnb/common" - "github.com/bnb-chain/zkbnb/dao/tx" - "github.com/bnb-chain/zkbnb/types" -) - -func (w *WitnessHelper) constructAddLiquidityTxWitness(witness *TxWitness, oTx *tx.Tx) (*TxWitness, error) { - txInfo, err := types.ParseAddLiquidityTxInfo(oTx.TxInfo) - if err != nil { - return nil, err - } - cryptoTxInfo, err := toCryptoAddLiquidityTx(txInfo) - if err != nil { - return nil, err - } - witness.AddLiquidityTxInfo = cryptoTxInfo - witness.ExpiredAt = txInfo.ExpiredAt - witness.Signature = new(eddsa.Signature) - _, err = witness.Signature.SetBytes(txInfo.Sig) - if err != nil { - return nil, err - } - return witness, nil -} - -func toCryptoAddLiquidityTx(txInfo *txtypes.AddLiquidityTxInfo) (info *cryptoTypes.AddLiquidityTx, err error) { - packedAAmount, err := common.ToPackedAmount(txInfo.AssetAAmount) - if err != nil { - return nil, err - } - packedBAmount, err := common.ToPackedAmount(txInfo.AssetBAmount) - if err != nil { - return nil, err - } - packedLpAmount, err := common.ToPackedAmount(txInfo.LpAmount) - if err != nil { - return nil, err - } - packedTreasuryAmount, err := common.ToPackedAmount(txInfo.TreasuryAmount) - if err != nil { - return nil, err - } - packedKLast, err := common.ToPackedAmount(txInfo.KLast) - if err != nil { - return nil, err - } - packedFee, err := common.ToPackedFee(txInfo.GasFeeAssetAmount) - if err != nil { - return nil, err - } - info = &cryptoTypes.AddLiquidityTx{ - FromAccountIndex: txInfo.FromAccountIndex, - PairIndex: txInfo.PairIndex, - AssetAId: txInfo.AssetAId, - AssetAAmount: packedAAmount, - AssetBId: txInfo.AssetBId, - AssetBAmount: packedBAmount, - LpAmount: packedLpAmount, - KLast: packedKLast, - TreasuryAmount: packedTreasuryAmount, - GasAccountIndex: txInfo.GasAccountIndex, - GasFeeAssetId: txInfo.GasFeeAssetId, - GasFeeAssetAmount: packedFee, - } - return info, nil -} diff --git a/common/prove/create_pair.go b/common/prove/create_pair.go deleted file mode 100644 index 827ae8144..000000000 --- a/common/prove/create_pair.go +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright © 2021 ZkBNB Protocol - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package prove - -import ( - cryptoTypes "github.com/bnb-chain/zkbnb-crypto/circuit/types" - "github.com/bnb-chain/zkbnb-crypto/wasm/txtypes" - "github.com/bnb-chain/zkbnb/dao/tx" - "github.com/bnb-chain/zkbnb/types" -) - -func (w *WitnessHelper) constructCreatePairTxWitness(cryptoTx *TxWitness, oTx *tx.Tx) (*TxWitness, error) { - txInfo, err := types.ParseCreatePairTxInfo(oTx.TxInfo) - if err != nil { - return nil, err - } - cryptoTxInfo, err := toCryptoCreatePairTx(txInfo) - if err != nil { - return nil, err - } - cryptoTx.CreatePairTxInfo = cryptoTxInfo - cryptoTx.Signature = cryptoTypes.EmptySignature() - return cryptoTx, nil -} - -func toCryptoCreatePairTx(txInfo *txtypes.CreatePairTxInfo) (info *cryptoTypes.CreatePairTx, err error) { - info = &cryptoTypes.CreatePairTx{ - PairIndex: txInfo.PairIndex, - AssetAId: txInfo.AssetAId, - AssetBId: txInfo.AssetBId, - FeeRate: txInfo.FeeRate, - TreasuryAccountIndex: txInfo.TreasuryAccountIndex, - TreasuryRate: txInfo.TreasuryRate, - } - return info, nil -} diff --git a/common/prove/deposit_nft.go b/common/prove/deposit_nft.go index 9af62669e..7451480cb 100644 --- a/common/prove/deposit_nft.go +++ b/common/prove/deposit_nft.go @@ -40,7 +40,6 @@ func (w *WitnessHelper) constructDepositNftTxWitness(cryptoTx *TxWitness, oTx *t func toCryptoDepositNftTx(txInfo *txtypes.DepositNftTxInfo) (info *cryptoTypes.DepositNftTx, err error) { info = &cryptoTypes.DepositNftTx{ - IsNewNft: txInfo.IsNewNft, AccountIndex: txInfo.AccountIndex, NftIndex: txInfo.NftIndex, NftL1Address: txInfo.NftL1Address, diff --git a/common/prove/proof_keys.go b/common/prove/proof_keys.go index 809176fa2..a93fd0843 100644 --- a/common/prove/proof_keys.go +++ b/common/prove/proof_keys.go @@ -64,7 +64,7 @@ func GenerateProof( if err != nil { return proof, err } - proof, err = groth16.Prove(r1cs, provingKey, witness, backend.WithHints(types.Keccak256, types.ComputeSLp)) + proof, err = groth16.Prove(r1cs, provingKey, witness, backend.WithHints(types.Keccak256)) if err != nil { return proof, err } diff --git a/common/prove/remove_liquidity.go b/common/prove/remove_liquidity.go deleted file mode 100644 index 7768d3c99..000000000 --- a/common/prove/remove_liquidity.go +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright © 2021 ZkBNB Protocol - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package prove - -import ( - "github.com/consensys/gnark-crypto/ecc/bn254/twistededwards/eddsa" - - cryptoTypes "github.com/bnb-chain/zkbnb-crypto/circuit/types" - "github.com/bnb-chain/zkbnb-crypto/wasm/txtypes" - "github.com/bnb-chain/zkbnb/common" - "github.com/bnb-chain/zkbnb/dao/tx" - "github.com/bnb-chain/zkbnb/types" -) - -func (w *WitnessHelper) constructRemoveLiquidityTxWitness(cryptoTx *TxWitness, oTx *tx.Tx) (*TxWitness, error) { - txInfo, err := types.ParseRemoveLiquidityTxInfo(oTx.TxInfo) - if err != nil { - return nil, err - } - cryptoTxInfo, err := toCryptoRemoveLiquidityTx(txInfo) - if err != nil { - return nil, err - } - cryptoTx.RemoveLiquidityTxInfo = cryptoTxInfo - cryptoTx.ExpiredAt = txInfo.ExpiredAt - cryptoTx.Signature = new(eddsa.Signature) - _, err = cryptoTx.Signature.SetBytes(txInfo.Sig) - if err != nil { - return nil, err - } - return cryptoTx, nil -} - -func toCryptoRemoveLiquidityTx(txInfo *txtypes.RemoveLiquidityTxInfo) (info *cryptoTypes.RemoveLiquidityTx, err error) { - packedAMinAmount, err := common.ToPackedAmount(txInfo.AssetAMinAmount) - if err != nil { - return nil, err - } - packedBMinAmount, err := common.ToPackedAmount(txInfo.AssetBMinAmount) - if err != nil { - return nil, err - } - packedAAmount, err := common.ToPackedAmount(txInfo.AssetAAmountDelta) - if err != nil { - return nil, err - } - packedBAmount, err := common.ToPackedAmount(txInfo.AssetBAmountDelta) - if err != nil { - return nil, err - } - packedLpAmount, err := common.ToPackedAmount(txInfo.LpAmount) - if err != nil { - return nil, err - } - packedKLast, err := common.ToPackedAmount(txInfo.KLast) - if err != nil { - return nil, err - } - packedTreasuryAmount, err := common.ToPackedAmount(txInfo.TreasuryAmount) - if err != nil { - return nil, err - } - packedFee, err := common.ToPackedFee(txInfo.GasFeeAssetAmount) - if err != nil { - return nil, err - } - info = &cryptoTypes.RemoveLiquidityTx{ - FromAccountIndex: txInfo.FromAccountIndex, - PairIndex: txInfo.PairIndex, - AssetAId: txInfo.AssetAId, - AssetAMinAmount: packedAMinAmount, - AssetBId: txInfo.AssetBId, - AssetBMinAmount: packedBMinAmount, - LpAmount: packedLpAmount, - KLast: packedKLast, - TreasuryAmount: packedTreasuryAmount, - AssetAAmountDelta: packedAAmount, - AssetBAmountDelta: packedBAmount, - GasAccountIndex: txInfo.GasAccountIndex, - GasFeeAssetId: txInfo.GasFeeAssetId, - GasFeeAssetAmount: packedFee, - } - return info, nil -} diff --git a/common/prove/swap.go b/common/prove/swap.go deleted file mode 100644 index 0c74675b7..000000000 --- a/common/prove/swap.go +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright © 2021 ZkBNB Protocol - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package prove - -import ( - "github.com/consensys/gnark-crypto/ecc/bn254/twistededwards/eddsa" - - cryptoTypes "github.com/bnb-chain/zkbnb-crypto/circuit/types" - "github.com/bnb-chain/zkbnb-crypto/wasm/txtypes" - "github.com/bnb-chain/zkbnb/common" - "github.com/bnb-chain/zkbnb/dao/tx" - "github.com/bnb-chain/zkbnb/types" -) - -func (w *WitnessHelper) constructSwapTxWitness(cryptoTx *TxWitness, oTx *tx.Tx) (*TxWitness, error) { - txInfo, err := types.ParseSwapTxInfo(oTx.TxInfo) - if err != nil { - return nil, err - } - cryptoTxInfo, err := toCryptoSwapTx(txInfo) - if err != nil { - return nil, err - } - cryptoTx.SwapTxInfo = cryptoTxInfo - cryptoTx.ExpiredAt = txInfo.ExpiredAt - cryptoTx.Signature = new(eddsa.Signature) - _, err = cryptoTx.Signature.SetBytes(txInfo.Sig) - if err != nil { - return nil, err - } - return cryptoTx, nil -} - -func toCryptoSwapTx(txInfo *txtypes.SwapTxInfo) (info *cryptoTypes.SwapTx, err error) { - packedAAmount, err := common.ToPackedAmount(txInfo.AssetAAmount) - if err != nil { - return nil, err - } - packedBMinAmount, err := common.ToPackedAmount(txInfo.AssetBMinAmount) - if err != nil { - return nil, err - } - packedBAmount, err := common.ToPackedAmount(txInfo.AssetBAmountDelta) - if err != nil { - return nil, err - } - packedFee, err := common.ToPackedFee(txInfo.GasFeeAssetAmount) - if err != nil { - return nil, err - } - info = &cryptoTypes.SwapTx{ - FromAccountIndex: txInfo.FromAccountIndex, - PairIndex: txInfo.PairIndex, - AssetAId: txInfo.AssetAId, - AssetAAmount: packedAAmount, - AssetBId: txInfo.AssetBId, - AssetBMinAmount: packedBMinAmount, - AssetBAmountDelta: packedBAmount, - GasAccountIndex: txInfo.GasAccountIndex, - GasFeeAssetId: txInfo.GasFeeAssetId, - GasFeeAssetAmount: packedFee, - } - return info, nil -} diff --git a/common/prove/types.go b/common/prove/types.go index 67e0d16d3..7120df119 100644 --- a/common/prove/types.go +++ b/common/prove/types.go @@ -26,21 +26,20 @@ import ( ) type ( - TxWitness = circuit.Tx + TxWitness = circuit.Tx + GasWitness = circuit.Gas ) const ( NbAccountAssetsPerAccount = ctypes.NbAccountAssetsPerAccount NbAccountsPerTx = ctypes.NbAccountsPerTx - AssetMerkleLevels = circuit.AssetMerkleLevels - LiquidityMerkleLevels = circuit.LiquidityMerkleLevels - NftMerkleLevels = circuit.NftMerkleLevels - AccountMerkleLevels = circuit.AccountMerkleLevels + AssetMerkleLevels = circuit.AssetMerkleLevels + NftMerkleLevels = circuit.NftMerkleLevels + AccountMerkleLevels = circuit.AccountMerkleLevels LastAccountIndex = circuit.LastAccountIndex LastAccountAssetId = circuit.LastAccountAssetId - LastPairIndex = circuit.LastPairIndex LastNftIndex = circuit.LastNftIndex ) @@ -50,11 +49,6 @@ type AccountWitnessInfo struct { AssetsRelatedTxDetails []*tx.TxDetail } -type LiquidityWitnessInfo struct { - LiquidityInfo *types.LiquidityInfo - LiquidityRelatedTxDetail *tx.TxDetail -} - type NftWitnessInfo struct { NftInfo *types.NftInfo NftRelatedTxDetail *tx.TxDetail diff --git a/common/prove/update_pairrate.go b/common/prove/update_pairrate.go deleted file mode 100644 index ddd096e6d..000000000 --- a/common/prove/update_pairrate.go +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright © 2021 ZkBNB Protocol - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package prove - -import ( - cryptoTypes "github.com/bnb-chain/zkbnb-crypto/circuit/types" - "github.com/bnb-chain/zkbnb-crypto/wasm/txtypes" - "github.com/bnb-chain/zkbnb/dao/tx" - "github.com/bnb-chain/zkbnb/types" -) - -func (w *WitnessHelper) constructUpdatePairRateTxWitness(cryptoTx *TxWitness, oTx *tx.Tx) (*TxWitness, error) { - txInfo, err := types.ParseUpdatePairRateTxInfo(oTx.TxInfo) - if err != nil { - return nil, err - } - cryptoTxInfo, err := toCryptoUpdatePairRateTx(txInfo) - if err != nil { - return nil, err - } - cryptoTx.UpdatePairRateTxInfo = cryptoTxInfo - cryptoTx.Signature = cryptoTypes.EmptySignature() - return cryptoTx, nil -} - -func toCryptoUpdatePairRateTx(txInfo *txtypes.UpdatePairRateTxInfo) (info *cryptoTypes.UpdatePairRateTx, err error) { - info = &cryptoTypes.UpdatePairRateTx{ - PairIndex: txInfo.PairIndex, - FeeRate: txInfo.FeeRate, - TreasuryAccountIndex: txInfo.TreasuryAccountIndex, - TreasuryRate: txInfo.TreasuryRate, - } - return info, nil -} diff --git a/common/prove/witness_helper.go b/common/prove/witness_helper.go index 7bdddf18d..efe6b4703 100644 --- a/common/prove/witness_helper.go +++ b/common/prove/witness_helper.go @@ -22,12 +22,16 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/zeromicro/go-zero/core/logx" + "github.com/bnb-chain/zkbnb-crypto/circuit" cryptoTypes "github.com/bnb-chain/zkbnb-crypto/circuit/types" + "github.com/bnb-chain/zkbnb-crypto/ffmath" bsmt "github.com/bnb-chain/zkbnb-smt" common2 "github.com/bnb-chain/zkbnb/common" "github.com/bnb-chain/zkbnb/common/chain" "github.com/bnb-chain/zkbnb/dao/account" + "github.com/bnb-chain/zkbnb/dao/block" "github.com/bnb-chain/zkbnb/dao/tx" "github.com/bnb-chain/zkbnb/tree" "github.com/bnb-chain/zkbnb/types" @@ -36,24 +40,26 @@ import ( type WitnessHelper struct { treeCtx *tree.Context - accountModel account.AccountModel + accountModel account.AccountModel + accountHistoryModel account.AccountHistoryModel + + gasAccountInfo *types.AccountInfo //gas account cache // Trees - accountTree bsmt.SparseMerkleTree - assetTrees *[]bsmt.SparseMerkleTree - liquidityTree bsmt.SparseMerkleTree - nftTree bsmt.SparseMerkleTree + accountTree bsmt.SparseMerkleTree + assetTrees *tree.AssetTreeCache + nftTree bsmt.SparseMerkleTree } -func NewWitnessHelper(treeCtx *tree.Context, accountTree, liquidityTree, nftTree bsmt.SparseMerkleTree, - assetTrees *[]bsmt.SparseMerkleTree, accountModel account.AccountModel) *WitnessHelper { +func NewWitnessHelper(treeCtx *tree.Context, accountTree, nftTree bsmt.SparseMerkleTree, + assetTrees *tree.AssetTreeCache, accountModel account.AccountModel, accountHistoryModel account.AccountHistoryModel) *WitnessHelper { return &WitnessHelper{ - treeCtx: treeCtx, - accountModel: accountModel, - accountTree: accountTree, - assetTrees: assetTrees, - liquidityTree: liquidityTree, - nftTree: nftTree, + treeCtx: treeCtx, + accountModel: accountModel, + accountHistoryModel: accountHistoryModel, + accountTree: accountTree, + assetTrees: assetTrees, + nftTree: nftTree, } } @@ -72,7 +78,7 @@ func (w *WitnessHelper) ConstructTxWitness(oTx *tx.Tx, finalityBlockNr uint64, } func (w *WitnessHelper) constructTxWitness(oTx *tx.Tx, finalityBlockNr uint64) (witness *TxWitness, err error) { - if oTx == nil || w.accountTree == nil || w.assetTrees == nil || w.liquidityTree == nil || w.nftTree == nil { + if oTx == nil || w.accountTree == nil || w.assetTrees == nil || w.nftTree == nil { return nil, fmt.Errorf("failed because of nil tx or tree") } witness, err = w.constructWitnessInfo(oTx, finalityBlockNr) @@ -84,22 +90,12 @@ func (w *WitnessHelper) constructTxWitness(oTx *tx.Tx, finalityBlockNr uint64) ( switch oTx.TxType { case types.TxTypeRegisterZns: return w.constructRegisterZnsTxWitness(witness, oTx) - case types.TxTypeCreatePair: - return w.constructCreatePairTxWitness(witness, oTx) - case types.TxTypeUpdatePairRate: - return w.constructUpdatePairRateTxWitness(witness, oTx) case types.TxTypeDeposit: return w.constructDepositTxWitness(witness, oTx) case types.TxTypeDepositNft: return w.constructDepositNftTxWitness(witness, oTx) case types.TxTypeTransfer: return w.constructTransferTxWitness(witness, oTx) - case types.TxTypeSwap: - return w.constructSwapTxWitness(witness, oTx) - case types.TxTypeAddLiquidity: - return w.constructAddLiquidityTxWitness(witness, oTx) - case types.TxTypeRemoveLiquidity: - return w.constructRemoveLiquidityTxWitness(witness, oTx) case types.TxTypeWithdraw: return w.constructWithdrawTxWitness(witness, oTx) case types.TxTypeCreateCollection: @@ -130,7 +126,7 @@ func (w *WitnessHelper) constructWitnessInfo( cryptoTx *TxWitness, err error, ) { - accountKeys, proverAccounts, proverLiquidityInfo, proverNftInfo, err := w.constructSimpleWitnessInfo(oTx) + accountKeys, proverAccounts, proverNftInfo, err := w.constructSimpleWitnessInfo(oTx) if err != nil { return nil, err } @@ -140,31 +136,22 @@ func (w *WitnessHelper) constructWitnessInfo( if err != nil { return nil, err } - // construct liquidity witness - liquidityRootBefore, liquidityBefore, merkleProofsLiquidityBefore, err := - w.constructLiquidityWitness(proverLiquidityInfo) - if err != nil { - return nil, err - } // construct nft witness nftRootBefore, nftBefore, merkleProofsNftBefore, err := w.constructNftWitness(proverNftInfo) if err != nil { return nil, err } - stateRootBefore := tree.ComputeStateRootHash(accountRootBefore, liquidityRootBefore, nftRootBefore) - stateRootAfter := tree.ComputeStateRootHash(w.accountTree.Root(), w.liquidityTree.Root(), w.nftTree.Root()) + stateRootBefore := tree.ComputeStateRootHash(accountRootBefore, nftRootBefore) + stateRootAfter := tree.ComputeStateRootHash(w.accountTree.Root(), w.nftTree.Root()) cryptoTx = &TxWitness{ AccountRootBefore: accountRootBefore, AccountsInfoBefore: accountsInfoBefore, - LiquidityRootBefore: liquidityRootBefore, - LiquidityBefore: liquidityBefore, NftRootBefore: nftRootBefore, NftBefore: nftBefore, StateRootBefore: stateRootBefore, MerkleProofsAccountAssetsBefore: merkleProofsAccountAssetsBefore, MerkleProofsAccountBefore: merkleProofsAccountBefore, - MerkleProofsLiquidityBefore: merkleProofsLiquidityBefore, MerkleProofsNftBefore: merkleProofsNftBefore, StateRootAfter: stateRootAfter, } @@ -178,7 +165,7 @@ func (w *WitnessHelper) constructAccountWitness( proverAccounts []*AccountWitnessInfo, ) ( accountRootBefore []byte, - // account before info, size is 5 + // account before info, size is 4 accountsInfoBefore [NbAccountsPerTx]*cryptoTypes.Account, // before account asset merkle proof merkleProofsAccountAssetsBefore [NbAccountsPerTx][NbAccountAssetsPerAccount][AssetMerkleLevels][]byte, @@ -203,15 +190,11 @@ func (w *WitnessHelper) constructAccountWitness( } // it means this is a registerZNS tx if proverAccounts == nil { - if accountKey != int64(len(*w.assetTrees)) { + if accountKey != w.assetTrees.GetNextAccountIndex() { return accountRootBefore, accountsInfoBefore, merkleProofsAccountAssetsBefore, merkleProofsAccountBefore, fmt.Errorf("invalid key") } - emptyAccountAssetTree, err := tree.NewEmptyAccountAssetTree(w.treeCtx, accountKey, finalityBlockNr) - if err != nil { - return accountRootBefore, accountsInfoBefore, merkleProofsAccountAssetsBefore, merkleProofsAccountBefore, err - } - *w.assetTrees = append(*w.assetTrees, emptyAccountAssetTree) + w.assetTrees.UpdateCache(accountKey, int64(finalityBlockNr)) cryptoAccount = cryptoTypes.EmptyAccount(accountKey, tree.NilAccountAssetRoot) // update account info accountInfo, err := w.accountModel.GetConfirmedAccountByIndex(accountKey) @@ -232,6 +215,20 @@ func (w *WitnessHelper) constructAccountWitness( Status: accountInfo.Status, }, }) + + // cache gas account + if accountKey == types.GasAccount { + w.gasAccountInfo = &types.AccountInfo{ + AccountIndex: accountInfo.AccountIndex, + AccountName: accountInfo.AccountName, + PublicKey: accountInfo.PublicKey, + AccountNameHash: accountInfo.AccountNameHash, + Nonce: types.EmptyNonce, + CollectionNonce: types.EmptyCollectionNonce, + AssetRoot: common.Bytes2Hex(tree.NilAccountAssetRoot), + AssetInfo: make(map[int64]*types.AccountAsset, 0), + } + } } else { proverAccountInfo := proverAccounts[accountCount] pk, err := common2.ParsePubKey(proverAccountInfo.AccountInfo.PublicKey) @@ -244,10 +241,10 @@ func (w *WitnessHelper) constructAccountWitness( AccountPk: pk, Nonce: proverAccountInfo.AccountInfo.Nonce, CollectionNonce: proverAccountInfo.AccountInfo.CollectionNonce, - AssetRoot: (*w.assetTrees)[accountKey].Root(), + AssetRoot: w.assetTrees.Get(accountKey).Root(), } for i, accountAsset := range proverAccountInfo.AccountAssets { - assetMerkleProof, err := (*w.assetTrees)[accountKey].GetProof(uint64(accountAsset.AssetId)) + assetMerkleProof, err := w.assetTrees.Get(accountKey).GetProof(uint64(accountAsset.AssetId)) if err != nil { return accountRootBefore, accountsInfoBefore, merkleProofsAccountAssetsBefore, merkleProofsAccountBefore, err } @@ -255,7 +252,6 @@ func (w *WitnessHelper) constructAccountWitness( cryptoAccount.AssetsInfo[assetCount] = &cryptoTypes.AccountAsset{ AssetId: accountAsset.AssetId, Balance: accountAsset.Balance, - LpAmount: accountAsset.LpAmount, OfferCanceledOrFinalized: accountAsset.OfferCanceledOrFinalized, } @@ -277,11 +273,11 @@ func (w *WitnessHelper) constructAccountWitness( if err != nil { return accountRootBefore, accountsInfoBefore, merkleProofsAccountAssetsBefore, merkleProofsAccountBefore, err } - nAssetHash, err := tree.ComputeAccountAssetLeafHash(nAsset.Balance.String(), nAsset.LpAmount.String(), nAsset.OfferCanceledOrFinalized.String()) + nAssetHash, err := tree.ComputeAccountAssetLeafHash(nAsset.Balance.String(), nAsset.OfferCanceledOrFinalized.String()) if err != nil { return accountRootBefore, accountsInfoBefore, merkleProofsAccountAssetsBefore, merkleProofsAccountBefore, err } - err = (*w.assetTrees)[accountKey].Set(uint64(accountAsset.AssetId), nAssetHash) + err = w.assetTrees.Get(accountKey).Set(uint64(accountAsset.AssetId), nAssetHash) if err != nil { return accountRootBefore, accountsInfoBefore, merkleProofsAccountAssetsBefore, merkleProofsAccountBefore, err } @@ -295,7 +291,7 @@ func (w *WitnessHelper) constructAccountWitness( // padding empty account asset for assetCount < NbAccountAssetsPerAccount { cryptoAccount.AssetsInfo[assetCount] = cryptoTypes.EmptyAccountAsset(LastAccountAssetId) - assetMerkleProof, err := (*w.assetTrees)[accountKey].GetProof(LastAccountAssetId) + assetMerkleProof, err := w.assetTrees.Get(accountKey).GetProof(LastAccountAssetId) if err != nil { return accountRootBefore, accountsInfoBefore, merkleProofsAccountAssetsBefore, merkleProofsAccountBefore, err } @@ -324,7 +320,7 @@ func (w *WitnessHelper) constructAccountWitness( proverAccounts[accountCount].AccountInfo.PublicKey, nonce, collectionNonce, - (*w.assetTrees)[accountKey].Root(), + w.assetTrees.Get(accountKey).Root(), ) if err != nil { return accountRootBefore, accountsInfoBefore, merkleProofsAccountAssetsBefore, merkleProofsAccountBefore, err @@ -333,6 +329,21 @@ func (w *WitnessHelper) constructAccountWitness( if err != nil { return accountRootBefore, accountsInfoBefore, merkleProofsAccountAssetsBefore, merkleProofsAccountBefore, err } + + // cache gas account + if accountKey == types.GasAccount { + w.gasAccountInfo.Nonce = nonce + w.gasAccountInfo.CollectionNonce = collectionNonce + w.gasAccountInfo.AssetRoot = common.Bytes2Hex(w.assetTrees.Get(accountKey).Root()) + for i := 0; i < NbAccountAssetsPerAccount; i++ { + w.gasAccountInfo.AssetInfo[cryptoAccount.AssetsInfo[i].AssetId] = &types.AccountAsset{ + AssetId: cryptoAccount.AssetsInfo[i].AssetId, + Balance: cryptoAccount.AssetsInfo[i].Balance, + OfferCanceledOrFinalized: cryptoAccount.AssetsInfo[i].OfferCanceledOrFinalized, + } + } + } + // set account info before accountsInfoBefore[accountCount] = cryptoAccount // add count @@ -374,84 +385,6 @@ func (w *WitnessHelper) constructAccountWitness( return accountRootBefore, accountsInfoBefore, merkleProofsAccountAssetsBefore, merkleProofsAccountBefore, nil } -func (w *WitnessHelper) constructLiquidityWitness( - proverLiquidityInfo *LiquidityWitnessInfo, -) ( - // liquidity root before - LiquidityRootBefore []byte, - // liquidity before - LiquidityBefore *cryptoTypes.Liquidity, - // before liquidity merkle proof - MerkleProofsLiquidityBefore [LiquidityMerkleLevels][]byte, - err error, -) { - LiquidityRootBefore = w.liquidityTree.Root() - if proverLiquidityInfo == nil { - liquidityMerkleProofs, err := w.liquidityTree.GetProof(LastPairIndex) - if err != nil { - return LiquidityRootBefore, LiquidityBefore, MerkleProofsLiquidityBefore, err - } - MerkleProofsLiquidityBefore, err = SetFixedLiquidityArray(liquidityMerkleProofs) - if err != nil { - return LiquidityRootBefore, LiquidityBefore, MerkleProofsLiquidityBefore, err - } - LiquidityBefore = cryptoTypes.EmptyLiquidity(LastPairIndex) - return LiquidityRootBefore, LiquidityBefore, MerkleProofsLiquidityBefore, nil - } - liquidityMerkleProofs, err := w.liquidityTree.GetProof(uint64(proverLiquidityInfo.LiquidityInfo.PairIndex)) - if err != nil { - return LiquidityRootBefore, LiquidityBefore, MerkleProofsLiquidityBefore, err - } - MerkleProofsLiquidityBefore, err = SetFixedLiquidityArray(liquidityMerkleProofs) - if err != nil { - return LiquidityRootBefore, LiquidityBefore, MerkleProofsLiquidityBefore, err - } - LiquidityBefore = &cryptoTypes.Liquidity{ - PairIndex: proverLiquidityInfo.LiquidityInfo.PairIndex, - AssetAId: proverLiquidityInfo.LiquidityInfo.AssetAId, - AssetA: proverLiquidityInfo.LiquidityInfo.AssetA, - AssetBId: proverLiquidityInfo.LiquidityInfo.AssetBId, - AssetB: proverLiquidityInfo.LiquidityInfo.AssetB, - LpAmount: proverLiquidityInfo.LiquidityInfo.LpAmount, - KLast: proverLiquidityInfo.LiquidityInfo.KLast, - FeeRate: proverLiquidityInfo.LiquidityInfo.FeeRate, - TreasuryAccountIndex: proverLiquidityInfo.LiquidityInfo.TreasuryAccountIndex, - TreasuryRate: proverLiquidityInfo.LiquidityInfo.TreasuryRate, - } - // update liquidity tree - nBalance, err := chain.ComputeNewBalance( - proverLiquidityInfo.LiquidityRelatedTxDetail.AssetType, - proverLiquidityInfo.LiquidityRelatedTxDetail.Balance, - proverLiquidityInfo.LiquidityRelatedTxDetail.BalanceDelta, - ) - if err != nil { - return LiquidityRootBefore, LiquidityBefore, MerkleProofsLiquidityBefore, err - } - nPoolInfo, err := types.ParseLiquidityInfo(nBalance) - if err != nil { - return LiquidityRootBefore, LiquidityBefore, MerkleProofsLiquidityBefore, err - } - nLiquidityHash, err := tree.ComputeLiquidityAssetLeafHash( - nPoolInfo.AssetAId, - nPoolInfo.AssetA.String(), - nPoolInfo.AssetBId, - nPoolInfo.AssetB.String(), - nPoolInfo.LpAmount.String(), - nPoolInfo.KLast.String(), - nPoolInfo.FeeRate, - nPoolInfo.TreasuryAccountIndex, - nPoolInfo.TreasuryRate, - ) - if err != nil { - return LiquidityRootBefore, LiquidityBefore, MerkleProofsLiquidityBefore, err - } - err = w.liquidityTree.Set(uint64(proverLiquidityInfo.LiquidityInfo.PairIndex), nLiquidityHash) - if err != nil { - return LiquidityRootBefore, LiquidityBefore, MerkleProofsLiquidityBefore, err - } - return LiquidityRootBefore, LiquidityBefore, MerkleProofsLiquidityBefore, nil -} - func (w *WitnessHelper) constructNftWitness( proverNftInfo *NftWitnessInfo, ) ( @@ -465,11 +398,11 @@ func (w *WitnessHelper) constructNftWitness( ) { nftRootBefore = w.nftTree.Root() if proverNftInfo == nil { - liquidityMerkleProofs, err := w.nftTree.GetProof(LastNftIndex) + nftMerkleProofs, err := w.nftTree.GetProof(LastNftIndex) if err != nil { return nftRootBefore, nftBefore, merkleProofsNftBefore, err } - merkleProofsNftBefore, err = SetFixedNftArray(liquidityMerkleProofs) + merkleProofsNftBefore, err = SetFixedNftArray(nftMerkleProofs) if err != nil { return nftRootBefore, nftBefore, merkleProofsNftBefore, err } @@ -498,7 +431,7 @@ func (w *WitnessHelper) constructNftWitness( CreatorTreasuryRate: proverNftInfo.NftInfo.CreatorTreasuryRate, CollectionId: proverNftInfo.NftInfo.CollectionId, } - // update liquidity tree + nBalance, err := chain.ComputeNewBalance( proverNftInfo.NftRelatedTxDetail.AssetType, proverNftInfo.NftRelatedTxDetail.Balance, @@ -550,14 +483,6 @@ func SetFixedAccountAssetArray(proof [][]byte) (res [AssetMerkleLevels][]byte, e return res, nil } -func SetFixedLiquidityArray(proof [][]byte) (res [LiquidityMerkleLevels][]byte, err error) { - if len(proof) != LiquidityMerkleLevels { - return res, fmt.Errorf("invalid size") - } - copy(res[:], proof[:]) - return res, nil -} - func SetFixedNftArray(proof [][]byte) (res [NftMerkleLevels][]byte, err error) { if len(proof) != NftMerkleLevels { return res, fmt.Errorf("invalid size") @@ -569,7 +494,6 @@ func SetFixedNftArray(proof [][]byte) (res [NftMerkleLevels][]byte, err error) { func (w *WitnessHelper) constructSimpleWitnessInfo(oTx *tx.Tx) ( accountKeys []int64, accountWitnessInfo []*AccountWitnessInfo, - liquidityWitnessInfo *LiquidityWitnessInfo, nftWitnessInfo *NftWitnessInfo, err error, ) { @@ -585,13 +509,17 @@ func (w *WitnessHelper) constructSimpleWitnessInfo(oTx *tx.Tx) ( accountKeys = append(accountKeys, oTx.AccountIndex) } for _, txDetail := range oTx.TxDetails { + // if tx detail is from gas account + if txDetail.IsGas { + continue + } switch txDetail.AssetType { case types.FungibleAssetType: // get account info if accountMap[txDetail.AccountIndex] == nil { accountInfo, err := w.accountModel.GetConfirmedAccountByIndex(txDetail.AccountIndex) if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, err } // get current nonce accountInfo.Nonce = txDetail.Nonce @@ -629,7 +557,7 @@ func (w *WitnessHelper) constructSimpleWitnessInfo(oTx *tx.Tx) ( // set account before info oAsset, err := types.ParseAccountAsset(txDetail.Balance) if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, err } accountWitnessInfo[accountCount].AccountAssets = append( accountWitnessInfo[accountCount].AccountAssets, @@ -642,7 +570,6 @@ func (w *WitnessHelper) constructSimpleWitnessInfo(oTx *tx.Tx) ( &types.AccountAsset{ AssetId: accountAssetMap[txDetail.AccountIndex][txDetail.AssetId].AssetId, Balance: accountAssetMap[txDetail.AccountIndex][txDetail.AssetId].Balance, - LpAmount: accountAssetMap[txDetail.AccountIndex][txDetail.AssetId].LpAmount, OfferCanceledOrFinalized: accountAssetMap[txDetail.AccountIndex][txDetail.AssetId].OfferCanceledOrFinalized, }, ) @@ -655,27 +582,19 @@ func (w *WitnessHelper) constructSimpleWitnessInfo(oTx *tx.Tx) ( // update asset info newBalance, err := chain.ComputeNewBalance(txDetail.AssetType, txDetail.Balance, txDetail.BalanceDelta) if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, err } nAsset, err := types.ParseAccountAsset(newBalance) if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, err } accountAssetMap[txDetail.AccountIndex][txDetail.AssetId] = nAsset - case types.LiquidityAssetType: - liquidityWitnessInfo = new(LiquidityWitnessInfo) - liquidityWitnessInfo.LiquidityRelatedTxDetail = txDetail - poolInfo, err := types.ParseLiquidityInfo(txDetail.Balance) - if err != nil { - return nil, nil, nil, nil, err - } - liquidityWitnessInfo.LiquidityInfo = poolInfo case types.NftAssetType: nftWitnessInfo = new(NftWitnessInfo) nftWitnessInfo.NftRelatedTxDetail = txDetail nftInfo, err := types.ParseNftInfo(txDetail.Balance) if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, err } nftWitnessInfo.NftInfo = nftInfo case types.CollectionNonceAssetType: @@ -683,7 +602,7 @@ func (w *WitnessHelper) constructSimpleWitnessInfo(oTx *tx.Tx) ( if accountMap[txDetail.AccountIndex] == nil { accountInfo, err := w.accountModel.GetConfirmedAccountByIndex(txDetail.AccountIndex) if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, err } // get current nonce accountInfo.Nonce = txDetail.Nonce @@ -713,9 +632,178 @@ func (w *WitnessHelper) constructSimpleWitnessInfo(oTx *tx.Tx) ( accountMap[txDetail.AccountIndex].CollectionNonce = txDetail.CollectionNonce } default: - return nil, nil, nil, nil, + return nil, nil, nil, fmt.Errorf("invalid asset type") } } - return accountKeys, accountWitnessInfo, liquidityWitnessInfo, nftWitnessInfo, nil + return accountKeys, accountWitnessInfo, nftWitnessInfo, nil +} + +func (w *WitnessHelper) ConstructGasWitness(block *block.Block) (cryptoGas *GasWitness, err error) { + var gas *circuit.Gas + + needGas := false + gasChanges := make(map[int64]*big.Int) + for _, assetId := range types.GasAssets { + gasChanges[assetId] = types.ZeroBigInt + } + for _, tx := range block.Txs { + if types.IsL2Tx(tx.TxType) { + needGas = true + for _, txDetail := range tx.TxDetails { + if txDetail.IsGas { + assetDelta, err := types.ParseAccountAsset(txDetail.BalanceDelta) + if err != nil { + return nil, err + } + gasChanges[assetDelta.AssetId] = ffmath.Add(gasChanges[assetDelta.AssetId], assetDelta.Balance) + } + } + } + } + + gasAccountIndex := types.GasAccount + emptyAssetTree, err := tree.NewMemAccountAssetTree() + if err != nil { + return nil, err + } + if !needGas { // no need of gas for this block + accountInfoBefore := cryptoTypes.EmptyGasAccount(gasAccountIndex, tree.NilAccountAssetRoot) + accountMerkleProofs, err := w.accountTree.GetProof(uint64(gasAccountIndex)) + if err != nil { + return nil, err + } + merkleProofsAccountBefore, err := SetFixedAccountArray(accountMerkleProofs) + if err != nil { + return nil, err + } + merkleProofsAccountAssetsBefore := make([][AssetMerkleLevels][]byte, 0) + for _, assetId := range types.GasAssets { + accountInfoBefore.AssetsInfo = append(accountInfoBefore.AssetsInfo, cryptoTypes.EmptyAccountAsset(assetId)) + assetMerkleProof, err := emptyAssetTree.GetProof(uint64(assetId)) + if err != nil { + return nil, err + } + merkleProofsAccountAssetBefore, err := SetFixedAccountAssetArray(assetMerkleProof) + if err != nil { + return nil, err + } + merkleProofsAccountAssetsBefore = append(merkleProofsAccountAssetsBefore, merkleProofsAccountAssetBefore) + } + gas = &circuit.Gas{ + GasAssetCount: len(types.GasAssets), + AccountInfoBefore: accountInfoBefore, + MerkleProofsAccountBefore: merkleProofsAccountBefore, + MerkleProofsAccountAssetsBefore: merkleProofsAccountAssetsBefore, + } + } else { + pk, err := common2.ParsePubKey(w.gasAccountInfo.PublicKey) + if err != nil { + return nil, err + } + accountInfoBefore := &cryptoTypes.GasAccount{ + AccountIndex: gasAccountIndex, + AccountNameHash: common.FromHex(w.gasAccountInfo.AccountNameHash), + AccountPk: pk, + Nonce: w.gasAccountInfo.Nonce, + CollectionNonce: w.gasAccountInfo.CollectionNonce, + AssetRoot: w.assetTrees.Get(gasAccountIndex).Root(), + } + logx.Infof("old gas account asset root: %s", common.Bytes2Hex(w.assetTrees.Get(gasAccountIndex).Root())) + + accountMerkleProofs, err := w.accountTree.GetProof(uint64(gasAccountIndex)) + if err != nil { + return nil, err + } + merkleProofsAccountBefore, err := SetFixedAccountArray(accountMerkleProofs) + if err != nil { + return nil, err + } + merkleProofsAccountAssetsBefore := make([][AssetMerkleLevels][]byte, 0) + for _, assetId := range types.GasAssets { + assetMerkleProof, err := w.assetTrees.Get(gasAccountIndex).GetProof(uint64(assetId)) + if err != nil { + return nil, err + } + balanceBefore := types.ZeroBigInt + offerCanceledOrFinalized := types.ZeroBigInt + if asset, ok := w.gasAccountInfo.AssetInfo[assetId]; ok { + balanceBefore = asset.Balance + offerCanceledOrFinalized = asset.OfferCanceledOrFinalized + } + accountInfoBefore.AssetsInfo = append(accountInfoBefore.AssetsInfo, &cryptoTypes.AccountAsset{ + AssetId: assetId, + Balance: balanceBefore, + OfferCanceledOrFinalized: offerCanceledOrFinalized, + }) + + // set merkle proof + merkleProofsAccountAssetBefore, err := SetFixedAccountAssetArray(assetMerkleProof) + if err != nil { + return nil, err + } + merkleProofsAccountAssetsBefore = append(merkleProofsAccountAssetsBefore, merkleProofsAccountAssetBefore) + + balanceAfter := ffmath.Add(balanceBefore, gasChanges[assetId]) + nAssetHash, err := tree.ComputeAccountAssetLeafHash(balanceAfter.String(), offerCanceledOrFinalized.String()) + if err != nil { + return nil, err + } + err = w.assetTrees.Get(gasAccountIndex).Set(uint64(assetId), nAssetHash) + if err != nil { + return nil, err + } + + } + logx.Infof("new gas account asset root: %s", common.Bytes2Hex(w.assetTrees.Get(gasAccountIndex).Root())) + + nAccountHash, err := tree.ComputeAccountLeafHash( + w.gasAccountInfo.AccountNameHash, + w.gasAccountInfo.PublicKey, + w.gasAccountInfo.Nonce, + w.gasAccountInfo.CollectionNonce, + w.assetTrees.Get(gasAccountIndex).Root(), + ) + if err != nil { + return nil, err + } + err = w.accountTree.Set(uint64(gasAccountIndex), nAccountHash) + if err != nil { + return nil, err + } + gas = &circuit.Gas{ + GasAssetCount: len(types.GasAssets), + AccountInfoBefore: accountInfoBefore, + MerkleProofsAccountBefore: merkleProofsAccountBefore, + MerkleProofsAccountAssetsBefore: merkleProofsAccountAssetsBefore, + } + } + + return gas, nil +} + +func (w *WitnessHelper) ResetCache(height int64) error { + w.gasAccountInfo = nil + history, err := w.accountHistoryModel.GetLatestAccountHistory(types.GasAccount, height) + if err != nil && err != types.DbErrNotFound { + return err + } + + if history != nil { + gasAccount, err := w.accountModel.GetConfirmedAccountByIndex(types.GasAccount) + if err != nil && err != types.DbErrNotFound { + return err + } + gasAccount.Nonce = history.Nonce + gasAccount.CollectionNonce = history.CollectionNonce + gasAccount.AssetInfo = history.AssetInfo + gasAccount.AssetRoot = history.AssetRoot + formatGasAccount, err := chain.ToFormatAccountInfo(gasAccount) + if err != nil { + return err + } + + w.gasAccountInfo = formatGasAccount + } + return nil } diff --git a/common/prove/witness_test.go b/common/prove/witness_test.go index 5213a2192..84b9d1e89 100644 --- a/common/prove/witness_test.go +++ b/common/prove/witness_test.go @@ -33,25 +33,24 @@ import ( "github.com/bnb-chain/zkbnb/dao/account" "github.com/bnb-chain/zkbnb/dao/block" "github.com/bnb-chain/zkbnb/dao/blockwitness" - "github.com/bnb-chain/zkbnb/dao/liquidity" "github.com/bnb-chain/zkbnb/dao/nft" "github.com/bnb-chain/zkbnb/tree" ) var ( - dsn = "host=localhost user=postgres password=ZkBNB@123 dbname=zkbnb port=5434 sslmode=disable" - blockModel block.BlockModel - witnessModel blockwitness.BlockWitnessModel - accountModel account.AccountModel - accountHistoryModel account.AccountHistoryModel - liquidityHistoryModel liquidity.LiquidityHistoryModel - nftHistoryModel nft.L2NftHistoryModel + dsn = "host=localhost user=postgres password=ZkBNB@123 dbname=zkbnb port=5434 sslmode=disable" + blockModel block.BlockModel + witnessModel blockwitness.BlockWitnessModel + accountModel account.AccountModel + accountHistoryModel account.AccountHistoryModel + nftHistoryModel nft.L2NftHistoryModel + assetTreeCacheSize = 512000 ) -func TestConstructTxWitness(t *testing.T) { +func TestConstructWitness(t *testing.T) { testDBSetup() defer testDBShutdown() - maxTestBlockHeight := int64(33) + maxTestBlockHeight := int64(49) for h := int64(1); h < maxTestBlockHeight; h++ { witnessHelper, err := getWitnessHelper(h - 1) assert.NoError(t, err) @@ -62,6 +61,8 @@ func TestConstructTxWitness(t *testing.T) { var cBlock circuit.Block err = json.Unmarshal([]byte(w.WitnessData), &cBlock) assert.NoError(t, err) + err = witnessHelper.ResetCache(h) + assert.NoError(t, err) for idx, tx := range b[0].Txs { txWitness, err := witnessHelper.ConstructTxWitness(tx, uint64(0)) assert.NoError(t, err) @@ -69,6 +70,11 @@ func TestConstructTxWitness(t *testing.T) { actualBz, _ := json.Marshal(txWitness) assert.Equal(t, string(actualBz), string(expectedBz), fmt.Sprintf("block %d, tx %d generate witness failed, tx type: %d", h, idx, tx.TxType)) } + gasWitness, err := witnessHelper.ConstructGasWitness(b[0]) + assert.NoError(t, err) + expectedBz, _ := json.Marshal(cBlock.Gas) + actualBz, _ := json.Marshal(gasWitness) + assert.Equal(t, string(actualBz), string(expectedBz), fmt.Sprintf("block %d, gas generate witness failed", h)) } } @@ -77,11 +83,7 @@ func getWitnessHelper(blockHeight int64) (*WitnessHelper, error) { Driver: tree.MemoryDB, TreeDB: memory.NewMemoryDB(), } - accountTree, accountAssetTrees, err := tree.InitAccountTree(accountModel, accountHistoryModel, blockHeight, ctx) - if err != nil { - return nil, err - } - liquidityTree, err := tree.InitLiquidityTree(liquidityHistoryModel, blockHeight, ctx) + accountTree, accountAssetTrees, err := tree.InitAccountTree(accountModel, accountHistoryModel, blockHeight, ctx, assetTreeCacheSize) if err != nil { return nil, err } @@ -91,10 +93,10 @@ func getWitnessHelper(blockHeight int64) (*WitnessHelper, error) { } return NewWitnessHelper(ctx, accountTree, - liquidityTree, nftTree, - &accountAssetTrees, - accountModel), nil + accountAssetTrees, + accountModel, + accountHistoryModel), nil } func testDBSetup() { @@ -102,17 +104,16 @@ func testDBSetup() { time.Sleep(5 * time.Second) cmd := exec.Command("docker", "run", "--name", "postgres-ut-witness", "-p", "5434:5432", "-e", "POSTGRES_PASSWORD=ZkBNB@123", "-e", "POSTGRES_USER=postgres", "-e", "POSTGRES_DB=zkbnb", - "-e", "PGDATA=/var/lib/postgresql/pgdata", "-d", "ghcr.io/bnb-chain/zkbnb/zkbnb-ut-postgres:0.0.2") + "-e", "PGDATA=/var/lib/postgresql/pgdata", "-d", "ghcr.io/bnb-chain/zkbnb/zkbnb-ut-postgres:blockgas") if err := cmd.Run(); err != nil { panic(err) } - time.Sleep(5 * time.Second) + time.Sleep(15 * time.Second) db, _ := gorm.Open(postgres.Open(dsn), &gorm.Config{}) blockModel = block.NewBlockModel(db) witnessModel = blockwitness.NewBlockWitnessModel(db) accountModel = account.NewAccountModel(db) accountHistoryModel = account.NewAccountHistoryModel(db) - liquidityHistoryModel = liquidity.NewLiquidityHistoryModel(db) nftHistoryModel = nft.NewL2NftHistoryModel(db) } diff --git a/core/blockchain.go b/core/blockchain.go index 7d660d3ba..88676ac27 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -22,7 +22,6 @@ import ( "github.com/bnb-chain/zkbnb/dao/block" "github.com/bnb-chain/zkbnb/dao/compressedblock" "github.com/bnb-chain/zkbnb/dao/dbcache" - "github.com/bnb-chain/zkbnb/dao/liquidity" "github.com/bnb-chain/zkbnb/dao/nft" "github.com/bnb-chain/zkbnb/dao/sysconfig" "github.com/bnb-chain/zkbnb/dao/tx" @@ -45,7 +44,8 @@ type ChainConfig struct { //nolint:staticcheck LevelDBOption tree.LevelDBOption `json:",optional"` //nolint:staticcheck - RedisDBOption tree.RedisDBOption `json:",optional"` + RedisDBOption tree.RedisDBOption `json:",optional"` + AssetTreeCacheSize int } } @@ -93,7 +93,7 @@ func NewBlockChain(config *ChainConfig, moduleName string) (*BlockChain, error) RedisDBOption: &config.TreeDB.RedisDBOption, } - bc.Statedb, err = sdb.NewStateDB(treeCtx, bc.ChainDB, redisCache, &config.CacheConfig, bc.currentBlock.StateRoot, curHeight) + bc.Statedb, err = sdb.NewStateDB(treeCtx, bc.ChainDB, redisCache, &config.CacheConfig, config.TreeDB.AssetTreeCacheSize, bc.currentBlock.StateRoot, curHeight) if err != nil { return nil, err } @@ -109,12 +109,11 @@ func NewBlockChain(config *ChainConfig, moduleName string) (*BlockChain, error) // NewBlockChainForDryRun - for dry run mode, we can reuse existing models for quick creation // , e.g., for sending tx, we can create blockchain for each request quickly -func NewBlockChainForDryRun(accountModel account.AccountModel, liquidityModel liquidity.LiquidityModel, +func NewBlockChainForDryRun(accountModel account.AccountModel, nftModel nft.L2NftModel, txPoolModel tx.TxPoolModel, assetModel asset.AssetModel, sysConfigModel sysconfig.SysConfigModel, redisCache dbcache.Cache) (*BlockChain, error) { chainDb := &sdb.ChainDB{ AccountModel: accountModel, - LiquidityModel: liquidityModel, L2NftModel: nftModel, TxPoolModel: txPoolModel, L2AssetInfoModel: assetModel, @@ -164,38 +163,29 @@ func (bc *BlockChain) CommitNewBlock(blockSize int, createdAt int64) (*block.Blo } currentHeight := bc.currentBlock.BlockHeight - err = tree.CommitTrees(bc.taskPool, uint64(currentHeight), bc.Statedb.AccountTree, &bc.Statedb.AccountAssetTrees, bc.Statedb.LiquidityTree, bc.Statedb.NftTree) - if err != nil { - return nil, err - } - pendingNewAccount, pendingUpdateAccount, pendingNewAccountHistory, err := bc.Statedb.GetPendingAccount(currentHeight) + err = tree.CommitTrees(bc.taskPool, uint64(currentHeight), bc.Statedb.AccountTree, bc.Statedb.AccountAssetTrees, bc.Statedb.NftTree) if err != nil { return nil, err } - pendingNewLiquidity, pendingUpdateLiquidity, pendingNewLiquidityHistory, err := bc.Statedb.GetPendingLiquidity(currentHeight) + pendingAccount, pendingAccountHistory, err := bc.Statedb.GetPendingAccount(currentHeight) if err != nil { return nil, err } - pendingNewNft, pendingUpdateNft, pendingNewNftHistory, err := bc.Statedb.GetPendingNft(currentHeight) + pendingNft, pendingNftHistory, err := bc.Statedb.GetPendingNft(currentHeight) if err != nil { return nil, err } return &block.BlockStates{ - Block: newBlock, - CompressedBlock: compressedBlock, - PendingNewAccount: pendingNewAccount, - PendingUpdateAccount: pendingUpdateAccount, - PendingNewAccountHistory: pendingNewAccountHistory, - PendingNewLiquidity: pendingNewLiquidity, - PendingUpdateLiquidity: pendingUpdateLiquidity, - PendingNewLiquidityHistory: pendingNewLiquidityHistory, - PendingNewNft: pendingNewNft, - PendingUpdateNft: pendingUpdateNft, - PendingNewNftHistory: pendingNewNftHistory, + Block: newBlock, + CompressedBlock: compressedBlock, + PendingAccount: pendingAccount, + PendingAccountHistory: pendingAccountHistory, + PendingNft: pendingNft, + PendingNftHistory: pendingNftHistory, }, nil } diff --git a/core/executor/add_liquidity_executor.go b/core/executor/add_liquidity_executor.go deleted file mode 100644 index abed5e953..000000000 --- a/core/executor/add_liquidity_executor.go +++ /dev/null @@ -1,549 +0,0 @@ -package executor - -import ( - "bytes" - "encoding/json" - "math/big" - - "github.com/pkg/errors" - "github.com/zeromicro/go-zero/core/logx" - - "github.com/bnb-chain/zkbnb-crypto/ffmath" - "github.com/bnb-chain/zkbnb-crypto/wasm/txtypes" - common2 "github.com/bnb-chain/zkbnb/common" - "github.com/bnb-chain/zkbnb/common/chain" - "github.com/bnb-chain/zkbnb/dao/liquidity" - "github.com/bnb-chain/zkbnb/dao/tx" - "github.com/bnb-chain/zkbnb/types" -) - -type AddLiquidityExecutor struct { - BaseExecutor - - txInfo *txtypes.AddLiquidityTxInfo - - newPoolInfo *types.LiquidityInfo - lpDeltaForFromAccount *big.Int -} - -func NewAddLiquidityExecutor(bc IBlockchain, tx *tx.Tx) (TxExecutor, error) { - txInfo, err := types.ParseAddLiquidityTxInfo(tx.TxInfo) - if err != nil { - logx.Errorf("parse transfer tx failed: %s", err.Error()) - return nil, errors.New("invalid tx info") - } - - return &AddLiquidityExecutor{ - BaseExecutor: NewBaseExecutor(bc, tx, txInfo), - txInfo: txInfo, - }, nil -} - -func (e *AddLiquidityExecutor) Prepare() error { - txInfo := e.txInfo - - err := e.bc.StateDB().PrepareLiquidity(txInfo.PairIndex) - if err != nil { - logx.Errorf("prepare liquidity failed: %s", err.Error()) - return errors.New("internal error") - } - - // Add the right details to tx info. - err = e.fillTxInfo() - if err != nil { - return err - } - - // Mark the tree states that would be affected in this executor. - e.MarkLiquidityDirty(txInfo.PairIndex) - e.MarkAccountAssetsDirty(txInfo.FromAccountIndex, []int64{txInfo.GasFeeAssetId, txInfo.AssetAId, txInfo.AssetBId, txInfo.PairIndex}) - liquidity, err := e.bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return err - } - e.MarkAccountAssetsDirty(liquidity.TreasuryAccountIndex, []int64{txInfo.PairIndex}) - e.MarkAccountAssetsDirty(txInfo.GasAccountIndex, []int64{txInfo.GasFeeAssetId}) - err = e.BaseExecutor.Prepare() - if err != nil { - return err - } - - return nil -} - -func (e *AddLiquidityExecutor) VerifyInputs(skipGasAmtChk bool) error { - bc := e.bc - txInfo := e.txInfo - - err := e.BaseExecutor.VerifyInputs(skipGasAmtChk) - if err != nil { - return err - } - - fromAccount, err := bc.StateDB().GetFormatAccount(txInfo.FromAccountIndex) - if err != nil { - return err - } - if txInfo.GasFeeAssetId == txInfo.AssetAId { - deltaBalance := ffmath.Add(txInfo.AssetAAmount, txInfo.GasFeeAssetAmount) - if fromAccount.AssetInfo[txInfo.AssetAId].Balance.Cmp(deltaBalance) < 0 { - return errors.New("invalid asset amount") - } - if fromAccount.AssetInfo[txInfo.AssetBId].Balance.Cmp(txInfo.AssetBAmount) < 0 { - return errors.New("invalid asset amount") - } - } else if txInfo.GasFeeAssetId == txInfo.AssetBId { - deltaBalance := ffmath.Add(txInfo.AssetBAmount, txInfo.GasFeeAssetAmount) - if fromAccount.AssetInfo[txInfo.AssetBId].Balance.Cmp(deltaBalance) < 0 { - return errors.New("invalid asset amount") - } - if fromAccount.AssetInfo[txInfo.AssetAId].Balance.Cmp(txInfo.AssetAAmount) < 0 { - return errors.New("invalid asset amount") - } - } else { - if fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance.Cmp(txInfo.GasFeeAssetAmount) < 0 { - return errors.New("invalid gas asset amount") - } - if fromAccount.AssetInfo[txInfo.AssetAId].Balance.Cmp(txInfo.AssetAAmount) < 0 { - return errors.New("invalid asset amount") - } - if fromAccount.AssetInfo[txInfo.AssetBId].Balance.Cmp(txInfo.AssetBAmount) < 0 { - return errors.New("invalid asset amount") - } - } - - liquidityModel, err := bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return err - } - liquidityInfo, err := constructLiquidityInfo(liquidityModel) - if err != nil { - logx.Errorf("construct liquidity info error, err: %v", err) - return err - } - - if liquidityInfo.AssetA == nil || liquidityInfo.AssetB == nil { - return errors.New("invalid liquidity") - } - - return nil -} - -func (e *AddLiquidityExecutor) ApplyTransaction() error { - bc := e.bc - txInfo := e.txInfo - - // apply changes - fromAccount, err := bc.StateDB().GetFormatAccount(txInfo.FromAccountIndex) - if err != nil { - return err - } - gasAccount, err := bc.StateDB().GetFormatAccount(txInfo.GasAccountIndex) - if err != nil { - return err - } - liquidityModel, err := bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return err - } - treasuryAccount, err := bc.StateDB().GetFormatAccount(liquidityModel.TreasuryAccountIndex) - if err != nil { - return err - } - - fromAccount.AssetInfo[txInfo.AssetAId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.AssetAId].Balance, txInfo.AssetAAmount) - fromAccount.AssetInfo[txInfo.AssetBId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.AssetBId].Balance, txInfo.AssetBAmount) - fromAccount.AssetInfo[txInfo.PairIndex].LpAmount = ffmath.Add(fromAccount.AssetInfo[txInfo.PairIndex].LpAmount, e.lpDeltaForFromAccount) - treasuryAccount.AssetInfo[txInfo.PairIndex].LpAmount = ffmath.Add(treasuryAccount.AssetInfo[txInfo.PairIndex].LpAmount, txInfo.TreasuryAmount) - fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) - gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Add(gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) - fromAccount.Nonce++ - - stateCache := e.bc.StateDB() - stateCache.SetPendingUpdateAccount(fromAccount.AccountIndex, fromAccount) - stateCache.SetPendingUpdateAccount(treasuryAccount.AccountIndex, treasuryAccount) - stateCache.SetPendingUpdateAccount(gasAccount.AccountIndex, gasAccount) - stateCache.SetPendingUpdateLiquidity(txInfo.PairIndex, &liquidity.Liquidity{ - Model: liquidityModel.Model, - PairIndex: e.newPoolInfo.PairIndex, - AssetAId: liquidityModel.AssetAId, - AssetA: e.newPoolInfo.AssetA.String(), - AssetBId: liquidityModel.AssetBId, - AssetB: e.newPoolInfo.AssetB.String(), - LpAmount: e.newPoolInfo.LpAmount.String(), - KLast: e.newPoolInfo.KLast.String(), - FeeRate: e.newPoolInfo.FeeRate, - TreasuryAccountIndex: e.newPoolInfo.TreasuryAccountIndex, - TreasuryRate: e.newPoolInfo.TreasuryRate, - }) - return e.BaseExecutor.ApplyTransaction() -} - -func (e *AddLiquidityExecutor) fillTxInfo() error { - bc := e.bc - txInfo := e.txInfo - - liquidityModel, err := bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return err - } - - liquidityInfo, err := constructLiquidityInfo(liquidityModel) - if err != nil { - logx.Errorf("construct liquidity info error, err: %v", err) - return err - } - - if liquidityInfo.AssetA.Cmp(types.ZeroBigInt) == 0 { - txInfo.LpAmount, err = chain.ComputeEmptyLpAmount(txInfo.AssetAAmount, txInfo.AssetBAmount) - if err != nil { - logx.Errorf("[ComputeEmptyLpAmount] : %v", err) - return err - } - } else { - txInfo.LpAmount, err = chain.ComputeLpAmount(liquidityInfo, txInfo.AssetAAmount) - if err != nil { - return err - } - } - - txInfo.AssetAId = liquidityInfo.AssetAId - txInfo.AssetBId = liquidityInfo.AssetBId - - lpDeltaForTreasuryAccount, err := chain.ComputeSLp(liquidityInfo.AssetA, - liquidityInfo.AssetB, liquidityInfo.KLast, liquidityInfo.FeeRate, liquidityInfo.TreasuryRate) - if err != nil { - logx.Errorf("[ComputeSLp] err: %v", err) - return err - } - - // pool account pool info - finalPoolA := ffmath.Add(liquidityInfo.AssetA, txInfo.AssetAAmount) - finalPoolB := ffmath.Add(liquidityInfo.AssetB, txInfo.AssetBAmount) - - txInfo.TreasuryAmount = lpDeltaForTreasuryAccount - txInfo.KLast, err = common2.CleanPackedAmount(ffmath.Multiply(finalPoolA, finalPoolB)) - if err != nil { - return err - } - - txInfo.AssetAId = liquidityModel.AssetAId - txInfo.AssetBId = liquidityModel.AssetBId - - return nil -} - -func (e *AddLiquidityExecutor) GeneratePubData() error { - txInfo := e.txInfo - - var buf bytes.Buffer - buf.WriteByte(uint8(types.TxTypeAddLiquidity)) - buf.Write(common2.Uint32ToBytes(uint32(txInfo.FromAccountIndex))) - buf.Write(common2.Uint16ToBytes(uint16(txInfo.PairIndex))) - packedAssetAAmountBytes, err := common2.AmountToPackedAmountBytes(txInfo.AssetAAmount) - if err != nil { - logx.Errorf("unable to convert amount to packed amount: %s", err.Error()) - return err - } - buf.Write(packedAssetAAmountBytes) - packedAssetBAmountBytes, err := common2.AmountToPackedAmountBytes(txInfo.AssetBAmount) - if err != nil { - logx.Errorf("unable to convert amount to packed amount: %s", err.Error()) - return err - } - buf.Write(packedAssetBAmountBytes) - LpAmountBytes, err := common2.AmountToPackedAmountBytes(txInfo.LpAmount) - if err != nil { - logx.Errorf("unable to convert amount to packed amount: %s", err.Error()) - return err - } - buf.Write(LpAmountBytes) - KLastBytes, err := common2.AmountToPackedAmountBytes(txInfo.KLast) - if err != nil { - logx.Errorf("[ConvertTxToDepositPubData] unable to convert amount to packed amount: %s", err.Error()) - return err - } - buf.Write(KLastBytes) - chunk1 := common2.SuffixPaddingBufToChunkSize(buf.Bytes()) - buf.Reset() - treasuryAmountBytes, err := common2.AmountToPackedAmountBytes(txInfo.TreasuryAmount) - if err != nil { - logx.Errorf("unable to convert amount to packed amount: %s", err.Error()) - return err - } - buf.Write(treasuryAmountBytes) - buf.Write(common2.Uint32ToBytes(uint32(txInfo.GasAccountIndex))) - buf.Write(common2.Uint16ToBytes(uint16(txInfo.GasFeeAssetId))) - packedFeeBytes, err := common2.FeeToPackedFeeBytes(txInfo.GasFeeAssetAmount) - if err != nil { - logx.Errorf("unable to convert amount to packed fee amount: %s", err.Error()) - return err - } - buf.Write(packedFeeBytes) - chunk2 := common2.PrefixPaddingBufToChunkSize(buf.Bytes()) - buf.Reset() - buf.Write(chunk1) - buf.Write(chunk2) - buf.Write(common2.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common2.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common2.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common2.PrefixPaddingBufToChunkSize([]byte{})) - pubData := buf.Bytes() - - stateCache := e.bc.StateDB() - stateCache.PubData = append(stateCache.PubData, pubData...) - return nil -} - -func (e *AddLiquidityExecutor) GetExecutedTx() (*tx.Tx, error) { - txInfoBytes, err := json.Marshal(e.txInfo) - if err != nil { - logx.Errorf("unable to marshal tx, err: %s", err.Error()) - return nil, errors.New("unmarshal tx failed") - } - - e.tx.TxInfo = string(txInfoBytes) - e.tx.GasFeeAssetId = e.txInfo.GasFeeAssetId - e.tx.GasFee = e.txInfo.GasFeeAssetAmount.String() - e.tx.PairIndex = e.txInfo.PairIndex - e.tx.TxAmount = e.txInfo.LpAmount.String() - return e.BaseExecutor.GetExecutedTx() -} - -func (e *AddLiquidityExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { - txInfo := e.txInfo - - liquidityModel, err := e.bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return nil, err - } - liquidityInfo, err := constructLiquidityInfo(liquidityModel) - if err != nil { - logx.Errorf("construct liquidity info error, err: %v", err) - return nil, err - } - - copiedAccounts, err := e.bc.StateDB().DeepCopyAccounts([]int64{txInfo.FromAccountIndex, txInfo.GasAccountIndex, liquidityInfo.TreasuryAccountIndex}) - if err != nil { - return nil, err - } - - fromAccount := copiedAccounts[txInfo.FromAccountIndex] - gasAccount := copiedAccounts[txInfo.GasAccountIndex] - treasuryAccount := copiedAccounts[liquidityInfo.TreasuryAccountIndex] - - txDetails := make([]*tx.TxDetail, 0, 4) - // from account asset A - order := int64(0) - accountOrder := int64(0) - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.AssetAId, - AssetType: types.FungibleAssetType, - AccountIndex: txInfo.FromAccountIndex, - AccountName: fromAccount.AccountName, - Balance: fromAccount.AssetInfo[txInfo.AssetAId].String(), - BalanceDelta: types.ConstructAccountAsset( - txInfo.AssetAId, - ffmath.Neg(txInfo.AssetAAmount), - types.ZeroBigInt, - types.ZeroBigInt, - ).String(), - Order: order, - AccountOrder: accountOrder, - Nonce: fromAccount.Nonce, - CollectionNonce: fromAccount.CollectionNonce, - }) - fromAccount.AssetInfo[txInfo.AssetAId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.AssetAId].Balance, txInfo.AssetAAmount) - if fromAccount.AssetInfo[txInfo.AssetAId].Balance.Cmp(types.ZeroBigInt) < 0 { - return nil, errors.New("insufficient asset a balance") - } - - // from account asset B - order++ - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.AssetBId, - AssetType: types.FungibleAssetType, - AccountIndex: txInfo.FromAccountIndex, - AccountName: fromAccount.AccountName, - Balance: fromAccount.AssetInfo[txInfo.AssetBId].String(), - BalanceDelta: types.ConstructAccountAsset( - txInfo.AssetBId, - ffmath.Neg(txInfo.AssetBAmount), - types.ZeroBigInt, - types.ZeroBigInt, - ).String(), - Order: order, - AccountOrder: accountOrder, - Nonce: fromAccount.Nonce, - CollectionNonce: fromAccount.CollectionNonce, - }) - - fromAccount.AssetInfo[txInfo.AssetBId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.AssetBId].Balance, txInfo.AssetBAmount) - if fromAccount.AssetInfo[txInfo.AssetBId].Balance.Cmp(types.ZeroBigInt) < 0 { - return nil, errors.New("insufficient asset b balance") - } - - // from account asset gas - order++ - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.GasFeeAssetId, - AssetType: types.FungibleAssetType, - AccountIndex: txInfo.FromAccountIndex, - AccountName: fromAccount.AccountName, - Balance: fromAccount.AssetInfo[txInfo.GasFeeAssetId].String(), - BalanceDelta: types.ConstructAccountAsset( - txInfo.GasFeeAssetId, - ffmath.Neg(txInfo.GasFeeAssetAmount), - types.ZeroBigInt, - types.ZeroBigInt, - ).String(), - Order: order, - AccountOrder: accountOrder, - Nonce: fromAccount.Nonce, - CollectionNonce: fromAccount.CollectionNonce, - }) - - fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) - if fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance.Cmp(types.ZeroBigInt) < 0 { - return nil, errors.New("insufficient gas fee balance") - } - - // from account lp - poolLp := ffmath.Sub(liquidityInfo.LpAmount, txInfo.TreasuryAmount) - var lpDeltaForFromAccount *big.Int - if liquidityInfo.AssetA.Cmp(types.ZeroBigInt) == 0 { - lpDeltaForFromAccount, err = common2.CleanPackedAmount(new(big.Int).Sqrt(ffmath.Multiply(txInfo.AssetAAmount, txInfo.AssetBAmount))) - if err != nil { - logx.Errorf("unable to compute lp delta: %s", err.Error()) - return nil, err - } - } else { - lpDeltaForFromAccount, err = common2.CleanPackedAmount(ffmath.Div(ffmath.Multiply(txInfo.AssetAAmount, poolLp), liquidityInfo.AssetA)) - if err != nil { - logx.Errorf(" unable to compute lp delta: %s", err.Error()) - return nil, err - } - } - - order++ - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.PairIndex, - AssetType: types.FungibleAssetType, - AccountIndex: txInfo.FromAccountIndex, - AccountName: fromAccount.AccountName, - Balance: fromAccount.AssetInfo[txInfo.PairIndex].String(), - BalanceDelta: types.ConstructAccountAsset( - txInfo.PairIndex, - types.ZeroBigInt, - lpDeltaForFromAccount, - types.ZeroBigInt, - ).String(), - Order: order, - AccountOrder: accountOrder, - Nonce: fromAccount.Nonce, - CollectionNonce: fromAccount.CollectionNonce, - }) - e.lpDeltaForFromAccount = lpDeltaForFromAccount - fromAccount.AssetInfo[txInfo.PairIndex].LpAmount = ffmath.Add(fromAccount.AssetInfo[txInfo.PairIndex].LpAmount, lpDeltaForFromAccount) - - // pool info - liquidity, err := e.bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return nil, err - } - basePool, err := types.ConstructLiquidityInfo( - liquidity.PairIndex, - liquidity.AssetAId, - liquidity.AssetA, - liquidity.AssetBId, - liquidity.AssetB, - liquidity.LpAmount, - liquidity.KLast, - liquidity.FeeRate, - liquidity.TreasuryAccountIndex, - liquidity.TreasuryRate, - ) - if err != nil { - return nil, err - } - - finalPoolA := ffmath.Add(liquidityInfo.AssetA, txInfo.AssetAAmount) - finalPoolB := ffmath.Add(liquidityInfo.AssetB, txInfo.AssetBAmount) - poolDeltaForToAccount := &types.LiquidityInfo{ - PairIndex: txInfo.PairIndex, - AssetAId: txInfo.AssetAId, - AssetA: txInfo.AssetAAmount, - AssetBId: txInfo.AssetBId, - AssetB: txInfo.AssetAAmount, - LpAmount: lpDeltaForFromAccount, - KLast: ffmath.Multiply(finalPoolA, finalPoolB), - FeeRate: liquidityInfo.FeeRate, - TreasuryAccountIndex: liquidityInfo.TreasuryAccountIndex, - TreasuryRate: liquidityInfo.TreasuryRate, - } - newPool, err := chain.ComputeNewBalance(types.LiquidityAssetType, basePool.String(), poolDeltaForToAccount.String()) - if err != nil { - return nil, err - } - - newPoolInfo, err := types.ParseLiquidityInfo(newPool) - if err != nil { - return nil, err - } - e.newPoolInfo = newPoolInfo - - order++ - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.PairIndex, - AssetType: types.LiquidityAssetType, - AccountIndex: types.NilAccountIndex, - AccountName: types.NilAccountName, - Balance: basePool.String(), - BalanceDelta: poolDeltaForToAccount.String(), - Order: order, - Nonce: 0, - AccountOrder: types.NilAccountOrder, - CollectionNonce: 0, - }) - - // treasury account - order++ - accountOrder++ - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.PairIndex, - AssetType: types.FungibleAssetType, - AccountIndex: treasuryAccount.AccountIndex, - AccountName: treasuryAccount.AccountName, - Balance: treasuryAccount.AssetInfo[txInfo.PairIndex].String(), - BalanceDelta: types.ConstructAccountAsset( - txInfo.PairIndex, types.ZeroBigInt, txInfo.TreasuryAmount, types.ZeroBigInt, - ).String(), - Order: order, - Nonce: treasuryAccount.Nonce, - AccountOrder: accountOrder, - CollectionNonce: treasuryAccount.CollectionNonce, - }) - treasuryAccount.AssetInfo[txInfo.PairIndex].LpAmount = ffmath.Add(treasuryAccount.AssetInfo[txInfo.PairIndex].LpAmount, txInfo.TreasuryAmount) - - // gas account asset gas - order++ - accountOrder++ - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.GasFeeAssetId, - AssetType: types.FungibleAssetType, - AccountIndex: txInfo.GasAccountIndex, - AccountName: gasAccount.AccountName, - Balance: gasAccount.AssetInfo[txInfo.GasFeeAssetId].String(), - BalanceDelta: types.ConstructAccountAsset( - txInfo.GasFeeAssetId, - txInfo.GasFeeAssetAmount, - types.ZeroBigInt, - types.ZeroBigInt, - ).String(), - Order: order, - AccountOrder: accountOrder, - Nonce: gasAccount.Nonce, - CollectionNonce: gasAccount.CollectionNonce, - }) - return txDetails, nil -} diff --git a/core/executor/atomic_match_executor.go b/core/executor/atomic_match_executor.go index 4d08fa446..95a1d5e28 100644 --- a/core/executor/atomic_match_executor.go +++ b/core/executor/atomic_match_executor.go @@ -91,6 +91,17 @@ func (e *AtomicMatchExecutor) VerifyInputs(skipGasAmtChk bool) error { return errors.New("buy offer mismatches sell offer") } + // only gas assets are allowed for atomic match + found := false + for _, assetId := range types.GasAssets { + if assetId == txInfo.SellOffer.AssetId { + found = true + } + } + if !found { + return errors.New("invalid asset of offer") + } + // Check offer expired time. if err := e.bc.VerifyExpiredAt(txInfo.BuyOffer.ExpiredAt); err != nil { return errors.New("invalid BuyOffer.ExpiredAt") @@ -173,10 +184,6 @@ func (e *AtomicMatchExecutor) ApplyTransaction() error { if err != nil { return err } - gasAccount, err := bc.StateDB().GetFormatAccount(txInfo.GasAccountIndex) - if err != nil { - return err - } buyAccount, err := bc.StateDB().GetFormatAccount(txInfo.BuyOffer.AccountIndex) if err != nil { return err @@ -195,8 +202,6 @@ func (e *AtomicMatchExecutor) ApplyTransaction() error { sellAccount.AssetInfo[txInfo.SellOffer.AssetId].Balance = ffmath.Add(sellAccount.AssetInfo[txInfo.SellOffer.AssetId].Balance, ffmath.Sub( txInfo.BuyOffer.AssetAmount, ffmath.Add(txInfo.TreasuryAmount, txInfo.CreatorAmount))) creatorAccount.AssetInfo[txInfo.BuyOffer.AssetId].Balance = ffmath.Add(creatorAccount.AssetInfo[txInfo.BuyOffer.AssetId].Balance, txInfo.CreatorAmount) - gasAccount.AssetInfo[txInfo.BuyOffer.AssetId].Balance = ffmath.Add(gasAccount.AssetInfo[txInfo.BuyOffer.AssetId].Balance, txInfo.TreasuryAmount) - gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Add(gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) fromAccount.Nonce++ sellOffer := sellAccount.AssetInfo[e.sellOfferAssetId].OfferCanceledOrFinalized @@ -210,12 +215,13 @@ func (e *AtomicMatchExecutor) ApplyTransaction() error { matchNft.OwnerAccountIndex = txInfo.BuyOffer.AccountIndex stateCache := e.bc.StateDB() - stateCache.SetPendingUpdateAccount(fromAccount.AccountIndex, fromAccount) - stateCache.SetPendingUpdateAccount(buyAccount.AccountIndex, buyAccount) - stateCache.SetPendingUpdateAccount(sellAccount.AccountIndex, sellAccount) - stateCache.SetPendingUpdateAccount(gasAccount.AccountIndex, gasAccount) - stateCache.SetPendingUpdateAccount(creatorAccount.AccountIndex, creatorAccount) - stateCache.SetPendingUpdateNft(matchNft.NftIndex, matchNft) + stateCache.SetPendingAccount(fromAccount.AccountIndex, fromAccount) + stateCache.SetPendingAccount(buyAccount.AccountIndex, buyAccount) + stateCache.SetPendingAccount(sellAccount.AccountIndex, sellAccount) + stateCache.SetPendingAccount(creatorAccount.AccountIndex, creatorAccount) + stateCache.SetPendingNft(matchNft.NftIndex, matchNft) + stateCache.SetPendingUpdateGas(txInfo.BuyOffer.AssetId, txInfo.TreasuryAmount) + stateCache.SetPendingUpdateGas(txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount) return e.BaseExecutor.ApplyTransaction() } @@ -321,7 +327,7 @@ func (e *AtomicMatchExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { AccountName: fromAccount.AccountName, Balance: fromAccount.AssetInfo[txInfo.GasFeeAssetId].String(), BalanceDelta: types.ConstructAccountAsset( - txInfo.GasFeeAssetId, ffmath.Neg(txInfo.GasFeeAssetAmount), types.ZeroBigInt, types.ZeroBigInt).String(), + txInfo.GasFeeAssetId, ffmath.Neg(txInfo.GasFeeAssetAmount), types.ZeroBigInt).String(), Order: order, AccountOrder: accountOrder, Nonce: fromAccount.Nonce, @@ -339,7 +345,7 @@ func (e *AtomicMatchExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { AccountName: buyAccount.AccountName, Balance: buyAccount.AssetInfo[txInfo.BuyOffer.AssetId].String(), BalanceDelta: types.ConstructAccountAsset( - txInfo.BuyOffer.AssetId, ffmath.Neg(txInfo.BuyOffer.AssetAmount), types.ZeroBigInt, types.ZeroBigInt, + txInfo.BuyOffer.AssetId, ffmath.Neg(txInfo.BuyOffer.AssetAmount), types.ZeroBigInt, ).String(), Order: order, AccountOrder: accountOrder, @@ -359,7 +365,7 @@ func (e *AtomicMatchExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { AccountName: buyAccount.AccountName, Balance: buyAccount.AssetInfo[e.buyOfferAssetId].String(), BalanceDelta: types.ConstructAccountAsset( - e.buyOfferAssetId, types.ZeroBigInt, types.ZeroBigInt, buyOffer).String(), + e.buyOfferAssetId, types.ZeroBigInt, buyOffer).String(), Order: order, AccountOrder: accountOrder, Nonce: buyAccount.Nonce, @@ -378,7 +384,7 @@ func (e *AtomicMatchExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { AccountName: sellAccount.AccountName, Balance: sellAccount.AssetInfo[txInfo.SellOffer.AssetId].String(), BalanceDelta: types.ConstructAccountAsset( - txInfo.SellOffer.AssetId, sellDeltaAmount, types.ZeroBigInt, types.ZeroBigInt, + txInfo.SellOffer.AssetId, sellDeltaAmount, types.ZeroBigInt, ).String(), Order: order, AccountOrder: accountOrder, @@ -398,7 +404,7 @@ func (e *AtomicMatchExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { AccountName: sellAccount.AccountName, Balance: sellAccount.AssetInfo[e.sellOfferAssetId].String(), BalanceDelta: types.ConstructAccountAsset( - e.sellOfferAssetId, types.ZeroBigInt, types.ZeroBigInt, sellOffer).String(), + e.sellOfferAssetId, types.ZeroBigInt, sellOffer).String(), Order: order, AccountOrder: accountOrder, Nonce: sellAccount.Nonce, @@ -416,7 +422,7 @@ func (e *AtomicMatchExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { AccountName: creatorAccount.AccountName, Balance: creatorAccount.AssetInfo[txInfo.BuyOffer.AssetId].String(), BalanceDelta: types.ConstructAccountAsset( - txInfo.BuyOffer.AssetId, txInfo.CreatorAmount, types.ZeroBigInt, types.ZeroBigInt, + txInfo.BuyOffer.AssetId, txInfo.CreatorAmount, types.ZeroBigInt, ).String(), Order: order, AccountOrder: accountOrder, @@ -452,11 +458,12 @@ func (e *AtomicMatchExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { AccountName: gasAccount.AccountName, Balance: gasAccount.AssetInfo[txInfo.BuyOffer.AssetId].String(), BalanceDelta: types.ConstructAccountAsset( - txInfo.BuyOffer.AssetId, txInfo.TreasuryAmount, types.ZeroBigInt, types.ZeroBigInt).String(), + txInfo.BuyOffer.AssetId, txInfo.TreasuryAmount, types.ZeroBigInt).String(), Order: order, AccountOrder: accountOrder, Nonce: gasAccount.Nonce, CollectionNonce: gasAccount.CollectionNonce, + IsGas: true, }) gasAccount.AssetInfo[txInfo.BuyOffer.AssetId].Balance = ffmath.Add(gasAccount.AssetInfo[txInfo.BuyOffer.AssetId].Balance, txInfo.TreasuryAmount) @@ -469,11 +476,12 @@ func (e *AtomicMatchExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { AccountName: gasAccount.AccountName, Balance: gasAccount.AssetInfo[txInfo.GasFeeAssetId].String(), BalanceDelta: types.ConstructAccountAsset( - txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount, types.ZeroBigInt, types.ZeroBigInt).String(), + txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount, types.ZeroBigInt).String(), Order: order, AccountOrder: accountOrder, Nonce: gasAccount.Nonce, CollectionNonce: gasAccount.CollectionNonce, + IsGas: true, }) gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Add(gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) diff --git a/core/executor/base_executor.go b/core/executor/base_executor.go index f14889641..a38fb7cf8 100644 --- a/core/executor/base_executor.go +++ b/core/executor/base_executor.go @@ -23,7 +23,6 @@ type BaseExecutor struct { // Affected states. dirtyAccountsAndAssetsMap map[int64]map[int64]bool - dirtyLiquidityMap map[int64]bool dirtyNftMap map[int64]bool } @@ -34,7 +33,6 @@ func NewBaseExecutor(bc IBlockchain, tx *tx.Tx, txInfo txtypes.TxInfo) BaseExecu iTxInfo: txInfo, dirtyAccountsAndAssetsMap: make(map[int64]map[int64]bool, 0), - dirtyLiquidityMap: make(map[int64]bool, 0), dirtyNftMap: make(map[int64]bool, 0), } } @@ -139,10 +137,6 @@ func (e *BaseExecutor) MarkAccountAssetsDirty(accountIndex int64, assets []int64 } } -func (e *BaseExecutor) MarkLiquidityDirty(pairIndex int64) { - e.dirtyLiquidityMap[pairIndex] = true -} - func (e *BaseExecutor) MarkNftDirty(nftIndex int64) { e.dirtyNftMap[nftIndex] = true } @@ -156,10 +150,6 @@ func (e *BaseExecutor) SyncDirtyToStateCache() { e.bc.StateDB().MarkAccountAssetsDirty(accountIndex, assets) } - for pairIndex := range e.dirtyLiquidityMap { - e.bc.StateDB().MarkLiquidityDirty(pairIndex) - } - for nftIndex := range e.dirtyNftMap { e.bc.StateDB().MarkNftDirty(nftIndex) } diff --git a/core/executor/cancel_offer_executor.go b/core/executor/cancel_offer_executor.go index 04566697e..3ab06ba4a 100644 --- a/core/executor/cancel_offer_executor.go +++ b/core/executor/cancel_offer_executor.go @@ -82,13 +82,8 @@ func (e *CancelOfferExecutor) ApplyTransaction() error { if err != nil { return err } - gasAccount, err := bc.StateDB().GetFormatAccount(txInfo.GasAccountIndex) - if err != nil { - return err - } fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) - gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Add(gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) fromAccount.Nonce++ offerAssetId := txInfo.OfferId / OfferPerAsset @@ -98,8 +93,8 @@ func (e *CancelOfferExecutor) ApplyTransaction() error { fromAccount.AssetInfo[offerAssetId].OfferCanceledOrFinalized = nOffer stateCache := e.bc.StateDB() - stateCache.SetPendingUpdateAccount(fromAccount.AccountIndex, fromAccount) - stateCache.SetPendingUpdateAccount(gasAccount.AccountIndex, gasAccount) + stateCache.SetPendingAccount(fromAccount.AccountIndex, fromAccount) + stateCache.SetPendingUpdateGas(txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount) return e.BaseExecutor.ApplyTransaction() } @@ -171,7 +166,6 @@ func (e *CancelOfferExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { txInfo.GasFeeAssetId, ffmath.Neg(txInfo.GasFeeAssetAmount), types.ZeroBigInt, - types.ZeroBigInt, ).String(), Order: order, Nonce: fromAccount.Nonce, @@ -204,7 +198,6 @@ func (e *CancelOfferExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { BalanceDelta: types.ConstructAccountAsset( offerAssetId, types.ZeroBigInt, - types.ZeroBigInt, nOffer, ).String(), Order: order, @@ -227,12 +220,12 @@ func (e *CancelOfferExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount, types.ZeroBigInt, - types.ZeroBigInt, ).String(), Order: order, Nonce: gasAccount.Nonce, AccountOrder: accountOrder, CollectionNonce: gasAccount.CollectionNonce, + IsGas: true, }) return txDetails, nil } diff --git a/core/executor/create_collection_executor.go b/core/executor/create_collection_executor.go index 71ae8baaf..8fbf28464 100644 --- a/core/executor/create_collection_executor.go +++ b/core/executor/create_collection_executor.go @@ -81,20 +81,15 @@ func (e *CreateCollectionExecutor) ApplyTransaction() error { if err != nil { return err } - gasAccount, err := bc.StateDB().GetFormatAccount(txInfo.GasAccountIndex) - if err != nil { - return err - } // apply changes fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) - gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Add(gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) fromAccount.Nonce++ fromAccount.CollectionNonce++ stateCache := e.bc.StateDB() - stateCache.SetPendingUpdateAccount(fromAccount.AccountIndex, fromAccount) - stateCache.SetPendingUpdateAccount(gasAccount.AccountIndex, gasAccount) + stateCache.SetPendingAccount(fromAccount.AccountIndex, fromAccount) + stateCache.SetPendingUpdateGas(txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount) return e.BaseExecutor.ApplyTransaction() } @@ -184,7 +179,6 @@ func (e *CreateCollectionExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { txInfo.GasFeeAssetId, ffmath.Neg(txInfo.GasFeeAssetAmount), types.ZeroBigInt, - types.ZeroBigInt, ).String(), Order: order, Nonce: fromAccount.Nonce, @@ -209,11 +203,11 @@ func (e *CreateCollectionExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount, types.ZeroBigInt, - types.ZeroBigInt, ).String(), Order: order, Nonce: gasAccount.Nonce, AccountOrder: accountOrder, + IsGas: true, }) return txDetails, nil } diff --git a/core/executor/create_pair_executor.go b/core/executor/create_pair_executor.go deleted file mode 100644 index 25c66f699..000000000 --- a/core/executor/create_pair_executor.go +++ /dev/null @@ -1,153 +0,0 @@ -package executor - -import ( - "bytes" - "encoding/json" - "errors" - "math/big" - - "github.com/zeromicro/go-zero/core/logx" - "github.com/zeromicro/go-zero/core/stores/sqlx" - - "github.com/bnb-chain/zkbnb-crypto/wasm/txtypes" - "github.com/bnb-chain/zkbnb/common" - "github.com/bnb-chain/zkbnb/dao/liquidity" - "github.com/bnb-chain/zkbnb/dao/tx" - "github.com/bnb-chain/zkbnb/types" -) - -type CreatePairExecutor struct { - BaseExecutor - - txInfo *txtypes.CreatePairTxInfo -} - -func NewCreatePairExecutor(bc IBlockchain, tx *tx.Tx) (TxExecutor, error) { - txInfo, err := types.ParseCreatePairTxInfo(tx.TxInfo) - if err != nil { - logx.Errorf("parse create pair tx failed: %s", err.Error()) - return nil, errors.New("invalid tx info") - } - - return &CreatePairExecutor{ - BaseExecutor: NewBaseExecutor(bc, tx, txInfo), - txInfo: txInfo, - }, nil -} - -func (e *CreatePairExecutor) Prepare() error { - // Mark the tree states that would be affected in this executor. - e.MarkLiquidityDirty(e.txInfo.PairIndex) - return e.BaseExecutor.Prepare() -} - -func (e *CreatePairExecutor) VerifyInputs(skipGasAmtChk bool) error { - bc := e.bc - txInfo := e.txInfo - - _, err := bc.DB().LiquidityModel.GetLiquidityByIndex(txInfo.PairIndex) - if err != sqlx.ErrNotFound { - return errors.New("invalid pair index, already registered") - } - - for index := range bc.StateDB().PendingNewLiquidityMap { - if txInfo.PairIndex == index { - return errors.New("invalid pair index, already registered") - } - } - - return nil -} - -func (e *CreatePairExecutor) ApplyTransaction() error { - txInfo := e.txInfo - - newLiquidity := &liquidity.Liquidity{ - PairIndex: txInfo.PairIndex, - AssetAId: txInfo.AssetAId, - AssetA: types.ZeroBigIntString, - AssetBId: txInfo.AssetBId, - AssetB: types.ZeroBigIntString, - LpAmount: types.ZeroBigIntString, - KLast: types.ZeroBigIntString, - TreasuryAccountIndex: txInfo.TreasuryAccountIndex, - FeeRate: txInfo.FeeRate, - TreasuryRate: txInfo.TreasuryRate, - } - - stateCache := e.bc.StateDB() - stateCache.SetPendingNewLiquidity(txInfo.PairIndex, newLiquidity) - return e.BaseExecutor.ApplyTransaction() -} - -func (e *CreatePairExecutor) GeneratePubData() error { - txInfo := e.txInfo - - var buf bytes.Buffer - buf.WriteByte(uint8(types.TxTypeCreatePair)) - buf.Write(common.Uint16ToBytes(uint16(txInfo.PairIndex))) - buf.Write(common.Uint16ToBytes(uint16(txInfo.AssetAId))) - buf.Write(common.Uint16ToBytes(uint16(txInfo.AssetBId))) - buf.Write(common.Uint16ToBytes(uint16(txInfo.FeeRate))) - buf.Write(common.Uint32ToBytes(uint32(txInfo.TreasuryAccountIndex))) - buf.Write(common.Uint16ToBytes(uint16(txInfo.TreasuryRate))) - chunk := common.SuffixPaddingBufToChunkSize(buf.Bytes()) - buf.Reset() - buf.Write(chunk) - buf.Write(common.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common.PrefixPaddingBufToChunkSize([]byte{})) - pubData := buf.Bytes() - - stateCache := e.bc.StateDB() - stateCache.PriorityOperations++ - stateCache.PubDataOffset = append(stateCache.PubDataOffset, uint32(len(stateCache.PubData))) - stateCache.PubData = append(stateCache.PubData, pubData...) - return nil -} - -func (e *CreatePairExecutor) GetExecutedTx() (*tx.Tx, error) { - txInfoBytes, err := json.Marshal(e.txInfo) - if err != nil { - logx.Errorf("unable to marshal tx, err: %s", err.Error()) - return nil, errors.New("unmarshal tx failed") - } - - e.tx.TxInfo = string(txInfoBytes) - e.tx.PairIndex = e.txInfo.PairIndex - return e.BaseExecutor.GetExecutedTx() -} - -func (e *CreatePairExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { - txInfo := e.txInfo - baseLiquidity := types.EmptyLiquidityInfo(txInfo.PairIndex) - deltaLiquidity := &types.LiquidityInfo{ - PairIndex: txInfo.PairIndex, - AssetAId: txInfo.AssetAId, - AssetA: big.NewInt(0), - AssetBId: txInfo.AssetBId, - AssetB: big.NewInt(0), - LpAmount: big.NewInt(0), - KLast: big.NewInt(0), - FeeRate: txInfo.FeeRate, - TreasuryAccountIndex: txInfo.TreasuryAccountIndex, - TreasuryRate: txInfo.TreasuryRate, - } - - txDetail := &tx.TxDetail{ - AssetId: txInfo.PairIndex, - AssetType: types.LiquidityAssetType, - AccountIndex: types.NilAccountIndex, - AccountName: types.NilAccountName, - Balance: baseLiquidity.String(), - BalanceDelta: deltaLiquidity.String(), - Order: 0, - AccountOrder: types.NilAccountOrder, - Nonce: types.NilNonce, - CollectionNonce: types.NilCollectionNonce, - } - - return []*tx.TxDetail{txDetail}, nil -} diff --git a/core/executor/deposit_executor.go b/core/executor/deposit_executor.go index 108a57b3e..46ef44eed 100644 --- a/core/executor/deposit_executor.go +++ b/core/executor/deposit_executor.go @@ -41,24 +41,9 @@ func (e *DepositExecutor) Prepare() error { // The account index from txInfo isn't true, find account by account name hash. accountNameHash := common.Bytes2Hex(txInfo.AccountNameHash) - account, err := bc.DB().AccountModel.GetAccountByNameHash(accountNameHash) + account, err := bc.StateDB().GetAccountByNameHash(accountNameHash) if err != nil { - exist := false - for index := range bc.StateDB().PendingNewAccountMap { - tempAccount, err := bc.StateDB().GetAccount(index) - if err != nil { - continue - } - if accountNameHash == tempAccount.AccountNameHash { - account = tempAccount - exist = true - break - } - } - - if !exist { - return errors.New("invalid account name hash") - } + return err } // Set the right account index. @@ -90,7 +75,7 @@ func (e *DepositExecutor) ApplyTransaction() error { depositAccount.AssetInfo[txInfo.AssetId].Balance = ffmath.Add(depositAccount.AssetInfo[txInfo.AssetId].Balance, txInfo.AssetAmount) stateCache := e.bc.StateDB() - stateCache.SetPendingUpdateAccount(depositAccount.AccountIndex, depositAccount) + stateCache.SetPendingAccount(depositAccount.AccountIndex, depositAccount) return e.BaseExecutor.ApplyTransaction() } @@ -143,7 +128,6 @@ func (e *DepositExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { deltaBalance := &types.AccountAsset{ AssetId: txInfo.AssetId, Balance: txInfo.AssetAmount, - LpAmount: big.NewInt(0), OfferCanceledOrFinalized: big.NewInt(0), } txDetail := &tx.TxDetail{ diff --git a/core/executor/deposit_nft_executor.go b/core/executor/deposit_nft_executor.go index 1d973da0d..c5b502f53 100644 --- a/core/executor/deposit_nft_executor.go +++ b/core/executor/deposit_nft_executor.go @@ -20,8 +20,6 @@ type DepositNftExecutor struct { BaseExecutor txInfo *txtypes.DepositNftTxInfo - - isNewNft bool } func NewDepositNftExecutor(bc IBlockchain, tx *tx.Tx) (TxExecutor, error) { @@ -43,40 +41,18 @@ func (e *DepositNftExecutor) Prepare() error { // The account index from txInfo isn't true, find account by account name hash. accountNameHash := common.Bytes2Hex(txInfo.AccountNameHash) - account, err := bc.DB().AccountModel.GetAccountByNameHash(accountNameHash) + account, err := bc.StateDB().GetAccountByNameHash(accountNameHash) if err != nil { - exist := false - for index := range bc.StateDB().PendingNewAccountMap { - tempAccount, err := bc.StateDB().GetAccount(index) - if err != nil { - continue - } - if accountNameHash == tempAccount.AccountNameHash { - account = tempAccount - exist = true - break - } - } - - if !exist { - return errors.New("invalid account name hash") - } + return err } // Set the right account index. txInfo.AccountIndex = account.AccountIndex - // Check if it is a new nft, or it is a nft previously withdraw from layer2. - if txInfo.IsNewNft == 1 { - e.isNewNft = true - // Set new nft index for new nft. - txInfo.NftIndex = bc.StateDB().GetNextNftIndex() - } else { - _, err = e.bc.StateDB().PrepareNft(txInfo.NftIndex) - if err != nil { - logx.Errorf("prepare nft failed") - return err - } + _, err = e.bc.StateDB().PrepareNft(txInfo.NftIndex) + if err != nil { + logx.Errorf("prepare nft failed") + return err } // Mark the tree states that would be affected in this executor. @@ -90,9 +66,6 @@ func (e *DepositNftExecutor) VerifyInputs(skipGasAmtChk bool) error { txInfo := e.txInfo nft, err := bc.StateDB().GetNft(txInfo.NftIndex) - if e.isNewNft && nft == nil { - return nil - } if err != nil { return err } @@ -118,11 +91,7 @@ func (e *DepositNftExecutor) ApplyTransaction() error { } stateCache := e.bc.StateDB() - if e.isNewNft { - stateCache.SetPendingNewNft(txInfo.NftIndex, nft) - } else { - stateCache.SetPendingUpdateNft(txInfo.NftIndex, nft) - } + stateCache.SetPendingNft(txInfo.NftIndex, nft) return e.BaseExecutor.ApplyTransaction() } @@ -131,7 +100,6 @@ func (e *DepositNftExecutor) GeneratePubData() error { var buf bytes.Buffer buf.WriteByte(uint8(types.TxTypeDepositNft)) - buf.WriteByte(txInfo.IsNewNft) buf.Write(common2.Uint32ToBytes(uint32(txInfo.AccountIndex))) buf.Write(common2.Uint40ToBytes(txInfo.NftIndex)) buf.Write(common2.AddressStrToBytes(txInfo.NftL1Address)) @@ -185,7 +153,6 @@ func (e *DepositNftExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { deltaBalance := &types.AccountAsset{ AssetId: 0, Balance: big.NewInt(0), - LpAmount: big.NewInt(0), OfferCanceledOrFinalized: big.NewInt(0), } txDetails = append(txDetails, &tx.TxDetail{ diff --git a/core/executor/executor.go b/core/executor/executor.go index 19304bc2f..436f364cf 100644 --- a/core/executor/executor.go +++ b/core/executor/executor.go @@ -32,22 +32,12 @@ func NewTxExecutor(bc IBlockchain, tx *tx.Tx) (TxExecutor, error) { switch tx.TxType { case types.TxTypeRegisterZns: return NewRegisterZnsExecutor(bc, tx) - case types.TxTypeCreatePair: - return NewCreatePairExecutor(bc, tx) - case types.TxTypeUpdatePairRate: - return NewUpdatePairRateExecutor(bc, tx) case types.TxTypeDeposit: return NewDepositExecutor(bc, tx) case types.TxTypeDepositNft: return NewDepositNftExecutor(bc, tx) case types.TxTypeTransfer: return NewTransferExecutor(bc, tx) - case types.TxTypeSwap: - return NewSwapExecutor(bc, tx) - case types.TxTypeAddLiquidity: - return NewAddLiquidityExecutor(bc, tx) - case types.TxTypeRemoveLiquidity: - return NewRemoveLiquidityExecutor(bc, tx) case types.TxTypeWithdraw: return NewWithdrawExecutor(bc, tx) case types.TxTypeCreateCollection: diff --git a/core/executor/full_exit_executor.go b/core/executor/full_exit_executor.go index 4a5549b43..1215b567b 100644 --- a/core/executor/full_exit_executor.go +++ b/core/executor/full_exit_executor.go @@ -41,24 +41,9 @@ func (e *FullExitExecutor) Prepare() error { // The account index from txInfo isn't true, find account by account name hash. accountNameHash := common.Bytes2Hex(txInfo.AccountNameHash) - account, err := bc.DB().AccountModel.GetAccountByNameHash(accountNameHash) + account, err := bc.StateDB().GetAccountByNameHash(accountNameHash) if err != nil { - exist := false - for index := range bc.StateDB().PendingNewAccountMap { - tempAccount, err := bc.StateDB().GetAccount(index) - if err != nil { - continue - } - if accountNameHash == tempAccount.AccountNameHash { - account = tempAccount - exist = true - break - } - } - - if !exist { - return errors.New("invalid account name hash") - } + return err } // Set the right account index. @@ -96,7 +81,7 @@ func (e *FullExitExecutor) ApplyTransaction() error { if txInfo.AssetAmount.Cmp(types.ZeroBigInt) != 0 { stateCache := e.bc.StateDB() - stateCache.SetPendingUpdateAccount(txInfo.AccountIndex, exitAccount) + stateCache.SetPendingAccount(txInfo.AccountIndex, exitAccount) } return e.BaseExecutor.ApplyTransaction() } @@ -152,7 +137,6 @@ func (e *FullExitExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { deltaBalance := &types.AccountAsset{ AssetId: txInfo.AssetId, Balance: ffmath.Neg(txInfo.AssetAmount), - LpAmount: big.NewInt(0), OfferCanceledOrFinalized: big.NewInt(0), } txDetail := &tx.TxDetail{ diff --git a/core/executor/full_exit_nft_executor.go b/core/executor/full_exit_nft_executor.go index d6d09c9c8..30586cdb3 100644 --- a/core/executor/full_exit_nft_executor.go +++ b/core/executor/full_exit_nft_executor.go @@ -21,7 +21,8 @@ type FullExitNftExecutor struct { txInfo *txtypes.FullExitNftTxInfo - exitNft *nft.L2Nft + exitNft *nft.L2Nft + exitEmpty bool } func NewFullExitNftExecutor(bc IBlockchain, tx *tx.Tx) (TxExecutor, error) { @@ -43,24 +44,9 @@ func (e *FullExitNftExecutor) Prepare() error { // The account index from txInfo isn't true, find account by account name hash. accountNameHash := common.Bytes2Hex(txInfo.AccountNameHash) - account, err := bc.DB().AccountModel.GetAccountByNameHash(accountNameHash) + account, err := bc.StateDB().GetAccountByNameHash(accountNameHash) if err != nil { - exist := false - for index := range bc.StateDB().PendingNewAccountMap { - tempAccount, err := bc.StateDB().GetAccount(index) - if err != nil { - continue - } - if accountNameHash == tempAccount.AccountNameHash { - account = tempAccount - exist = true - break - } - } - - if !exist { - return errors.New("invalid account name hash") - } + return err } // Set the right account index. @@ -83,11 +69,11 @@ func (e *FullExitNftExecutor) Prepare() error { var isExitEmptyNft = true nft, err := e.bc.StateDB().PrepareNft(txInfo.NftIndex) - if err != nil { + if err != nil && err != types.DbErrNotFound { return err } - if nft.OwnerAccountIndex == account.AccountIndex { + if err == nil && nft.OwnerAccountIndex == account.AccountIndex { // Set the right nft if the owner is correct. exitNft = nft isExitEmptyNft = false @@ -95,9 +81,6 @@ func (e *FullExitNftExecutor) Prepare() error { // Mark the tree states that would be affected in this executor. e.MarkNftDirty(txInfo.NftIndex) - if exitNft.CreatorAccountIndex != types.NilAccountIndex { - e.MarkAccountAssetsDirty(exitNft.CreatorAccountIndex, []int64{}) - } e.MarkAccountAssetsDirty(txInfo.AccountIndex, []int64{0}) // Prepare asset 0 for generate an empty tx detail. err = e.BaseExecutor.Prepare() if err != nil { @@ -108,7 +91,7 @@ func (e *FullExitNftExecutor) Prepare() error { txInfo.CreatorAccountIndex = exitNft.CreatorAccountIndex txInfo.CreatorTreasuryRate = exitNft.CreatorTreasuryRate txInfo.CreatorAccountNameHash = common.FromHex(types.EmptyAccountNameHash) - if isExitEmptyNft { + if !isExitEmptyNft { creator, err := bc.StateDB().GetFormatAccount(exitNft.CreatorAccountIndex) if err != nil { return err @@ -121,45 +104,21 @@ func (e *FullExitNftExecutor) Prepare() error { txInfo.CollectionId = exitNft.CollectionId e.exitNft = exitNft + e.exitEmpty = isExitEmptyNft return nil } func (e *FullExitNftExecutor) VerifyInputs(skipGasAmtChk bool) error { - bc := e.bc - txInfo := e.txInfo - - nft, err := bc.StateDB().GetNft(txInfo.NftIndex) - if err != nil { - return err - } - if txInfo.AccountIndex != nft.OwnerAccountIndex { - // The check is not fully enough, just avoid explicit error. - if !bytes.Equal(txInfo.NftContentHash, common.FromHex(types.EmptyNftContentHash)) { - return errors.New("invalid nft content hash") - } - } else { - // The check is not fully enough, just avoid explicit error. - if !bytes.Equal(txInfo.NftContentHash, common.FromHex(nft.NftContentHash)) { - return errors.New("invalid nft content hash") - } - } - return nil } func (e *FullExitNftExecutor) ApplyTransaction() error { - bc := e.bc - txInfo := e.txInfo - oldNft, err := bc.StateDB().GetNft(txInfo.NftIndex) - if err != nil { - return err - } - if txInfo.AccountIndex != oldNft.OwnerAccountIndex { - // Do nothing. + if e.exitEmpty { return nil } // Set nft to empty nft. + txInfo := e.txInfo emptyNftInfo := types.EmptyNftInfo(txInfo.NftIndex) emptyNft := &nft.L2Nft{ NftIndex: emptyNftInfo.NftIndex, @@ -173,7 +132,7 @@ func (e *FullExitNftExecutor) ApplyTransaction() error { } stateCache := e.bc.StateDB() - stateCache.SetPendingUpdateNft(txInfo.NftIndex, emptyNft) + stateCache.SetPendingNft(txInfo.NftIndex, emptyNft) return e.BaseExecutor.ApplyTransaction() } @@ -238,7 +197,6 @@ func (e *FullExitNftExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { emptyDelta := &types.AccountAsset{ AssetId: 0, Balance: big.NewInt(0), - LpAmount: big.NewInt(0), OfferCanceledOrFinalized: big.NewInt(0), } txDetails = append(txDetails, &tx.TxDetail{ @@ -255,14 +213,10 @@ func (e *FullExitNftExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { }) // nft info order++ - oldNft, err := bc.StateDB().GetNft(txInfo.NftIndex) - if err != nil { - return nil, err - } emptyNft := types.EmptyNftInfo(txInfo.NftIndex) baseNft := emptyNft newNft := emptyNft - + oldNft, _ := bc.StateDB().GetNft(txInfo.NftIndex) if oldNft != nil { baseNft = types.ConstructNftInfo( oldNft.NftIndex, diff --git a/core/executor/mint_nft_executor.go b/core/executor/mint_nft_executor.go index 7cd69d4c6..5fd85c3da 100644 --- a/core/executor/mint_nft_executor.go +++ b/core/executor/mint_nft_executor.go @@ -89,19 +89,13 @@ func (e *MintNftExecutor) ApplyTransaction() error { if err != nil { return err } - gasAccount, err := bc.StateDB().GetFormatAccount(txInfo.GasAccountIndex) - if err != nil { - return err - } creatorAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Sub(creatorAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) - gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Add(gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) creatorAccount.Nonce++ stateCache := e.bc.StateDB() - stateCache.SetPendingUpdateAccount(txInfo.CreatorAccountIndex, creatorAccount) - stateCache.SetPendingUpdateAccount(txInfo.GasAccountIndex, gasAccount) - stateCache.SetPendingNewNft(txInfo.NftIndex, &nft.L2Nft{ + stateCache.SetPendingAccount(txInfo.CreatorAccountIndex, creatorAccount) + stateCache.SetPendingNft(txInfo.NftIndex, &nft.L2Nft{ NftIndex: txInfo.NftIndex, CreatorAccountIndex: txInfo.CreatorAccountIndex, OwnerAccountIndex: txInfo.ToAccountIndex, @@ -111,6 +105,7 @@ func (e *MintNftExecutor) ApplyTransaction() error { CreatorTreasuryRate: txInfo.CreatorTreasuryRate, CollectionId: txInfo.NftCollectionId, }) + stateCache.SetPendingUpdateGas(txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount) return e.BaseExecutor.ApplyTransaction() } @@ -189,7 +184,6 @@ func (e *MintNftExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { txInfo.GasFeeAssetId, ffmath.Neg(txInfo.GasFeeAssetAmount), types.ZeroBigInt, - types.ZeroBigInt, ).String(), Order: order, Nonce: creatorAccount.Nonce, @@ -214,7 +208,6 @@ func (e *MintNftExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { txInfo.GasFeeAssetId, types.ZeroBigInt, types.ZeroBigInt, - types.ZeroBigInt, ).String(), Order: order, Nonce: toAccount.Nonce, @@ -261,12 +254,12 @@ func (e *MintNftExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount, types.ZeroBigInt, - types.ZeroBigInt, ).String(), Order: order, Nonce: gasAccount.Nonce, AccountOrder: accountOrder, CollectionNonce: gasAccount.CollectionNonce, + IsGas: true, }) return txDetails, nil } diff --git a/core/executor/register_zns_executor.go b/core/executor/register_zns_executor.go index c19c8f01c..a381119dd 100644 --- a/core/executor/register_zns_executor.go +++ b/core/executor/register_zns_executor.go @@ -7,7 +7,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/zeromicro/go-zero/core/logx" - "github.com/zeromicro/go-zero/core/stores/sqlx" "github.com/bnb-chain/zkbnb-crypto/wasm/txtypes" common2 "github.com/bnb-chain/zkbnb/common" @@ -52,21 +51,11 @@ func (e *RegisterZnsExecutor) VerifyInputs(skipGasAmtChk bool) error { bc := e.bc txInfo := e.txInfo - _, err := bc.DB().AccountModel.GetAccountByName(txInfo.AccountName) - if err != sqlx.ErrNotFound { + _, err := bc.StateDB().GetAccountByName(txInfo.AccountName) + if err == nil { return errors.New("invalid account name, already registered") } - for index := range bc.StateDB().PendingNewAccountMap { - account, err := bc.StateDB().GetFormatAccount(index) - if err != nil { - continue - } - if txInfo.AccountName == account.AccountName { - return errors.New("invalid account name, already registered") - } - } - if txInfo.AccountIndex != bc.StateDB().GetNextAccountIndex() { return errors.New("invalid account index") } @@ -96,15 +85,10 @@ func (e *RegisterZnsExecutor) ApplyTransaction() error { return err } - emptyAssetTree, err := tree.NewEmptyAccountAssetTree(bc.StateDB().TreeCtx, txInfo.AccountIndex, uint64(bc.CurrentBlock().BlockHeight)) - if err != nil { - logx.Errorf("new empty account asset tree failed: %s", err.Error()) - return err - } - bc.StateDB().AccountAssetTrees = append(bc.StateDB().AccountAssetTrees, emptyAssetTree) + bc.StateDB().AccountAssetTrees.UpdateCache(txInfo.AccountIndex, bc.CurrentBlock().BlockHeight) stateCache := e.bc.StateDB() - stateCache.SetPendingNewAccount(txInfo.AccountIndex, formatAccount) + stateCache.SetPendingAccount(txInfo.AccountIndex, formatAccount) return e.BaseExecutor.ApplyTransaction() } diff --git a/core/executor/remove_liquidity_executor.go b/core/executor/remove_liquidity_executor.go deleted file mode 100644 index 3463cbb23..000000000 --- a/core/executor/remove_liquidity_executor.go +++ /dev/null @@ -1,523 +0,0 @@ -package executor - -import ( - "bytes" - "encoding/json" - "math/big" - - "github.com/pkg/errors" - "github.com/zeromicro/go-zero/core/logx" - - "github.com/bnb-chain/zkbnb-crypto/ffmath" - "github.com/bnb-chain/zkbnb-crypto/wasm/txtypes" - common2 "github.com/bnb-chain/zkbnb/common" - "github.com/bnb-chain/zkbnb/common/chain" - "github.com/bnb-chain/zkbnb/dao/liquidity" - "github.com/bnb-chain/zkbnb/dao/tx" - "github.com/bnb-chain/zkbnb/types" -) - -type RemoveLiquidityExecutor struct { - BaseExecutor - - txInfo *txtypes.RemoveLiquidityTxInfo - - newPoolInfo *types.LiquidityInfo -} - -func NewRemoveLiquidityExecutor(bc IBlockchain, tx *tx.Tx) (TxExecutor, error) { - txInfo, err := types.ParseRemoveLiquidityTxInfo(tx.TxInfo) - if err != nil { - logx.Errorf("parse transfer tx failed: %s", err.Error()) - return nil, errors.New("invalid tx info") - } - - return &RemoveLiquidityExecutor{ - BaseExecutor: NewBaseExecutor(bc, tx, txInfo), - txInfo: txInfo, - }, nil -} - -func (e *RemoveLiquidityExecutor) Prepare() error { - txInfo := e.txInfo - - err := e.bc.StateDB().PrepareLiquidity(txInfo.PairIndex) - if err != nil { - logx.Errorf("prepare liquidity failed: %s", err.Error()) - return err - } - err = e.bc.StateDB().PrepareAccountsAndAssets(map[int64]map[int64]bool{ - txInfo.FromAccountIndex: { - txInfo.PairIndex: true, - }, - }) - if err != nil { - return err - } - err = e.fillTxInfo() - if err != nil { - return err - } - - // Mark the tree states that would be affected in this executor. - e.MarkLiquidityDirty(txInfo.PairIndex) - e.MarkAccountAssetsDirty(txInfo.FromAccountIndex, []int64{txInfo.GasFeeAssetId, txInfo.AssetAId, txInfo.AssetBId, txInfo.PairIndex}) - liquidity, err := e.bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return err - } - e.MarkAccountAssetsDirty(liquidity.TreasuryAccountIndex, []int64{txInfo.PairIndex}) - e.MarkAccountAssetsDirty(txInfo.GasAccountIndex, []int64{txInfo.GasFeeAssetId}) - err = e.BaseExecutor.Prepare() - if err != nil { - return err - } - - return nil -} - -func (e *RemoveLiquidityExecutor) VerifyInputs(skipGasAmtChk bool) error { - bc := e.bc - txInfo := e.txInfo - - err := e.BaseExecutor.VerifyInputs(skipGasAmtChk) - if err != nil { - return err - } - - fromAccount, err := bc.StateDB().GetFormatAccount(txInfo.FromAccountIndex) - if err != nil { - return err - } - if fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance.Cmp(txInfo.GasFeeAssetAmount) < 0 { - return errors.New("invalid gas asset amount") - } - - liquidityModel, err := bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return err - } - liquidityInfo, err := constructLiquidityInfo(liquidityModel) - if err != nil { - logx.Errorf("construct liquidity info error, err: %v", err) - return err - } - if liquidityInfo.AssetA == nil || liquidityInfo.AssetA.Cmp(types.ZeroBigInt) == 0 || - liquidityInfo.AssetB == nil || liquidityInfo.AssetB.Cmp(types.ZeroBigInt) == 0 || - liquidityInfo.LpAmount == nil || liquidityInfo.LpAmount.Cmp(types.ZeroBigInt) == 0 { - return errors.New("invalid pool liquidity") - } - - return nil -} - -func (e *RemoveLiquidityExecutor) fillTxInfo() error { - bc := e.bc - txInfo := e.txInfo - - fromAccount, err := bc.StateDB().GetFormatAccount(txInfo.FromAccountIndex) - if err != nil { - return err - } - liquidityModel, err := bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return err - } - - liquidityInfo, err := constructLiquidityInfo(liquidityModel) - if err != nil { - logx.Errorf("construct liquidity info error, err: %v", err) - return err - } - - assetAAmount, assetBAmount, err := chain.ComputeRemoveLiquidityAmount(liquidityInfo, txInfo.LpAmount) - if err != nil { - return err - } - - if assetAAmount.Cmp(txInfo.AssetAMinAmount) < 0 || assetBAmount.Cmp(txInfo.AssetBMinAmount) < 0 { - return errors.New("invalid asset min amount") - } - - if fromAccount.AssetInfo[txInfo.PairIndex].LpAmount.Cmp(txInfo.LpAmount) < 0 { - return errors.New("invalid lp amount") - } - - txInfo.AssetAAmountDelta = assetAAmount - txInfo.AssetBAmountDelta = assetBAmount - txInfo.AssetAId = liquidityInfo.AssetAId - txInfo.AssetBId = liquidityInfo.AssetBId - - poolAssetADelta := ffmath.Neg(txInfo.AssetAAmountDelta) - poolAssetBDelta := ffmath.Neg(txInfo.AssetBAmountDelta) - finalPoolA := ffmath.Add(liquidityInfo.AssetA, poolAssetADelta) - finalPoolB := ffmath.Add(liquidityInfo.AssetB, poolAssetBDelta) - lpDeltaForTreasuryAccount, err := chain.ComputeSLp(liquidityInfo.AssetA, liquidityInfo.AssetB, liquidityInfo.KLast, liquidityInfo.FeeRate, liquidityInfo.TreasuryRate) - if err != nil { - return err - } - - // set tx info - txInfo.KLast, err = common2.CleanPackedAmount(ffmath.Multiply(finalPoolA, finalPoolB)) - if err != nil { - return err - } - txInfo.TreasuryAmount = lpDeltaForTreasuryAccount - - return nil -} - -func (e *RemoveLiquidityExecutor) ApplyTransaction() error { - bc := e.bc - txInfo := e.txInfo - - // apply changes - fromAccount, err := bc.StateDB().GetFormatAccount(txInfo.FromAccountIndex) - if err != nil { - return err - } - gasAccount, err := bc.StateDB().GetFormatAccount(txInfo.GasAccountIndex) - if err != nil { - return err - } - liquidityModel, err := bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return err - } - treasuryAccount, err := bc.StateDB().GetFormatAccount(liquidityModel.TreasuryAccountIndex) - if err != nil { - return err - } - - fromAccount.AssetInfo[txInfo.AssetAId].Balance = ffmath.Add(fromAccount.AssetInfo[txInfo.AssetAId].Balance, txInfo.AssetAAmountDelta) - fromAccount.AssetInfo[txInfo.AssetBId].Balance = ffmath.Add(fromAccount.AssetInfo[txInfo.AssetBId].Balance, txInfo.AssetBAmountDelta) - fromAccount.AssetInfo[txInfo.PairIndex].LpAmount = ffmath.Sub(fromAccount.AssetInfo[txInfo.PairIndex].LpAmount, txInfo.LpAmount) - treasuryAccount.AssetInfo[txInfo.PairIndex].LpAmount = ffmath.Add(treasuryAccount.AssetInfo[txInfo.PairIndex].LpAmount, txInfo.TreasuryAmount) - fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) - gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Add(gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) - fromAccount.Nonce++ - - stateCache := e.bc.StateDB() - stateCache.SetPendingUpdateAccount(fromAccount.AccountIndex, fromAccount) - stateCache.SetPendingUpdateAccount(treasuryAccount.AccountIndex, treasuryAccount) - stateCache.SetPendingUpdateAccount(gasAccount.AccountIndex, gasAccount) - stateCache.SetPendingUpdateLiquidity(txInfo.PairIndex, &liquidity.Liquidity{ - Model: liquidityModel.Model, - PairIndex: e.newPoolInfo.PairIndex, - AssetAId: liquidityModel.AssetAId, - AssetA: e.newPoolInfo.AssetA.String(), - AssetBId: liquidityModel.AssetBId, - AssetB: e.newPoolInfo.AssetB.String(), - LpAmount: e.newPoolInfo.LpAmount.String(), - KLast: e.newPoolInfo.KLast.String(), - FeeRate: e.newPoolInfo.FeeRate, - TreasuryAccountIndex: e.newPoolInfo.TreasuryAccountIndex, - TreasuryRate: e.newPoolInfo.TreasuryRate, - }) - return e.BaseExecutor.ApplyTransaction() -} - -func (e *RemoveLiquidityExecutor) GeneratePubData() error { - txInfo := e.txInfo - - var buf bytes.Buffer - buf.WriteByte(uint8(types.TxTypeRemoveLiquidity)) - buf.Write(common2.Uint32ToBytes(uint32(txInfo.FromAccountIndex))) - buf.Write(common2.Uint16ToBytes(uint16(txInfo.PairIndex))) - packedAssetAAmountBytes, err := common2.AmountToPackedAmountBytes(txInfo.AssetAAmountDelta) - if err != nil { - logx.Errorf("unable to convert amount to packed amount: %s", err.Error()) - return err - } - buf.Write(packedAssetAAmountBytes) - packedAssetBAmountBytes, err := common2.AmountToPackedAmountBytes(txInfo.AssetBAmountDelta) - if err != nil { - logx.Errorf("unable to convert amount to packed amount: %s", err.Error()) - return err - } - buf.Write(packedAssetBAmountBytes) - LpAmountBytes, err := common2.AmountToPackedAmountBytes(txInfo.LpAmount) - if err != nil { - logx.Errorf("unable to convert amount to packed amount: %s", err.Error()) - return err - } - buf.Write(LpAmountBytes) - KLastBytes, err := common2.AmountToPackedAmountBytes(txInfo.KLast) - if err != nil { - logx.Errorf("unable to convert amount to packed amount: %s", err.Error()) - return err - } - buf.Write(KLastBytes) - chunk1 := common2.SuffixPaddingBufToChunkSize(buf.Bytes()) - buf.Reset() - treasuryAmountBytes, err := common2.AmountToPackedAmountBytes(txInfo.TreasuryAmount) - if err != nil { - logx.Errorf("unable to convert amount to packed amount: %s", err.Error()) - return err - } - buf.Write(treasuryAmountBytes) - buf.Write(common2.Uint32ToBytes(uint32(txInfo.GasAccountIndex))) - buf.Write(common2.Uint16ToBytes(uint16(txInfo.GasFeeAssetId))) - packedFeeBytes, err := common2.FeeToPackedFeeBytes(txInfo.GasFeeAssetAmount) - if err != nil { - logx.Errorf("unable to convert amount to packed fee amount: %s", err.Error()) - return err - } - buf.Write(packedFeeBytes) - chunk2 := common2.PrefixPaddingBufToChunkSize(buf.Bytes()) - buf.Reset() - buf.Write(chunk1) - buf.Write(chunk2) - buf.Write(common2.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common2.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common2.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common2.PrefixPaddingBufToChunkSize([]byte{})) - pubData := buf.Bytes() - - stateCache := e.bc.StateDB() - stateCache.PubData = append(stateCache.PubData, pubData...) - return nil -} - -func (e *RemoveLiquidityExecutor) GetExecutedTx() (*tx.Tx, error) { - txInfoBytes, err := json.Marshal(e.txInfo) - if err != nil { - logx.Errorf("unable to marshal tx, err: %s", err.Error()) - return nil, errors.New("unmarshal tx failed") - } - - e.tx.TxInfo = string(txInfoBytes) - e.tx.GasFeeAssetId = e.txInfo.GasFeeAssetId - e.tx.GasFee = e.txInfo.GasFeeAssetAmount.String() - e.tx.PairIndex = e.txInfo.PairIndex - e.tx.TxAmount = e.txInfo.LpAmount.String() - return e.BaseExecutor.GetExecutedTx() -} - -func (e *RemoveLiquidityExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { - txInfo := e.txInfo - - liquidityModel, err := e.bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return nil, err - } - liquidityInfo, err := constructLiquidityInfo(liquidityModel) - if err != nil { - logx.Errorf("construct liquidity info error, err: %v", err) - return nil, err - } - - copiedAccounts, err := e.bc.StateDB().DeepCopyAccounts([]int64{txInfo.FromAccountIndex, txInfo.GasAccountIndex, liquidityInfo.TreasuryAccountIndex}) - if err != nil { - return nil, err - } - - fromAccount := copiedAccounts[txInfo.FromAccountIndex] - gasAccount := copiedAccounts[txInfo.GasAccountIndex] - treasuryAccount := copiedAccounts[liquidityInfo.TreasuryAccountIndex] - - txDetails := make([]*tx.TxDetail, 0, 4) - // from account asset A - order := int64(0) - accountOrder := int64(0) - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.AssetAId, - AssetType: types.FungibleAssetType, - AccountIndex: txInfo.FromAccountIndex, - AccountName: fromAccount.AccountName, - Balance: fromAccount.AssetInfo[txInfo.AssetAId].String(), - BalanceDelta: types.ConstructAccountAsset( - txInfo.AssetAId, - txInfo.AssetAAmountDelta, - types.ZeroBigInt, - types.ZeroBigInt, - ).String(), - Order: order, - AccountOrder: accountOrder, - Nonce: fromAccount.Nonce, - CollectionNonce: fromAccount.CollectionNonce, - }) - fromAccount.AssetInfo[txInfo.AssetAId].Balance = ffmath.Add(fromAccount.AssetInfo[txInfo.AssetAId].Balance, txInfo.AssetAAmountDelta) - if fromAccount.AssetInfo[txInfo.AssetAId].Balance.Cmp(big.NewInt(0)) < 0 { - return nil, errors.New("insufficient asset a balance") - } - - // from account asset B - order++ - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.AssetBId, - AssetType: types.FungibleAssetType, - AccountIndex: txInfo.FromAccountIndex, - AccountName: fromAccount.AccountName, - Balance: fromAccount.AssetInfo[txInfo.AssetBId].String(), - BalanceDelta: types.ConstructAccountAsset( - txInfo.AssetBId, - txInfo.AssetBAmountDelta, - types.ZeroBigInt, - types.ZeroBigInt, - ).String(), - Order: order, - AccountOrder: accountOrder, - Nonce: fromAccount.Nonce, - CollectionNonce: fromAccount.CollectionNonce, - }) - fromAccount.AssetInfo[txInfo.AssetBId].Balance = ffmath.Add(fromAccount.AssetInfo[txInfo.AssetBId].Balance, txInfo.AssetBAmountDelta) - if fromAccount.AssetInfo[txInfo.AssetBId].Balance.Cmp(types.ZeroBigInt) < 0 { - return nil, errors.New("insufficient asset b balance") - } - - // from account asset gas - order++ - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.GasFeeAssetId, - AssetType: types.FungibleAssetType, - AccountIndex: txInfo.FromAccountIndex, - AccountName: fromAccount.AccountName, - Balance: fromAccount.AssetInfo[txInfo.GasFeeAssetId].String(), - BalanceDelta: types.ConstructAccountAsset( - txInfo.GasFeeAssetId, - ffmath.Neg(txInfo.GasFeeAssetAmount), - types.ZeroBigInt, - types.ZeroBigInt, - ).String(), - Order: order, - AccountOrder: accountOrder, - Nonce: fromAccount.Nonce, - CollectionNonce: fromAccount.CollectionNonce, - }) - fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) - if fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance.Cmp(types.ZeroBigInt) < 0 { - return nil, errors.New("insufficient gas asset balance") - } - - // from account lp - order++ - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.PairIndex, - AssetType: types.FungibleAssetType, - AccountIndex: txInfo.FromAccountIndex, - AccountName: fromAccount.AccountName, - Balance: fromAccount.AssetInfo[txInfo.PairIndex].String(), - BalanceDelta: types.ConstructAccountAsset( - txInfo.PairIndex, - types.ZeroBigInt, - ffmath.Neg(txInfo.LpAmount), - types.ZeroBigInt, - ).String(), - Order: order, - AccountOrder: accountOrder, - Nonce: fromAccount.Nonce, - CollectionNonce: fromAccount.CollectionNonce, - }) - fromAccount.AssetInfo[txInfo.PairIndex].LpAmount = ffmath.Sub(fromAccount.AssetInfo[txInfo.PairIndex].LpAmount, txInfo.LpAmount) - if fromAccount.AssetInfo[txInfo.PairIndex].LpAmount.Cmp(types.ZeroBigInt) < 0 { - return nil, errors.New("insufficient lp amount") - } - - // treasury account - order++ - accountOrder++ - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.PairIndex, - AssetType: types.FungibleAssetType, - AccountIndex: treasuryAccount.AccountIndex, - AccountName: treasuryAccount.AccountName, - Balance: treasuryAccount.AssetInfo[txInfo.PairIndex].String(), - BalanceDelta: types.ConstructAccountAsset( - txInfo.PairIndex, types.ZeroBigInt, txInfo.TreasuryAmount, types.ZeroBigInt, - ).String(), - Order: order, - Nonce: treasuryAccount.Nonce, - AccountOrder: accountOrder, - CollectionNonce: treasuryAccount.CollectionNonce, - }) - treasuryAccount.AssetInfo[txInfo.PairIndex].LpAmount = ffmath.Add(treasuryAccount.AssetInfo[txInfo.PairIndex].LpAmount, txInfo.TreasuryAmount) - - // pool account info - liquidity, err := e.bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return nil, err - } - basePool, err := types.ConstructLiquidityInfo( - liquidity.PairIndex, - liquidity.AssetAId, - liquidity.AssetA, - liquidity.AssetBId, - liquidity.AssetB, - liquidity.LpAmount, - liquidity.KLast, - liquidity.FeeRate, - liquidity.TreasuryAccountIndex, - liquidity.TreasuryRate, - ) - if err != nil { - return nil, err - } - - finalPoolA := ffmath.Add(liquidityInfo.AssetA, ffmath.Neg(txInfo.AssetAAmountDelta)) - finalPoolB := ffmath.Add(liquidityInfo.AssetB, ffmath.Neg(txInfo.AssetBAmountDelta)) - poolDeltaForToAccount := &types.LiquidityInfo{ - PairIndex: txInfo.PairIndex, - AssetAId: txInfo.AssetAId, - AssetA: ffmath.Neg(txInfo.AssetAAmountDelta), - AssetBId: txInfo.AssetBId, - AssetB: ffmath.Neg(txInfo.AssetBAmountDelta), - LpAmount: ffmath.Neg(txInfo.LpAmount), - KLast: ffmath.Multiply(finalPoolA, finalPoolB), - FeeRate: liquidityInfo.FeeRate, - TreasuryAccountIndex: liquidityInfo.TreasuryAccountIndex, - TreasuryRate: liquidityInfo.TreasuryRate, - } - newPool, err := chain.ComputeNewBalance(types.LiquidityAssetType, basePool.String(), poolDeltaForToAccount.String()) - if err != nil { - return nil, err - } - - newPoolInfo, err := types.ParseLiquidityInfo(newPool) - if err != nil { - return nil, err - } - e.newPoolInfo = newPoolInfo - if newPoolInfo.AssetA.Cmp(types.ZeroBigInt) <= 0 || - newPoolInfo.AssetB.Cmp(types.ZeroBigInt) <= 0 || - newPoolInfo.LpAmount.Cmp(types.ZeroBigInt) < 0 || - newPoolInfo.KLast.Cmp(types.ZeroBigInt) <= 0 { - return nil, errors.New("invalid new pool") - } - - order++ - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.PairIndex, - AssetType: types.LiquidityAssetType, - AccountIndex: types.NilAccountIndex, - AccountName: types.NilAccountName, - Balance: basePool.String(), - BalanceDelta: poolDeltaForToAccount.String(), - Order: order, - Nonce: types.NilNonce, - AccountOrder: types.NilAccountOrder, - CollectionNonce: types.NilCollectionNonce, - }) - - // gas account asset gas - order++ - accountOrder++ - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.GasFeeAssetId, - AssetType: types.FungibleAssetType, - AccountIndex: txInfo.GasAccountIndex, - AccountName: gasAccount.AccountName, - Balance: gasAccount.AssetInfo[txInfo.GasFeeAssetId].String(), - BalanceDelta: types.ConstructAccountAsset( - txInfo.GasFeeAssetId, - txInfo.GasFeeAssetAmount, - types.ZeroBigInt, - types.ZeroBigInt, - ).String(), - Order: order, - AccountOrder: accountOrder, - Nonce: gasAccount.Nonce, - CollectionNonce: gasAccount.CollectionNonce, - }) - return txDetails, nil -} diff --git a/core/executor/swap_executor.go b/core/executor/swap_executor.go deleted file mode 100644 index 2358f7be8..000000000 --- a/core/executor/swap_executor.go +++ /dev/null @@ -1,457 +0,0 @@ -package executor - -import ( - "bytes" - "encoding/json" - "math/big" - - "github.com/pkg/errors" - "github.com/zeromicro/go-zero/core/logx" - - "github.com/bnb-chain/zkbnb-crypto/ffmath" - "github.com/bnb-chain/zkbnb-crypto/wasm/txtypes" - common2 "github.com/bnb-chain/zkbnb/common" - "github.com/bnb-chain/zkbnb/common/chain" - "github.com/bnb-chain/zkbnb/dao/liquidity" - "github.com/bnb-chain/zkbnb/dao/tx" - "github.com/bnb-chain/zkbnb/types" -) - -type SwapExecutor struct { - BaseExecutor - - txInfo *txtypes.SwapTxInfo - - newPoolInfo *types.LiquidityInfo -} - -func NewSwapExecutor(bc IBlockchain, tx *tx.Tx) (TxExecutor, error) { - txInfo, err := types.ParseSwapTxInfo(tx.TxInfo) - if err != nil { - logx.Errorf("parse transfer tx failed: %s", err.Error()) - return nil, errors.New("invalid tx info") - } - - return &SwapExecutor{ - BaseExecutor: NewBaseExecutor(bc, tx, txInfo), - txInfo: txInfo, - }, nil -} - -func (e *SwapExecutor) Prepare() error { - txInfo := e.txInfo - - err := e.bc.StateDB().PrepareLiquidity(txInfo.PairIndex) - if err != nil { - logx.Errorf("prepare liquidity failed: %s", err.Error()) - return errors.New("internal error") - } - - err = e.fillTxInfo() - if err != nil { - return err - } - - // Mark the tree states that would be affected in this executor. - e.MarkLiquidityDirty(txInfo.PairIndex) - e.MarkAccountAssetsDirty(txInfo.FromAccountIndex, []int64{txInfo.GasFeeAssetId, txInfo.AssetAId, txInfo.AssetBId}) - e.MarkAccountAssetsDirty(txInfo.GasAccountIndex, []int64{txInfo.GasFeeAssetId}) - err = e.BaseExecutor.Prepare() - if err != nil { - return err - } - - return nil -} - -func (e *SwapExecutor) VerifyInputs(skipGasAmtChk bool) error { - bc := e.bc - txInfo := e.txInfo - - err := e.BaseExecutor.VerifyInputs(skipGasAmtChk) - if err != nil { - return err - } - - fromAccount, err := bc.StateDB().GetFormatAccount(txInfo.FromAccountIndex) - if err != nil { - return err - } - if txInfo.GasFeeAssetId != txInfo.AssetAId { - if fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance.Cmp(txInfo.GasFeeAssetAmount) < 0 { - return errors.New("invalid gas asset amount") - } - if fromAccount.AssetInfo[txInfo.AssetAId].Balance.Cmp(txInfo.AssetAAmount) < 0 { - return errors.New("invalid asset amount") - } - } else { - deltaBalance := ffmath.Add(txInfo.AssetAAmount, txInfo.GasFeeAssetAmount) - if fromAccount.AssetInfo[txInfo.AssetAId].Balance.Cmp(deltaBalance) < 0 { - return errors.New("invalid asset amount") - } - } - - liquidityModel, err := bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return err - } - liquidityInfo, err := constructLiquidityInfo(liquidityModel) - if err != nil { - logx.Errorf("construct liquidity info error, err: %v", err) - return errors.New("internal error") - } - if !((liquidityModel.AssetAId == txInfo.AssetAId && liquidityModel.AssetBId == txInfo.AssetBId) || - (liquidityModel.AssetAId == txInfo.AssetBId && liquidityModel.AssetBId == txInfo.AssetAId)) { - return errors.New("invalid asset ids") - } - if liquidityInfo.AssetA == nil || liquidityInfo.AssetA.Cmp(types.ZeroBigInt) == 0 || - liquidityInfo.AssetB == nil || liquidityInfo.AssetB.Cmp(types.ZeroBigInt) == 0 { - return errors.New("liquidity is empty") - } - - return nil -} - -func constructLiquidityInfo(liquidity *liquidity.Liquidity) (*types.LiquidityInfo, error) { - return types.ConstructLiquidityInfo( - liquidity.PairIndex, - liquidity.AssetAId, - liquidity.AssetA, - liquidity.AssetBId, - liquidity.AssetB, - liquidity.LpAmount, - liquidity.KLast, - liquidity.FeeRate, - liquidity.TreasuryAccountIndex, - liquidity.TreasuryRate, - ) -} - -func (e *SwapExecutor) ApplyTransaction() error { - bc := e.bc - txInfo := e.txInfo - - // apply changes - fromAccount, err := bc.StateDB().GetFormatAccount(txInfo.FromAccountIndex) - if err != nil { - return err - } - gasAccount, err := bc.StateDB().GetFormatAccount(txInfo.GasAccountIndex) - if err != nil { - return err - } - - fromAccount.AssetInfo[txInfo.AssetAId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.AssetAId].Balance, txInfo.AssetAAmount) - fromAccount.AssetInfo[txInfo.AssetBId].Balance = ffmath.Add(fromAccount.AssetInfo[txInfo.AssetBId].Balance, txInfo.AssetBAmountDelta) - fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) - gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Add(gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) - fromAccount.Nonce++ - - liquidityModel, err := bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return err - } - - stateCache := e.bc.StateDB() - stateCache.SetPendingUpdateAccount(txInfo.FromAccountIndex, fromAccount) - stateCache.SetPendingUpdateAccount(txInfo.GasAccountIndex, gasAccount) - stateCache.SetPendingUpdateLiquidity(txInfo.PairIndex, &liquidity.Liquidity{ - Model: liquidityModel.Model, - PairIndex: e.newPoolInfo.PairIndex, - AssetAId: liquidityModel.AssetAId, - AssetA: e.newPoolInfo.AssetA.String(), - AssetBId: liquidityModel.AssetBId, - AssetB: e.newPoolInfo.AssetB.String(), - LpAmount: e.newPoolInfo.LpAmount.String(), - KLast: e.newPoolInfo.KLast.String(), - FeeRate: e.newPoolInfo.FeeRate, - TreasuryAccountIndex: e.newPoolInfo.TreasuryAccountIndex, - TreasuryRate: e.newPoolInfo.TreasuryRate, - }) - return e.BaseExecutor.ApplyTransaction() -} - -func (e *SwapExecutor) fillTxInfo() error { - bc := e.bc - txInfo := e.txInfo - - liquidityModel, err := bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return err - } - - liquidityInfo, err := constructLiquidityInfo(liquidityModel) - if err != nil { - logx.Errorf("construct liquidity info error, err: %v", err) - return err - } - - // add details to tx info - var toDelta *big.Int - if liquidityInfo.AssetAId == txInfo.AssetAId && liquidityInfo.AssetBId == txInfo.AssetBId { - toDelta, _, err = chain.ComputeDelta( - liquidityInfo.AssetA, - liquidityInfo.AssetB, - liquidityInfo.AssetAId, - liquidityInfo.AssetBId, - txInfo.AssetAId, - true, - txInfo.AssetAAmount, - liquidityInfo.FeeRate, - ) - if err != nil { - return err - } - } else if liquidityInfo.AssetAId == txInfo.AssetBId && liquidityInfo.AssetBId == txInfo.AssetAId { - toDelta, _, err = chain.ComputeDelta( - liquidityInfo.AssetA, - liquidityInfo.AssetB, - liquidityInfo.AssetAId, - liquidityInfo.AssetBId, - txInfo.AssetBId, - true, - txInfo.AssetAAmount, - liquidityInfo.FeeRate, - ) - if err != nil { - return err - } - } - - if toDelta.Cmp(txInfo.AssetBMinAmount) < 0 { - return errors.New("invalid AssetBMinAmount") - } - txInfo.AssetBAmountDelta = toDelta - - return nil -} - -func (e *SwapExecutor) GeneratePubData() error { - txInfo := e.txInfo - - var buf bytes.Buffer - buf.WriteByte(uint8(types.TxTypeSwap)) - buf.Write(common2.Uint32ToBytes(uint32(txInfo.FromAccountIndex))) - buf.Write(common2.Uint16ToBytes(uint16(txInfo.PairIndex))) - buf.Write(common2.Uint16ToBytes(uint16(txInfo.AssetAId))) - packedAssetAAmountBytes, err := common2.AmountToPackedAmountBytes(txInfo.AssetAAmount) - if err != nil { - logx.Errorf("unable to convert amount to packed amount: %s", err.Error()) - return err - } - buf.Write(packedAssetAAmountBytes) - buf.Write(common2.Uint16ToBytes(uint16(txInfo.AssetBId))) - packedAssetBAmountDeltaBytes, err := common2.AmountToPackedAmountBytes(txInfo.AssetBAmountDelta) - if err != nil { - logx.Errorf("unable to convert amount to packed amount: %s", err.Error()) - return err - } - buf.Write(packedAssetBAmountDeltaBytes) - buf.Write(common2.Uint32ToBytes(uint32(txInfo.GasAccountIndex))) - buf.Write(common2.Uint16ToBytes(uint16(txInfo.GasFeeAssetId))) - packedFeeBytes, err := common2.FeeToPackedFeeBytes(txInfo.GasFeeAssetAmount) - if err != nil { - logx.Errorf("unable to convert amount to packed fee amount: %s", err.Error()) - return err - } - buf.Write(packedFeeBytes) - chunk := common2.SuffixPaddingBufToChunkSize(buf.Bytes()) - buf.Reset() - buf.Write(chunk) - buf.Write(common2.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common2.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common2.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common2.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common2.PrefixPaddingBufToChunkSize([]byte{})) - pubData := buf.Bytes() - - stateCache := e.bc.StateDB() - stateCache.PubData = append(stateCache.PubData, pubData...) - return nil -} - -func (e *SwapExecutor) GetExecutedTx() (*tx.Tx, error) { - txInfoBytes, err := json.Marshal(e.txInfo) - if err != nil { - logx.Errorf("unable to marshal tx, err: %s", err.Error()) - return nil, errors.New("unmarshal tx failed") - } - - e.tx.TxInfo = string(txInfoBytes) - e.tx.GasFeeAssetId = e.txInfo.GasFeeAssetId - e.tx.GasFee = e.txInfo.GasFeeAssetAmount.String() - e.tx.PairIndex = e.txInfo.PairIndex - e.tx.TxAmount = e.txInfo.AssetAAmount.String() - return e.BaseExecutor.GetExecutedTx() -} - -func (e *SwapExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { - txInfo := e.txInfo - - copiedAccounts, err := e.bc.StateDB().DeepCopyAccounts([]int64{txInfo.FromAccountIndex, txInfo.GasAccountIndex}) - if err != nil { - return nil, err - } - - fromAccount := copiedAccounts[txInfo.FromAccountIndex] - gasAccount := copiedAccounts[txInfo.GasAccountIndex] - liquidityModel, err := e.bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return nil, err - } - liquidityInfo, err := constructLiquidityInfo(liquidityModel) - if err != nil { - logx.Errorf("construct liquidity info error, err: %v", err) - return nil, err - } - - txDetails := make([]*tx.TxDetail, 0, 4) - // from account asset A - order := int64(0) - accountOrder := int64(0) - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.AssetAId, - AssetType: types.FungibleAssetType, - AccountIndex: txInfo.FromAccountIndex, - AccountName: fromAccount.AccountName, - Balance: fromAccount.AssetInfo[txInfo.AssetAId].String(), - BalanceDelta: types.ConstructAccountAsset( - txInfo.AssetAId, - ffmath.Neg(txInfo.AssetAAmount), - types.ZeroBigInt, - types.ZeroBigInt, - ).String(), - Order: order, - AccountOrder: accountOrder, - Nonce: fromAccount.Nonce, - CollectionNonce: fromAccount.CollectionNonce, - }) - fromAccount.AssetInfo[txInfo.AssetAId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.AssetAId].Balance, txInfo.AssetAAmount) - if fromAccount.AssetInfo[txInfo.AssetAId].Balance.Cmp(types.ZeroBigInt) < 0 { - return nil, errors.New("insufficient asset a balance") - } - - // from account asset B - order++ - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.AssetBId, - AssetType: types.FungibleAssetType, - AccountIndex: txInfo.FromAccountIndex, - AccountName: fromAccount.AccountName, - Balance: fromAccount.AssetInfo[txInfo.AssetBId].String(), - BalanceDelta: types.ConstructAccountAsset( - txInfo.AssetBId, - txInfo.AssetBAmountDelta, - types.ZeroBigInt, - types.ZeroBigInt, - ).String(), - Order: order, - AccountOrder: accountOrder, - Nonce: fromAccount.Nonce, - CollectionNonce: fromAccount.CollectionNonce, - }) - fromAccount.AssetInfo[txInfo.AssetBId].Balance = ffmath.Add(fromAccount.AssetInfo[txInfo.AssetBId].Balance, txInfo.AssetBAmountDelta) - - // from account asset gas - order++ - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.GasFeeAssetId, - AssetType: types.FungibleAssetType, - AccountIndex: txInfo.FromAccountIndex, - AccountName: fromAccount.AccountName, - Balance: fromAccount.AssetInfo[txInfo.GasFeeAssetId].String(), - BalanceDelta: types.ConstructAccountAsset( - txInfo.GasFeeAssetId, - ffmath.Neg(txInfo.GasFeeAssetAmount), - types.ZeroBigInt, - types.ZeroBigInt, - ).String(), - Order: order, - AccountOrder: accountOrder, - Nonce: fromAccount.Nonce, - CollectionNonce: fromAccount.CollectionNonce, - }) - fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) - if fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance.Cmp(types.ZeroBigInt) < 0 { - return nil, errors.New("insufficient gas fee balance") - } - - // pool info - var poolDelta *types.LiquidityInfo - poolAssetBDelta := ffmath.Neg(txInfo.AssetBAmountDelta) - if txInfo.AssetAId == liquidityInfo.AssetAId { - poolDelta = &types.LiquidityInfo{ - PairIndex: txInfo.PairIndex, - AssetAId: txInfo.AssetAId, - AssetA: txInfo.AssetAAmount, - AssetBId: txInfo.AssetBId, - AssetB: poolAssetBDelta, - LpAmount: types.ZeroBigInt, - KLast: types.ZeroBigInt, - FeeRate: liquidityInfo.FeeRate, - TreasuryAccountIndex: liquidityInfo.TreasuryAccountIndex, - TreasuryRate: liquidityInfo.TreasuryRate, - } - } else if txInfo.AssetAId == liquidityInfo.AssetBId { - poolDelta = &types.LiquidityInfo{ - PairIndex: txInfo.PairIndex, - AssetAId: txInfo.AssetBId, - AssetA: poolAssetBDelta, - AssetBId: txInfo.AssetAId, - AssetB: txInfo.AssetAAmount, - LpAmount: types.ZeroBigInt, - KLast: types.ZeroBigInt, - FeeRate: liquidityInfo.FeeRate, - TreasuryAccountIndex: liquidityInfo.TreasuryAccountIndex, - TreasuryRate: liquidityInfo.TreasuryRate, - } - } - - newPool, err := chain.ComputeNewBalance( - types.LiquidityAssetType, liquidityInfo.String(), poolDelta.String()) - if err != nil { - return nil, err - } - - nPoolInfo, err := types.ParseLiquidityInfo(newPool) - if err != nil { - return nil, err - } - e.newPoolInfo = nPoolInfo - - order++ - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.PairIndex, - AssetType: types.LiquidityAssetType, - AccountIndex: types.NilAccountIndex, - AccountName: types.NilAccountName, - Balance: liquidityInfo.String(), - BalanceDelta: poolDelta.String(), - Order: order, - Nonce: 0, - AccountOrder: types.NilAccountOrder, - CollectionNonce: 0, - }) - - // gas account asset gas - order++ - accountOrder++ - txDetails = append(txDetails, &tx.TxDetail{ - AssetId: txInfo.GasFeeAssetId, - AssetType: types.FungibleAssetType, - AccountIndex: txInfo.GasAccountIndex, - AccountName: gasAccount.AccountName, - Balance: gasAccount.AssetInfo[txInfo.GasFeeAssetId].String(), - BalanceDelta: types.ConstructAccountAsset( - txInfo.GasFeeAssetId, - txInfo.GasFeeAssetAmount, - types.ZeroBigInt, - types.ZeroBigInt, - ).String(), - Order: order, - AccountOrder: accountOrder, - Nonce: gasAccount.Nonce, - CollectionNonce: gasAccount.CollectionNonce, - }) - return txDetails, nil -} diff --git a/core/executor/transfer_executor.go b/core/executor/transfer_executor.go index 8a62d95cf..887df5e5f 100644 --- a/core/executor/transfer_executor.go +++ b/core/executor/transfer_executor.go @@ -92,21 +92,16 @@ func (e *TransferExecutor) ApplyTransaction() error { if err != nil { return err } - gasAccount, err := bc.StateDB().GetFormatAccount(txInfo.GasAccountIndex) - if err != nil { - return err - } fromAccount.AssetInfo[txInfo.AssetId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.AssetId].Balance, txInfo.AssetAmount) fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) toAccount.AssetInfo[txInfo.AssetId].Balance = ffmath.Add(toAccount.AssetInfo[txInfo.AssetId].Balance, txInfo.AssetAmount) - gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Add(gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) fromAccount.Nonce++ stateCache := e.bc.StateDB() - stateCache.SetPendingUpdateAccount(txInfo.FromAccountIndex, fromAccount) - stateCache.SetPendingUpdateAccount(txInfo.ToAccountIndex, toAccount) - stateCache.SetPendingUpdateAccount(txInfo.GasAccountIndex, gasAccount) + stateCache.SetPendingAccount(txInfo.FromAccountIndex, fromAccount) + stateCache.SetPendingAccount(txInfo.ToAccountIndex, toAccount) + stateCache.SetPendingUpdateGas(txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount) return e.BaseExecutor.ApplyTransaction() } @@ -182,13 +177,14 @@ func (e *TransferExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { AccountName: fromAccount.AccountName, Balance: fromAccount.AssetInfo[txInfo.AssetId].String(), BalanceDelta: types.ConstructAccountAsset( - txInfo.AssetId, ffmath.Neg(txInfo.AssetAmount), types.ZeroBigInt, types.ZeroBigInt).String(), + txInfo.AssetId, ffmath.Neg(txInfo.AssetAmount), types.ZeroBigInt).String(), Order: order, AccountOrder: accountOrder, Nonce: fromAccount.Nonce, CollectionNonce: fromAccount.CollectionNonce, }) fromAccount.AssetInfo[txInfo.AssetId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.AssetId].Balance, txInfo.AssetAmount) + // from account asset gas order++ txDetails = append(txDetails, &tx.TxDetail{ @@ -198,13 +194,14 @@ func (e *TransferExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { AccountName: fromAccount.AccountName, Balance: fromAccount.AssetInfo[txInfo.GasFeeAssetId].String(), BalanceDelta: types.ConstructAccountAsset( - txInfo.GasFeeAssetId, ffmath.Neg(txInfo.GasFeeAssetAmount), types.ZeroBigInt, types.ZeroBigInt).String(), + txInfo.GasFeeAssetId, ffmath.Neg(txInfo.GasFeeAssetAmount), types.ZeroBigInt).String(), Order: order, AccountOrder: accountOrder, Nonce: fromAccount.Nonce, CollectionNonce: fromAccount.CollectionNonce, }) fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) + // to account asset a order++ accountOrder++ @@ -215,13 +212,14 @@ func (e *TransferExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { AccountName: toAccount.AccountName, Balance: toAccount.AssetInfo[txInfo.AssetId].String(), BalanceDelta: types.ConstructAccountAsset( - txInfo.AssetId, txInfo.AssetAmount, types.ZeroBigInt, types.ZeroBigInt).String(), + txInfo.AssetId, txInfo.AssetAmount, types.ZeroBigInt).String(), Order: order, AccountOrder: accountOrder, Nonce: toAccount.Nonce, CollectionNonce: toAccount.CollectionNonce, }) toAccount.AssetInfo[txInfo.AssetId].Balance = ffmath.Add(toAccount.AssetInfo[txInfo.AssetId].Balance, txInfo.AssetAmount) + // gas account asset gas order++ accountOrder++ @@ -232,11 +230,12 @@ func (e *TransferExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { AccountName: gasAccount.AccountName, Balance: gasAccount.AssetInfo[txInfo.GasFeeAssetId].String(), BalanceDelta: types.ConstructAccountAsset( - txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount, types.ZeroBigInt, types.ZeroBigInt).String(), + txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount, types.ZeroBigInt).String(), Order: order, AccountOrder: accountOrder, Nonce: gasAccount.Nonce, CollectionNonce: gasAccount.CollectionNonce, + IsGas: true, }) gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Add(gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) diff --git a/core/executor/transfer_nft_executor.go b/core/executor/transfer_nft_executor.go index 354b2fb80..27a4fe157 100644 --- a/core/executor/transfer_nft_executor.go +++ b/core/executor/transfer_nft_executor.go @@ -89,28 +89,23 @@ func (e *TransferNftExecutor) ApplyTransaction() error { bc := e.bc txInfo := e.txInfo - fromAccount, err := e.bc.StateDB().GetFormatAccount(txInfo.FromAccountIndex) - if err != nil { - return err - } - gasAccount, err := bc.StateDB().GetFormatAccount(txInfo.GasAccountIndex) + fromAccount, err := bc.StateDB().GetFormatAccount(txInfo.FromAccountIndex) if err != nil { return err } - nft, err := e.bc.StateDB().GetNft(txInfo.NftIndex) + nft, err := bc.StateDB().GetNft(txInfo.NftIndex) if err != nil { return err } fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) - gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Add(gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) fromAccount.Nonce++ nft.OwnerAccountIndex = txInfo.ToAccountIndex stateCache := e.bc.StateDB() - stateCache.SetPendingUpdateAccount(txInfo.FromAccountIndex, fromAccount) - stateCache.SetPendingUpdateAccount(txInfo.GasAccountIndex, gasAccount) - stateCache.SetPendingUpdateNft(txInfo.NftIndex, nft) + stateCache.SetPendingAccount(txInfo.FromAccountIndex, fromAccount) + stateCache.SetPendingNft(txInfo.NftIndex, nft) + stateCache.SetPendingUpdateGas(txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount) return e.BaseExecutor.ApplyTransaction() } @@ -188,7 +183,6 @@ func (e *TransferNftExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { txInfo.GasFeeAssetId, ffmath.Neg(txInfo.GasFeeAssetAmount), types.ZeroBigInt, - types.ZeroBigInt, ).String(), Order: order, Nonce: fromAccount.Nonce, @@ -213,7 +207,6 @@ func (e *TransferNftExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { txInfo.GasFeeAssetId, types.ZeroBigInt, types.ZeroBigInt, - types.ZeroBigInt, ).String(), Order: order, Nonce: toAccount.Nonce, @@ -269,12 +262,12 @@ func (e *TransferNftExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount, types.ZeroBigInt, - types.ZeroBigInt, ).String(), Order: order, Nonce: gasAccount.Nonce, AccountOrder: accountOrder, CollectionNonce: gasAccount.CollectionNonce, + IsGas: true, }) return txDetails, nil } diff --git a/core/executor/update_pair_rate_executor.go b/core/executor/update_pair_rate_executor.go deleted file mode 100644 index d82c958a2..000000000 --- a/core/executor/update_pair_rate_executor.go +++ /dev/null @@ -1,171 +0,0 @@ -package executor - -import ( - "bytes" - "encoding/json" - "errors" - "math/big" - - "github.com/zeromicro/go-zero/core/logx" - - "github.com/bnb-chain/zkbnb-crypto/wasm/txtypes" - "github.com/bnb-chain/zkbnb/common" - "github.com/bnb-chain/zkbnb/dao/tx" - "github.com/bnb-chain/zkbnb/types" -) - -type UpdatePairRateExecutor struct { - BaseExecutor - - txInfo *txtypes.UpdatePairRateTxInfo -} - -func NewUpdatePairRateExecutor(bc IBlockchain, tx *tx.Tx) (TxExecutor, error) { - txInfo, err := types.ParseUpdatePairRateTxInfo(tx.TxInfo) - if err != nil { - logx.Errorf("parse update pair rate tx failed: %s", err.Error()) - return nil, errors.New("invalid tx info") - } - - return &UpdatePairRateExecutor{ - BaseExecutor: NewBaseExecutor(bc, tx, txInfo), - txInfo: txInfo, - }, nil -} - -func (e *UpdatePairRateExecutor) Prepare() error { - txInfo := e.txInfo - - err := e.bc.StateDB().PrepareLiquidity(txInfo.PairIndex) - if err != nil { - logx.Errorf("prepare liquidity failed: %s", err.Error()) - return err - } - - // Mark the tree states that would be affected in this executor. - e.MarkLiquidityDirty(txInfo.PairIndex) - return e.BaseExecutor.Prepare() -} - -func (e *UpdatePairRateExecutor) VerifyInputs(skipGasAmtChk bool) error { - bc := e.bc - txInfo := e.txInfo - liquidity, err := bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return err - } - - if liquidity.FeeRate == txInfo.FeeRate && - liquidity.TreasuryAccountIndex == txInfo.TreasuryAccountIndex && - liquidity.TreasuryRate == txInfo.TreasuryRate { - return errors.New("invalid update, the same to old") - } - - return nil -} - -func (e *UpdatePairRateExecutor) ApplyTransaction() error { - bc := e.bc - txInfo := e.txInfo - - liquidity, err := bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return err - } - liquidity.FeeRate = txInfo.FeeRate - liquidity.TreasuryAccountIndex = txInfo.TreasuryAccountIndex - liquidity.TreasuryRate = txInfo.TreasuryRate - - stateCache := e.bc.StateDB() - stateCache.SetPendingUpdateLiquidity(txInfo.PairIndex, liquidity) - return e.BaseExecutor.ApplyTransaction() -} - -func (e *UpdatePairRateExecutor) GeneratePubData() error { - txInfo := e.txInfo - - var buf bytes.Buffer - buf.WriteByte(uint8(types.TxTypeUpdatePairRate)) - buf.Write(common.Uint16ToBytes(uint16(txInfo.PairIndex))) - buf.Write(common.Uint16ToBytes(uint16(txInfo.FeeRate))) - buf.Write(common.Uint32ToBytes(uint32(txInfo.TreasuryAccountIndex))) - buf.Write(common.Uint16ToBytes(uint16(txInfo.TreasuryRate))) - chunk := common.SuffixPaddingBufToChunkSize(buf.Bytes()) - buf.Reset() - buf.Write(chunk) - buf.Write(common.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common.PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(common.PrefixPaddingBufToChunkSize([]byte{})) - pubData := buf.Bytes() - - stateCache := e.bc.StateDB() - stateCache.PriorityOperations++ - stateCache.PubDataOffset = append(stateCache.PubDataOffset, uint32(len(stateCache.PubData))) - stateCache.PubData = append(stateCache.PubData, pubData...) - return nil -} - -func (e *UpdatePairRateExecutor) GetExecutedTx() (*tx.Tx, error) { - txInfoBytes, err := json.Marshal(e.txInfo) - if err != nil { - logx.Errorf("unable to marshal tx, err: %s", err.Error()) - return nil, errors.New("unmarshal tx failed") - } - - e.tx.TxInfo = string(txInfoBytes) - e.tx.PairIndex = e.txInfo.PairIndex - return e.BaseExecutor.GetExecutedTx() -} - -func (e *UpdatePairRateExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { - bc := e.bc - txInfo := e.txInfo - liquidity, err := bc.StateDB().GetLiquidity(txInfo.PairIndex) - if err != nil { - return nil, err - } - baseLiquidity, err := types.ConstructLiquidityInfo( - liquidity.PairIndex, - liquidity.AssetAId, - liquidity.AssetA, - liquidity.AssetBId, - liquidity.AssetB, - liquidity.LpAmount, - liquidity.KLast, - liquidity.FeeRate, - liquidity.TreasuryAccountIndex, - liquidity.TreasuryRate, - ) - if err != nil { - return nil, err - } - deltaLiquidity := &types.LiquidityInfo{ - PairIndex: baseLiquidity.PairIndex, - AssetAId: baseLiquidity.AssetAId, - AssetA: big.NewInt(0), - AssetBId: baseLiquidity.AssetBId, - AssetB: big.NewInt(0), - LpAmount: big.NewInt(0), - KLast: baseLiquidity.KLast, - FeeRate: txInfo.FeeRate, - TreasuryAccountIndex: txInfo.TreasuryAccountIndex, - TreasuryRate: txInfo.TreasuryRate, - } - - txDetail := &tx.TxDetail{ - AssetId: txInfo.PairIndex, - AssetType: types.LiquidityAssetType, - AccountIndex: types.NilAccountIndex, - AccountName: types.NilAccountName, - Balance: baseLiquidity.String(), - BalanceDelta: deltaLiquidity.String(), - Order: 0, - AccountOrder: types.NilAccountOrder, - Nonce: types.NilNonce, - CollectionNonce: types.NilCollectionNonce, - } - - return []*tx.TxDetail{txDetail}, nil -} diff --git a/core/executor/withdraw_executor.go b/core/executor/withdraw_executor.go index ce3bae020..793218caf 100644 --- a/core/executor/withdraw_executor.go +++ b/core/executor/withdraw_executor.go @@ -79,20 +79,15 @@ func (e *WithdrawExecutor) ApplyTransaction() error { if err != nil { return err } - gasAccount, err := bc.StateDB().GetFormatAccount(txInfo.GasAccountIndex) - if err != nil { - return err - } // apply changes fromAccount.AssetInfo[txInfo.AssetId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.AssetId].Balance, txInfo.AssetAmount) fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) - gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Add(gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) fromAccount.Nonce++ stateCache := e.bc.StateDB() - stateCache.SetPendingUpdateAccount(txInfo.FromAccountIndex, fromAccount) - stateCache.SetPendingUpdateAccount(txInfo.GasAccountIndex, gasAccount) + stateCache.SetPendingAccount(txInfo.FromAccountIndex, fromAccount) + stateCache.SetPendingUpdateGas(txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount) return e.BaseExecutor.ApplyTransaction() } @@ -169,7 +164,7 @@ func (e *WithdrawExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { AccountName: fromAccount.AccountName, Balance: fromAccount.AssetInfo[txInfo.AssetId].String(), BalanceDelta: types.ConstructAccountAsset( - txInfo.AssetId, ffmath.Neg(txInfo.AssetAmount), types.ZeroBigInt, types.ZeroBigInt).String(), + txInfo.AssetId, ffmath.Neg(txInfo.AssetAmount), types.ZeroBigInt).String(), Order: order, AccountOrder: accountOrder, Nonce: fromAccount.Nonce, @@ -189,7 +184,7 @@ func (e *WithdrawExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { AccountName: fromAccount.AccountName, Balance: fromAccount.AssetInfo[txInfo.GasFeeAssetId].String(), BalanceDelta: types.ConstructAccountAsset( - txInfo.GasFeeAssetId, ffmath.Neg(txInfo.GasFeeAssetAmount), types.ZeroBigInt, types.ZeroBigInt).String(), + txInfo.GasFeeAssetId, ffmath.Neg(txInfo.GasFeeAssetAmount), types.ZeroBigInt).String(), Order: order, AccountOrder: accountOrder, Nonce: fromAccount.Nonce, @@ -210,11 +205,12 @@ func (e *WithdrawExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { AccountName: gasAccount.AccountName, Balance: gasAccount.AssetInfo[txInfo.GasFeeAssetId].String(), BalanceDelta: types.ConstructAccountAsset( - txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount, types.ZeroBigInt, types.ZeroBigInt).String(), + txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount, types.ZeroBigInt).String(), Order: order, AccountOrder: accountOrder, Nonce: gasAccount.Nonce, CollectionNonce: gasAccount.CollectionNonce, + IsGas: true, }) return txDetails, nil } diff --git a/core/executor/withdraw_nft_executor.go b/core/executor/withdraw_nft_executor.go index ca407165b..dc62c1008 100644 --- a/core/executor/withdraw_nft_executor.go +++ b/core/executor/withdraw_nft_executor.go @@ -115,21 +115,15 @@ func (e *WithdrawNftExecutor) ApplyTransaction() error { if err != nil { return err } - gasAccount, err := bc.StateDB().GetFormatAccount(txInfo.GasAccountIndex) - if err != nil { - return err - } // apply changes fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Sub(fromAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) - gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance = ffmath.Add(gasAccount.AssetInfo[txInfo.GasFeeAssetId].Balance, txInfo.GasFeeAssetAmount) fromAccount.Nonce++ newNftInfo := types.EmptyNftInfo(txInfo.NftIndex) stateCache := e.bc.StateDB() - stateCache.SetPendingUpdateAccount(txInfo.AccountIndex, fromAccount) - stateCache.SetPendingUpdateAccount(txInfo.GasAccountIndex, gasAccount) - stateCache.SetPendingUpdateNft(txInfo.NftIndex, &nft.L2Nft{ + stateCache.SetPendingAccount(txInfo.AccountIndex, fromAccount) + stateCache.SetPendingNft(txInfo.NftIndex, &nft.L2Nft{ Model: oldNft.Model, NftIndex: newNftInfo.NftIndex, CreatorAccountIndex: newNftInfo.CreatorAccountIndex, @@ -140,6 +134,7 @@ func (e *WithdrawNftExecutor) ApplyTransaction() error { CreatorTreasuryRate: newNftInfo.CreatorTreasuryRate, CollectionId: newNftInfo.CollectionId, }) + stateCache.SetPendingUpdateGas(txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount) return e.BaseExecutor.ApplyTransaction() } @@ -230,7 +225,6 @@ func (e *WithdrawNftExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { txInfo.GasFeeAssetId, ffmath.Neg(txInfo.GasFeeAssetAmount), types.ZeroBigInt, - types.ZeroBigInt, ).String(), Order: order, AccountOrder: accountOrder, @@ -279,7 +273,6 @@ func (e *WithdrawNftExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { txInfo.GasFeeAssetId, types.ZeroBigInt, types.ZeroBigInt, - types.ZeroBigInt, ).String(), Order: order, AccountOrder: accountOrder, @@ -300,12 +293,12 @@ func (e *WithdrawNftExecutor) GenerateTxDetails() ([]*tx.TxDetail, error) { txInfo.GasFeeAssetId, txInfo.GasFeeAssetAmount, types.ZeroBigInt, - types.ZeroBigInt, ).String(), Order: order, AccountOrder: accountOrder, Nonce: gasAccount.Nonce, CollectionNonce: gasAccount.CollectionNonce, + IsGas: true, }) return txDetails, nil } diff --git a/core/statedb/chaindb.go b/core/statedb/chaindb.go index 6268c6bb1..8788ae271 100644 --- a/core/statedb/chaindb.go +++ b/core/statedb/chaindb.go @@ -8,8 +8,8 @@ import ( "github.com/bnb-chain/zkbnb/dao/asset" "github.com/bnb-chain/zkbnb/dao/block" "github.com/bnb-chain/zkbnb/dao/compressedblock" - "github.com/bnb-chain/zkbnb/dao/liquidity" "github.com/bnb-chain/zkbnb/dao/nft" + "github.com/bnb-chain/zkbnb/dao/priorityrequest" "github.com/bnb-chain/zkbnb/dao/sysconfig" "github.com/bnb-chain/zkbnb/dao/tx" ) @@ -20,16 +20,15 @@ type ChainDB struct { BlockModel block.BlockModel CompressedBlockModel compressedblock.CompressedBlockModel TxModel tx.TxModel + PriorityRequestModel priorityrequest.PriorityRequestModel // State DB - AccountModel account.AccountModel - AccountHistoryModel account.AccountHistoryModel - L2AssetInfoModel asset.AssetModel - LiquidityModel liquidity.LiquidityModel - LiquidityHistoryModel liquidity.LiquidityHistoryModel - L2NftModel nft.L2NftModel - L2NftHistoryModel nft.L2NftHistoryModel - TxPoolModel tx.TxPoolModel + AccountModel account.AccountModel + AccountHistoryModel account.AccountHistoryModel + L2AssetInfoModel asset.AssetModel + L2NftModel nft.L2NftModel + L2NftHistoryModel nft.L2NftHistoryModel + TxPoolModel tx.TxPoolModel // Sys config SysConfigModel sysconfig.SysConfigModel @@ -41,15 +40,14 @@ func NewChainDB(db *gorm.DB) *ChainDB { BlockModel: block.NewBlockModel(db), CompressedBlockModel: compressedblock.NewCompressedBlockModel(db), TxModel: tx.NewTxModel(db), + PriorityRequestModel: priorityrequest.NewPriorityRequestModel(db), - AccountModel: account.NewAccountModel(db), - AccountHistoryModel: account.NewAccountHistoryModel(db), - L2AssetInfoModel: asset.NewAssetModel(db), - LiquidityModel: liquidity.NewLiquidityModel(db), - LiquidityHistoryModel: liquidity.NewLiquidityHistoryModel(db), - L2NftModel: nft.NewL2NftModel(db), - L2NftHistoryModel: nft.NewL2NftHistoryModel(db), - TxPoolModel: tx.NewTxPoolModel(db), + AccountModel: account.NewAccountModel(db), + AccountHistoryModel: account.NewAccountHistoryModel(db), + L2AssetInfoModel: asset.NewAssetModel(db), + L2NftModel: nft.NewL2NftModel(db), + L2NftHistoryModel: nft.NewL2NftHistoryModel(db), + TxPoolModel: tx.NewTxPoolModel(db), SysConfigModel: sysconfig.NewSysConfigModel(db), } diff --git a/core/statedb/state_cache.go b/core/statedb/state_cache.go index 528a96438..8b28ece3f 100644 --- a/core/statedb/state_cache.go +++ b/core/statedb/state_cache.go @@ -1,10 +1,12 @@ package statedb import ( + "math/big" + "github.com/ethereum/go-ethereum/common" cryptoTypes "github.com/bnb-chain/zkbnb-crypto/circuit/types" - "github.com/bnb-chain/zkbnb/dao/liquidity" + "github.com/bnb-chain/zkbnb-crypto/ffmath" "github.com/bnb-chain/zkbnb/dao/nft" "github.com/bnb-chain/zkbnb/dao/tx" "github.com/bnb-chain/zkbnb/types" @@ -21,16 +23,12 @@ type StateCache struct { Txs []*tx.Tx // Record the flat data that should be updated. - PendingNewAccountMap map[int64]*types.AccountInfo - PendingNewLiquidityMap map[int64]*liquidity.Liquidity - PendingNewNftMap map[int64]*nft.L2Nft - PendingUpdateAccountMap map[int64]*types.AccountInfo - PendingUpdateLiquidityMap map[int64]*liquidity.Liquidity - PendingUpdateNftMap map[int64]*nft.L2Nft + PendingAccountMap map[int64]*types.AccountInfo + PendingNftMap map[int64]*nft.L2Nft + PendingGasMap map[int64]*big.Int //pending gas changes of a block // Record the tree states that should be updated. dirtyAccountsAndAssetsMap map[int64]map[int64]bool - dirtyLiquidityMap map[int64]bool dirtyNftMap map[int64]bool } @@ -39,12 +37,9 @@ func NewStateCache(stateRoot string) *StateCache { StateRoot: stateRoot, Txs: make([]*tx.Tx, 0), - PendingNewAccountMap: make(map[int64]*types.AccountInfo, 0), - PendingNewLiquidityMap: make(map[int64]*liquidity.Liquidity, 0), - PendingNewNftMap: make(map[int64]*nft.L2Nft, 0), - PendingUpdateAccountMap: make(map[int64]*types.AccountInfo, 0), - PendingUpdateLiquidityMap: make(map[int64]*liquidity.Liquidity, 0), - PendingUpdateNftMap: make(map[int64]*nft.L2Nft, 0), + PendingAccountMap: make(map[int64]*types.AccountInfo, 0), + PendingNftMap: make(map[int64]*nft.L2Nft, 0), + PendingGasMap: make(map[int64]*big.Int, 0), PubData: make([]byte, 0), PriorityOperations: 0, @@ -53,7 +48,6 @@ func NewStateCache(stateRoot string) *StateCache { PendingOnChainOperationsHash: common.FromHex(types.EmptyStringKeccak), dirtyAccountsAndAssetsMap: make(map[int64]map[int64]bool, 0), - dirtyLiquidityMap: make(map[int64]bool, 0), dirtyNftMap: make(map[int64]bool, 0), } } @@ -81,70 +75,44 @@ func (c *StateCache) MarkAccountAssetsDirty(accountIndex int64, assets []int64) } } -func (c *StateCache) MarkLiquidityDirty(pairIndex int64) { - c.dirtyLiquidityMap[pairIndex] = true -} - func (c *StateCache) MarkNftDirty(nftIndex int64) { c.dirtyNftMap[nftIndex] = true } func (c *StateCache) GetPendingAccount(accountIndex int64) (*types.AccountInfo, bool) { - account, exist := c.PendingNewAccountMap[accountIndex] - if exist { - return account, exist - } - account, exist = c.PendingUpdateAccountMap[accountIndex] + account, exist := c.PendingAccountMap[accountIndex] if exist { return account, exist } return nil, false } -func (c *StateCache) GetPendingLiquidity(pairIndex int64) (*liquidity.Liquidity, bool) { - liquidity, exist := c.PendingNewLiquidityMap[pairIndex] - if exist { - return liquidity, exist - } - liquidity, exist = c.PendingUpdateLiquidityMap[pairIndex] - if exist { - return liquidity, exist - } - return nil, false -} - func (c *StateCache) GetPendingNft(nftIndex int64) (*nft.L2Nft, bool) { - nft, exist := c.PendingNewNftMap[nftIndex] - if exist { - return nft, exist - } - nft, exist = c.PendingUpdateNftMap[nftIndex] + nft, exist := c.PendingNftMap[nftIndex] if exist { return nft, exist } return nil, false } -func (c *StateCache) SetPendingNewAccount(accountIndex int64, account *types.AccountInfo) { - c.PendingNewAccountMap[accountIndex] = account +func (c *StateCache) SetPendingAccount(accountIndex int64, account *types.AccountInfo) { + c.PendingAccountMap[accountIndex] = account } -func (c *StateCache) SetPendingUpdateAccount(accountIndex int64, account *types.AccountInfo) { - c.PendingUpdateAccountMap[accountIndex] = account +func (c *StateCache) SetPendingNft(nftIndex int64, nft *nft.L2Nft) { + c.PendingNftMap[nftIndex] = nft } -func (c *StateCache) SetPendingUpdateLiquidity(pairIndex int64, liquidity *liquidity.Liquidity) { - c.PendingUpdateLiquidityMap[pairIndex] = liquidity -} - -func (c *StateCache) SetPendingNewLiquidity(pairIndex int64, liquidity *liquidity.Liquidity) { - c.PendingNewLiquidityMap[pairIndex] = liquidity -} - -func (c *StateCache) SetPendingNewNft(nftIndex int64, nft *nft.L2Nft) { - c.PendingNewNftMap[nftIndex] = nft +func (c *StateCache) GetPendingUpdateGas(assetId int64) *big.Int { + if delta, ok := c.PendingGasMap[assetId]; ok { + return delta + } + return types.ZeroBigInt } -func (c *StateCache) SetPendingUpdateNft(nftIndex int64, nft *nft.L2Nft) { - c.PendingUpdateNftMap[nftIndex] = nft +func (c *StateCache) SetPendingUpdateGas(assetId int64, balanceDelta *big.Int) { + if _, ok := c.PendingGasMap[assetId]; !ok { + c.PendingGasMap[assetId] = types.ZeroBigInt + } + c.PendingGasMap[assetId] = ffmath.Add(c.PendingGasMap[assetId], balanceDelta) } diff --git a/core/statedb/statedb.go b/core/statedb/statedb.go index 52618cd13..b1654211e 100644 --- a/core/statedb/statedb.go +++ b/core/statedb/statedb.go @@ -12,11 +12,11 @@ import ( lru "github.com/hashicorp/golang-lru" "github.com/zeromicro/go-zero/core/logx" + "github.com/bnb-chain/zkbnb-crypto/ffmath" bsmt "github.com/bnb-chain/zkbnb-smt" "github.com/bnb-chain/zkbnb/common/chain" "github.com/bnb-chain/zkbnb/dao/account" "github.com/bnb-chain/zkbnb/dao/dbcache" - "github.com/bnb-chain/zkbnb/dao/liquidity" "github.com/bnb-chain/zkbnb/dao/nft" "github.com/bnb-chain/zkbnb/tree" "github.com/bnb-chain/zkbnb/types" @@ -24,16 +24,14 @@ import ( var ( DefaultCacheConfig = CacheConfig{ - AccountCacheSize: 2048, - LiquidityCacheSize: 2048, - NftCacheSize: 2048, + AccountCacheSize: 2048, + NftCacheSize: 2048, } ) type CacheConfig struct { - AccountCacheSize int - LiquidityCacheSize int - NftCacheSize int + AccountCacheSize int + NftCacheSize int } func (c *CacheConfig) sanitize() *CacheConfig { @@ -41,10 +39,6 @@ func (c *CacheConfig) sanitize() *CacheConfig { c.AccountCacheSize = DefaultCacheConfig.AccountCacheSize } - if c.LiquidityCacheSize <= 0 { - c.LiquidityCacheSize = DefaultCacheConfig.LiquidityCacheSize - } - if c.NftCacheSize <= 0 { c.NftCacheSize = DefaultCacheConfig.NftCacheSize } @@ -60,20 +54,18 @@ type StateDB struct { redisCache dbcache.Cache // Flat state - AccountCache *lru.Cache - LiquidityCache *lru.Cache - NftCache *lru.Cache + AccountCache *lru.Cache + NftCache *lru.Cache // Tree state AccountTree bsmt.SparseMerkleTree - LiquidityTree bsmt.SparseMerkleTree NftTree bsmt.SparseMerkleTree - AccountAssetTrees []bsmt.SparseMerkleTree + AccountAssetTrees *tree.AssetTreeCache TreeCtx *tree.Context } func NewStateDB(treeCtx *tree.Context, chainDb *ChainDB, - redisCache dbcache.Cache, cacheConfig *CacheConfig, + redisCache dbcache.Cache, cacheConfig *CacheConfig, assetCacheSize int, stateRoot string, curHeight int64) (*StateDB, error) { err := tree.SetupTreeDB(treeCtx) if err != nil { @@ -85,20 +77,12 @@ func NewStateDB(treeCtx *tree.Context, chainDb *ChainDB, chainDb.AccountHistoryModel, curHeight, treeCtx, + assetCacheSize, ) if err != nil { logx.Error("dbinitializer account tree failed:", err) return nil, err } - liquidityTree, err := tree.InitLiquidityTree( - chainDb.LiquidityHistoryModel, - curHeight, - treeCtx, - ) - if err != nil { - logx.Error("dbinitializer liquidity tree failed:", err) - return nil, err - } nftTree, err := tree.InitNftTree( chainDb.L2NftHistoryModel, curHeight, @@ -115,11 +99,6 @@ func NewStateDB(treeCtx *tree.Context, chainDb *ChainDB, logx.Error("init account cache failed:", err) return nil, err } - liquidityCache, err := lru.New(cacheConfig.LiquidityCacheSize) - if err != nil { - logx.Error("init liquidity cache failed:", err) - return nil, err - } nftCache, err := lru.New(cacheConfig.NftCacheSize) if err != nil { logx.Error("init nft cache failed:", err) @@ -127,15 +106,13 @@ func NewStateDB(treeCtx *tree.Context, chainDb *ChainDB, } return &StateDB{ - StateCache: NewStateCache(stateRoot), - chainDb: chainDb, - redisCache: redisCache, - AccountCache: accountCache, - LiquidityCache: liquidityCache, - NftCache: nftCache, + StateCache: NewStateCache(stateRoot), + chainDb: chainDb, + redisCache: redisCache, + AccountCache: accountCache, + NftCache: nftCache, AccountTree: accountTree, - LiquidityTree: liquidityTree, NftTree: nftTree, AccountAssetTrees: accountAssetTrees, TreeCtx: treeCtx, @@ -148,24 +125,18 @@ func NewStateDBForDryRun(redisCache dbcache.Cache, cacheConfig *CacheConfig, cha logx.Error("init account cache failed:", err) return nil, err } - liquidityCache, err := lru.New(cacheConfig.LiquidityCacheSize) - if err != nil { - logx.Error("init liquidity cache failed:", err) - return nil, err - } nftCache, err := lru.New(cacheConfig.NftCacheSize) if err != nil { logx.Error("init nft cache failed:", err) return nil, err } return &StateDB{ - dryRun: true, - redisCache: redisCache, - chainDb: chainDb, - AccountCache: accountCache, - LiquidityCache: liquidityCache, - NftCache: nftCache, - StateCache: NewStateCache(""), + dryRun: true, + redisCache: redisCache, + chainDb: chainDb, + AccountCache: accountCache, + NftCache: nftCache, + StateCache: NewStateCache(""), }, nil } @@ -223,21 +194,52 @@ func (s *StateDB) GetAccount(accountIndex int64) (*account.Account, error) { return account, nil } -func (s *StateDB) GetLiquidity(pairIndex int64) (*liquidity.Liquidity, error) { - pending, exist := s.StateCache.GetPendingLiquidity(pairIndex) - if exist { - return pending, nil +// GetAccountByName get the account by its name. +// Firstly, try to find the account in the current state cache, it iterates the pending +// account map, not performance friendly, please take care when use this API. +// Secondly, if not found in the current state cache, then try to find the account from database. +func (s *StateDB) GetAccountByName(accountName string) (*account.Account, error) { + for _, accountInfo := range s.PendingAccountMap { + if accountInfo.AccountName == accountName { + account, err := chain.FromFormatAccountInfo(accountInfo) + if err != nil { + return nil, err + } + + return account, nil + } } - cached, exist := s.LiquidityCache.Get(pairIndex) - if exist { - return cached.(*liquidity.Liquidity), nil + + account, err := s.chainDb.AccountModel.GetAccountByName(accountName) + if err != nil { + return nil, err } - liquidity, err := s.chainDb.LiquidityModel.GetLiquidityByIndex(pairIndex) + + return account, nil +} + +// GetAccountByNameHash get the account by its name hash. +// Firstly, try to find the account in the current state cache, it iterates the pending +// account map, not performance friendly, please take care when use this API. +// Secondly, if not found in the current state cache, then try to find the account from database. +func (s *StateDB) GetAccountByNameHash(accountNameHash string) (*account.Account, error) { + for _, accountInfo := range s.PendingAccountMap { + if accountInfo.AccountNameHash == accountNameHash { + account, err := chain.FromFormatAccountInfo(accountInfo) + if err != nil { + return nil, err + } + + return account, nil + } + } + + account, err := s.chainDb.AccountModel.GetAccountByNameHash(accountNameHash) if err != nil { return nil, err } - s.LiquidityCache.Add(pairIndex, liquidity) - return liquidity, nil + + return account, nil } func (s *StateDB) GetNft(nftIndex int64) (*nft.L2Nft, error) { @@ -273,53 +275,41 @@ func (s *StateDB) syncPendingAccount(pendingAccount map[int64]*types.AccountInfo return nil } -func (s *StateDB) syncPendingLiquidity(pendingLiquidity map[int64]*liquidity.Liquidity) error { - for index, liquidity := range pendingLiquidity { - err := s.redisCache.Set(context.Background(), dbcache.LiquidityKeyByIndex(index), liquidity) +func (s *StateDB) syncPendingNft(pendingNft map[int64]*nft.L2Nft) error { + for index, nft := range pendingNft { + err := s.redisCache.Set(context.Background(), dbcache.NftKeyByIndex(index), nft) if err != nil { return fmt.Errorf("cache to redis failed: %v", err) } - s.LiquidityCache.Add(index, liquidity) + s.NftCache.Add(index, nft) } return nil } -func (s *StateDB) syncPendingNft(pendingNft map[int64]*nft.L2Nft) error { - for index, nft := range pendingNft { - err := s.redisCache.Set(context.Background(), dbcache.NftKeyByIndex(index), nft) +func (s *StateDB) SyncPendingGasAccount() error { + if cacheAccount, ok := s.AccountCache.Get(types.GasAccount); ok { + formatAccount := cacheAccount.(*types.AccountInfo) + s.applyGasUpdate(formatAccount) + account, err := chain.FromFormatAccountInfo(formatAccount) + if err != nil { + return err + } + err = s.redisCache.Set(context.Background(), dbcache.AccountKeyByIndex(account.AccountIndex), account) if err != nil { return fmt.Errorf("cache to redis failed: %v", err) } - s.NftCache.Add(index, nft) + s.AccountCache.Add(account.AccountIndex, formatAccount) } return nil } func (s *StateDB) SyncStateCacheToRedis() error { - // Sync new create to cache. - err := s.syncPendingAccount(s.PendingNewAccountMap) - if err != nil { - return err - } - err = s.syncPendingLiquidity(s.PendingNewLiquidityMap) + // Sync pending to cache. + err := s.syncPendingAccount(s.PendingAccountMap) if err != nil { return err } - err = s.syncPendingNft(s.PendingNewNftMap) - if err != nil { - return err - } - - // Sync pending update to cache. - err = s.syncPendingAccount(s.PendingUpdateAccountMap) - if err != nil { - return err - } - err = s.syncPendingLiquidity(s.PendingUpdateLiquidityMap) - if err != nil { - return err - } - err = s.syncPendingNft(s.PendingUpdateNftMap) + err = s.syncPendingNft(s.PendingNftMap) if err != nil { return err } @@ -331,19 +321,31 @@ func (s *StateDB) PurgeCache(stateRoot string) { s.StateCache = NewStateCache(stateRoot) } -func (s *StateDB) GetPendingAccount(blockHeight int64) ([]*account.Account, []*account.Account, []*account.AccountHistory, error) { - pendingNewAccount := make([]*account.Account, 0) - pendingUpdateAccount := make([]*account.Account, 0) - pendingNewAccountHistory := make([]*account.AccountHistory, 0) +func (s *StateDB) GetPendingAccount(blockHeight int64) ([]*account.Account, []*account.AccountHistory, error) { + pendingAccount := make([]*account.Account, 0) + pendingAccountHistory := make([]*account.AccountHistory, 0) + + gasChanged := false + for _, delta := range s.StateCache.PendingGasMap { + if delta.Cmp(types.ZeroBigInt) > 0 { + gasChanged = true + break + } + } + + handledGasAccount := false + for _, formatAccount := range s.PendingAccountMap { + if formatAccount.AccountIndex == types.GasAccount && gasChanged { + handledGasAccount = true + s.applyGasUpdate(formatAccount) + } - for _, formatAccount := range s.PendingNewAccountMap { newAccount, err := chain.FromFormatAccountInfo(formatAccount) if err != nil { - return nil, nil, nil, err + return nil, nil, err } - - pendingNewAccount = append(pendingNewAccount, newAccount) - pendingNewAccountHistory = append(pendingNewAccountHistory, &account.AccountHistory{ + pendingAccount = append(pendingAccount, newAccount) + pendingAccountHistory = append(pendingAccountHistory, &account.AccountHistory{ AccountIndex: newAccount.AccountIndex, Nonce: newAccount.Nonce, CollectionNonce: newAccount.CollectionNonce, @@ -353,17 +355,25 @@ func (s *StateDB) GetPendingAccount(blockHeight int64) ([]*account.Account, []*a }) } - for index, formatAccount := range s.PendingUpdateAccountMap { - if _, exist := s.PendingNewAccountMap[index]; exist { - continue + if !handledGasAccount && gasChanged { + gasAccount, err := s.GetAccount(types.GasAccount) + if err != nil { + return nil, nil, err } + formatAccount, err := chain.ToFormatAccountInfo(gasAccount) + if err != nil { + return nil, nil, err + } + s.applyGasUpdate(formatAccount) + newAccount, err := chain.FromFormatAccountInfo(formatAccount) if err != nil { - return nil, nil, nil, err + return nil, nil, err } - pendingUpdateAccount = append(pendingUpdateAccount, newAccount) - pendingNewAccountHistory = append(pendingNewAccountHistory, &account.AccountHistory{ + + pendingAccount = append(pendingAccount, newAccount) + pendingAccountHistory = append(pendingAccountHistory, &account.AccountHistory{ AccountIndex: newAccount.AccountIndex, Nonce: newAccount.Nonce, CollectionNonce: newAccount.CollectionNonce, @@ -373,81 +383,29 @@ func (s *StateDB) GetPendingAccount(blockHeight int64) ([]*account.Account, []*a }) } - return pendingNewAccount, pendingUpdateAccount, pendingNewAccountHistory, nil + return pendingAccount, pendingAccountHistory, nil } -func (s *StateDB) GetPendingLiquidity(blockHeight int64) ([]*liquidity.Liquidity, []*liquidity.Liquidity, []*liquidity.LiquidityHistory, error) { - pendingNewLiquidity := make([]*liquidity.Liquidity, 0) - pendingUpdateLiquidity := make([]*liquidity.Liquidity, 0) - pendingNewLiquidityHistory := make([]*liquidity.LiquidityHistory, 0) - - for _, newLiquidity := range s.PendingNewLiquidityMap { - pendingNewLiquidity = append(pendingNewLiquidity, newLiquidity) - pendingNewLiquidityHistory = append(pendingNewLiquidityHistory, &liquidity.LiquidityHistory{ - PairIndex: newLiquidity.PairIndex, - AssetAId: newLiquidity.AssetAId, - AssetA: newLiquidity.AssetA, - AssetBId: newLiquidity.AssetBId, - AssetB: newLiquidity.AssetB, - LpAmount: newLiquidity.LpAmount, - KLast: newLiquidity.KLast, - FeeRate: newLiquidity.FeeRate, - TreasuryAccountIndex: newLiquidity.TreasuryAccountIndex, - TreasuryRate: newLiquidity.TreasuryRate, - L2BlockHeight: blockHeight, - }) - } - - for index, newLiquidity := range s.PendingUpdateLiquidityMap { - if _, exist := s.PendingNewLiquidityMap[index]; exist { - continue +func (s *StateDB) applyGasUpdate(formatAccount *types.AccountInfo) { + for assetId, delta := range s.StateCache.PendingGasMap { + if asset, ok := formatAccount.AssetInfo[assetId]; ok { + formatAccount.AssetInfo[assetId].Balance = ffmath.Add(asset.Balance, delta) + } else { + formatAccount.AssetInfo[assetId] = &types.AccountAsset{ + Balance: delta, + OfferCanceledOrFinalized: types.ZeroBigInt, + } } - - pendingUpdateLiquidity = append(pendingUpdateLiquidity, newLiquidity) - pendingNewLiquidityHistory = append(pendingNewLiquidityHistory, &liquidity.LiquidityHistory{ - PairIndex: newLiquidity.PairIndex, - AssetAId: newLiquidity.AssetAId, - AssetA: newLiquidity.AssetA, - AssetBId: newLiquidity.AssetBId, - AssetB: newLiquidity.AssetB, - LpAmount: newLiquidity.LpAmount, - KLast: newLiquidity.KLast, - FeeRate: newLiquidity.FeeRate, - TreasuryAccountIndex: newLiquidity.TreasuryAccountIndex, - TreasuryRate: newLiquidity.TreasuryRate, - L2BlockHeight: blockHeight, - }) } - - return pendingNewLiquidity, pendingUpdateLiquidity, pendingNewLiquidityHistory, nil } -func (s *StateDB) GetPendingNft(blockHeight int64) ([]*nft.L2Nft, []*nft.L2Nft, []*nft.L2NftHistory, error) { - pendingNewNft := make([]*nft.L2Nft, 0) - pendingUpdateNft := make([]*nft.L2Nft, 0) - pendingNewNftHistory := make([]*nft.L2NftHistory, 0) - - for _, newNft := range s.PendingNewNftMap { - pendingNewNft = append(pendingNewNft, newNft) - pendingNewNftHistory = append(pendingNewNftHistory, &nft.L2NftHistory{ - NftIndex: newNft.NftIndex, - CreatorAccountIndex: newNft.CreatorAccountIndex, - OwnerAccountIndex: newNft.OwnerAccountIndex, - NftContentHash: newNft.NftContentHash, - NftL1Address: newNft.NftL1Address, - NftL1TokenId: newNft.NftL1TokenId, - CreatorTreasuryRate: newNft.CreatorTreasuryRate, - CollectionId: newNft.CollectionId, - L2BlockHeight: blockHeight, - }) - } +func (s *StateDB) GetPendingNft(blockHeight int64) ([]*nft.L2Nft, []*nft.L2NftHistory, error) { + pendingNft := make([]*nft.L2Nft, 0) + pendingNftHistory := make([]*nft.L2NftHistory, 0) - for index, newNft := range s.PendingUpdateNftMap { - if _, exist := s.PendingNewNftMap[index]; exist { - continue - } - pendingUpdateNft = append(pendingUpdateNft, newNft) - pendingNewNftHistory = append(pendingNewNftHistory, &nft.L2NftHistory{ + for _, newNft := range s.PendingNftMap { + pendingNft = append(pendingNft, newNft) + pendingNftHistory = append(pendingNftHistory, &nft.L2NftHistory{ NftIndex: newNft.NftIndex, CreatorAccountIndex: newNft.CreatorAccountIndex, OwnerAccountIndex: newNft.OwnerAccountIndex, @@ -460,7 +418,7 @@ func (s *StateDB) GetPendingNft(blockHeight int64) ([]*nft.L2Nft, []*nft.L2Nft, }) } - return pendingNewNft, pendingUpdateNft, pendingNewNftHistory, nil + return pendingNft, pendingNftHistory, nil } func (s *StateDB) DeepCopyAccounts(accountIds []int64) (map[int64]*types.AccountInfo, error) { @@ -477,11 +435,7 @@ func (s *StateDB) DeepCopyAccounts(accountIds []int64) (map[int64]*types.Account if err != nil { return nil, err } - accountCopy, err := account.DeepCopy() - if err != nil { - return nil, err - } - accounts[accountId] = accountCopy + accounts[accountId] = account.DeepCopy() } return accounts, nil @@ -512,7 +466,6 @@ func (s *StateDB) PrepareAccountsAndAssets(accountAssetsMap map[int64]map[int64] account.AssetInfo[assetId] = &types.AccountAsset{ AssetId: assetId, Balance: types.ZeroBigInt, - LpAmount: types.ZeroBigInt, OfferCanceledOrFinalized: types.ZeroBigInt, } } @@ -523,22 +476,6 @@ func (s *StateDB) PrepareAccountsAndAssets(accountAssetsMap map[int64]map[int64] return nil } -func (s *StateDB) PrepareLiquidity(pairIndex int64) error { - if s.dryRun { - l := &liquidity.Liquidity{} - redisLiquidity, err := s.redisCache.Get(context.Background(), dbcache.LiquidityKeyByIndex(pairIndex), l) - if err == nil && redisLiquidity != nil { - s.LiquidityCache.Add(pairIndex, l) - } - } - - _, err := s.GetLiquidity(pairIndex) - if err != nil { - return err - } - return nil -} - func (s *StateDB) PrepareNft(nftIndex int64) (*nft.L2Nft, error) { if s.dryRun { n := &nft.L2Nft{} @@ -567,16 +504,6 @@ func (s *StateDB) IntermediateRoot(cleanDirty bool) error { } } - for pairIndex, isDirty := range s.dirtyLiquidityMap { - if !isDirty { - continue - } - err := s.updateLiquidityTree(pairIndex) - if err != nil { - return err - } - } - for nftIndex, isDirty := range s.dirtyNftMap { if !isDirty { continue @@ -589,13 +516,11 @@ func (s *StateDB) IntermediateRoot(cleanDirty bool) error { if cleanDirty { s.dirtyAccountsAndAssetsMap = make(map[int64]map[int64]bool, 0) - s.dirtyLiquidityMap = make(map[int64]bool, 0) s.dirtyNftMap = make(map[int64]bool, 0) } hFunc := mimc.NewMiMC() hFunc.Write(s.AccountTree.Root()) - hFunc.Write(s.LiquidityTree.Root()) hFunc.Write(s.NftTree.Root()) s.StateRoot = common.Bytes2Hex(hFunc.Sum(nil)) return nil @@ -606,28 +531,41 @@ func (s *StateDB) updateAccountTree(accountIndex int64, assets []int64) error { if err != nil { return err } + isGasAccount := accountIndex == types.GasAccount for _, assetId := range assets { + isGasAsset := false + if isGasAccount { + for _, gasAssetId := range types.GasAssets { + if assetId == gasAssetId { + isGasAsset = true + break + } + } + } + balance := account.AssetInfo[assetId].Balance + if isGasAsset { + balance = ffmath.Add(balance, s.GetPendingUpdateGas(assetId)) + } assetLeaf, err := tree.ComputeAccountAssetLeafHash( - account.AssetInfo[assetId].Balance.String(), - account.AssetInfo[assetId].LpAmount.String(), + balance.String(), account.AssetInfo[assetId].OfferCanceledOrFinalized.String(), ) if err != nil { return fmt.Errorf("compute new account asset leaf failed: %v", err) } - err = s.AccountAssetTrees[accountIndex].Set(uint64(assetId), assetLeaf) + err = s.AccountAssetTrees.Get(accountIndex).Set(uint64(assetId), assetLeaf) if err != nil { return fmt.Errorf("update asset tree failed: %v", err) } } - account.AssetRoot = common.Bytes2Hex(s.AccountAssetTrees[accountIndex].Root()) + account.AssetRoot = common.Bytes2Hex(s.AccountAssetTrees.Get(accountIndex).Root()) nAccountLeafHash, err := tree.ComputeAccountLeafHash( account.AccountNameHash, account.PublicKey, account.Nonce, account.CollectionNonce, - s.AccountAssetTrees[accountIndex].Root(), + s.AccountAssetTrees.Get(accountIndex).Root(), ) if err != nil { return fmt.Errorf("unable to compute account leaf: %v", err) @@ -640,33 +578,6 @@ func (s *StateDB) updateAccountTree(accountIndex int64, assets []int64) error { return nil } -func (s *StateDB) updateLiquidityTree(pairIndex int64) error { - liquidity, err := s.GetLiquidity(pairIndex) - if err != nil { - return err - } - nLiquidityAssetLeaf, err := tree.ComputeLiquidityAssetLeafHash( - liquidity.AssetAId, - liquidity.AssetA, - liquidity.AssetBId, - liquidity.AssetB, - liquidity.LpAmount, - liquidity.KLast, - liquidity.FeeRate, - liquidity.TreasuryAccountIndex, - liquidity.TreasuryRate, - ) - if err != nil { - return fmt.Errorf("unable to compute liquidity leaf: %v", err) - } - err = s.LiquidityTree.Set(uint64(pairIndex), nLiquidityAssetLeaf) - if err != nil { - return fmt.Errorf("unable to update liquidity tree: %v", err) - } - - return nil -} - func (s *StateDB) updateNftTree(nftIndex int64) error { nft, err := s.GetNft(nftIndex) if err != nil { @@ -718,20 +629,16 @@ func (s *StateDB) GetPendingNonce(accountIndex int64) (int64, error) { } func (s *StateDB) GetNextAccountIndex() int64 { - return int64(len(s.AccountAssetTrees)) + return s.AccountAssetTrees.GetNextAccountIndex() } func (s *StateDB) GetNextNftIndex() int64 { - if len(s.PendingNewNftMap) == 0 { - maxNftIndex, err := s.chainDb.L2NftModel.GetLatestNftIndex() - if err != nil { - panic("get latest nft index error: " + err.Error()) - } - return maxNftIndex + 1 + maxNftIndex, err := s.chainDb.L2NftModel.GetLatestNftIndex() + if err != nil { + panic("get latest nft index error: " + err.Error()) } - maxNftIndex := int64(-1) - for index := range s.PendingNewNftMap { + for index := range s.PendingNftMap { if index > maxNftIndex { maxNftIndex = index } diff --git a/dao/account/account.go b/dao/account/account.go index 3342266ab..ec820e958 100644 --- a/dao/account/account.go +++ b/dao/account/account.go @@ -43,7 +43,6 @@ type ( GetAccountByNameHash(nameHash string) (account *Account, err error) GetAccounts(limit int, offset int64) (accounts []*Account, err error) GetAccountsTotalCount() (count int64, err error) - CreateAccountsInTransact(tx *gorm.DB, accounts []*Account) error UpdateAccountsInTransact(tx *gorm.DB, accounts []*Account) error } @@ -161,17 +160,6 @@ func (m *defaultAccountModel) GetConfirmedAccountByIndex(accountIndex int64) (ac return account, nil } -func (m *defaultAccountModel) CreateAccountsInTransact(tx *gorm.DB, accounts []*Account) error { - dbTx := tx.Table(m.table).CreateInBatches(accounts, len(accounts)) - if dbTx.Error != nil { - return dbTx.Error - } - if dbTx.RowsAffected != int64(len(accounts)) { - return types.DbErrFailToCreateAccount - } - return nil -} - func (m *defaultAccountModel) UpdateAccountsInTransact(tx *gorm.DB, accounts []*Account) error { for _, account := range accounts { dbTx := tx.Table(m.table).Where("account_index = ?", account.AccountIndex). @@ -181,7 +169,11 @@ func (m *defaultAccountModel) UpdateAccountsInTransact(tx *gorm.DB, accounts []* return dbTx.Error } if dbTx.RowsAffected == 0 { - return types.DbErrFailToUpdateAccount + // this account is new, we need create first + dbTx = tx.Table(m.table).Create(&account) + if dbTx.Error != nil { + return dbTx.Error + } } } return nil diff --git a/dao/account/account_history.go b/dao/account/account_history.go index 52ea69cd1..8024854ef 100644 --- a/dao/account/account_history.go +++ b/dao/account/account_history.go @@ -33,6 +33,7 @@ type ( GetValidAccounts(height int64, limit int, offset int) (rowsAffected int64, accounts []*AccountHistory, err error) GetValidAccountCount(height int64) (accounts int64, err error) CreateAccountHistoriesInTransact(tx *gorm.DB, histories []*AccountHistory) error + GetLatestAccountHistory(accountIndex, height int64) (accountHistory *AccountHistory, err error) } defaultAccountHistoryModel struct { @@ -47,7 +48,7 @@ type ( CollectionNonce int64 AssetInfo string AssetRoot string - L2BlockHeight int64 + L2BlockHeight int64 `gorm:"index"` } ) @@ -120,3 +121,13 @@ func (m *defaultAccountHistoryModel) CreateAccountHistoriesInTransact(tx *gorm.D } return nil } + +func (m *defaultAccountHistoryModel) GetLatestAccountHistory(accountIndex, height int64) (accountHistory *AccountHistory, err error) { + dbTx := m.DB.Table(m.table).Where("account_index = ? and l2_block_height < ?", accountIndex, height).Order("l2_block_height desc").Limit(1).Find(&accountHistory) + if dbTx.Error != nil { + return nil, types.DbErrSqlOperation + } else if dbTx.RowsAffected == 0 { + return nil, types.DbErrNotFound + } + return accountHistory, nil +} diff --git a/dao/block/block.go b/dao/block/block.go index fa3d93c40..6604b2724 100644 --- a/dao/block/block.go +++ b/dao/block/block.go @@ -24,7 +24,6 @@ import ( "github.com/bnb-chain/zkbnb/dao/account" "github.com/bnb-chain/zkbnb/dao/compressedblock" - "github.com/bnb-chain/zkbnb/dao/liquidity" "github.com/bnb-chain/zkbnb/dao/nft" "github.com/bnb-chain/zkbnb/dao/tx" "github.com/bnb-chain/zkbnb/types" @@ -90,15 +89,10 @@ type ( Block *Block CompressedBlock *compressedblock.CompressedBlock - PendingNewAccount []*account.Account - PendingUpdateAccount []*account.Account - PendingNewAccountHistory []*account.AccountHistory - PendingNewLiquidity []*liquidity.Liquidity - PendingUpdateLiquidity []*liquidity.Liquidity - PendingNewLiquidityHistory []*liquidity.LiquidityHistory - PendingNewNft []*nft.L2Nft - PendingUpdateNft []*nft.L2Nft - PendingNewNftHistory []*nft.L2NftHistory + PendingAccount []*account.Account + PendingAccountHistory []*account.AccountHistory + PendingNft []*nft.L2Nft + PendingNftHistory []*nft.L2NftHistory } ) diff --git a/dao/dbcache/cache.go b/dao/dbcache/cache.go index 4c96fa954..485b5184d 100644 --- a/dao/dbcache/cache.go +++ b/dao/dbcache/cache.go @@ -16,21 +16,16 @@ type Cache interface { } const ( - AccountKeyPrefix = "cache:account_" - LiquidityKeyPrefix = "cache:liquidity_" - NftKeyPrefix = "cache:nft_" - GasAccountKey = "cache:gasAccount" - GasConfigKey = "cache:gasConfig" + AccountKeyPrefix = "cache:account_" + NftKeyPrefix = "cache:nft_" + GasAccountKey = "cache:gasAccount" + GasConfigKey = "cache:gasConfig" ) func AccountKeyByIndex(accountIndex int64) string { return AccountKeyPrefix + fmt.Sprintf("%d", accountIndex) } -func LiquidityKeyByIndex(pairIndex int64) string { - return LiquidityKeyPrefix + fmt.Sprintf("%d", pairIndex) -} - func NftKeyByIndex(nftIndex int64) string { return NftKeyPrefix + fmt.Sprintf("%d", nftIndex) } diff --git a/dao/l1rolluptx/l1_rollup_tx.go b/dao/l1rolluptx/l1_rollup_tx.go index ee5cc5620..14c277e79 100644 --- a/dao/l1rolluptx/l1_rollup_tx.go +++ b/dao/l1rolluptx/l1_rollup_tx.go @@ -43,6 +43,7 @@ type ( GetLatestHandledTx(txType int64) (tx *L1RollupTx, err error) GetLatestPendingTx(txType int64) (tx *L1RollupTx, err error) GetL1RollupTxsByStatus(txStatus int) (txs []*L1RollupTx, err error) + GetL1RollupTxsByHash(hash string) (txs []*L1RollupTx, err error) DeleteL1RollupTx(tx *L1RollupTx) error UpdateL1RollupTxsInTransact(tx *gorm.DB, txs []*L1RollupTx) error } @@ -104,6 +105,16 @@ func (m *defaultL1RollupTxModel) GetL1RollupTxsByStatus(txStatus int) (txs []*L1 return txs, nil } +func (m *defaultL1RollupTxModel) GetL1RollupTxsByHash(hash string) (txs []*L1RollupTx, err error) { + dbTx := m.DB.Table(m.table).Where("l1_tx_hash = ?", hash).Find(&txs) + if dbTx.Error != nil { + return nil, types.DbErrSqlOperation + } else if dbTx.RowsAffected == 0 { + return nil, types.DbErrNotFound + } + return txs, nil +} + func (m *defaultL1RollupTxModel) DeleteL1RollupTx(rollupTx *L1RollupTx) error { return m.DB.Transaction(func(tx *gorm.DB) error { dbTx := tx.Table(m.table).Where("id = ?", rollupTx.ID).Delete(&rollupTx) diff --git a/dao/liquidity/liquidity.go b/dao/liquidity/liquidity.go deleted file mode 100644 index d6be00775..000000000 --- a/dao/liquidity/liquidity.go +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright © 2021 ZkBNB Protocol - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package liquidity - -import ( - "gorm.io/gorm" - - "github.com/bnb-chain/zkbnb/types" -) - -const ( - LiquidityTable = `liquidity` -) - -type ( - LiquidityModel interface { - CreateLiquidityTable() error - DropLiquidityTable() error - GetLiquidityByIndex(index int64) (entity *Liquidity, err error) - GetAllLiquidity() (liquidityList []*Liquidity, err error) - CreateLiquidityInTransact(tx *gorm.DB, liquidity []*Liquidity) error - UpdateLiquidityInTransact(tx *gorm.DB, liquidity []*Liquidity) error - } - - defaultLiquidityModel struct { - table string - DB *gorm.DB - } - - Liquidity struct { - gorm.Model - PairIndex int64 - AssetAId int64 - AssetA string - AssetBId int64 - AssetB string - LpAmount string - KLast string - FeeRate int64 - TreasuryAccountIndex int64 - TreasuryRate int64 - } -) - -func NewLiquidityModel(db *gorm.DB) LiquidityModel { - return &defaultLiquidityModel{ - table: LiquidityTable, - DB: db, - } -} - -func (*Liquidity) TableName() string { - return LiquidityTable -} - -func (m *defaultLiquidityModel) CreateLiquidityTable() error { - return m.DB.AutoMigrate(Liquidity{}) -} - -func (m *defaultLiquidityModel) DropLiquidityTable() error { - return m.DB.Migrator().DropTable(m.table) -} - -func (m *defaultLiquidityModel) GetLiquidityByIndex(pairIndex int64) (entity *Liquidity, err error) { - dbTx := m.DB.Table(m.table).Where("pair_index = ?", pairIndex).Find(&entity) - if dbTx.Error != nil { - return nil, types.DbErrSqlOperation - } else if dbTx.RowsAffected == 0 { - return nil, types.DbErrNotFound - } - return entity, nil -} - -func (m *defaultLiquidityModel) GetAllLiquidity() (liquidityList []*Liquidity, err error) { - dbTx := m.DB.Table(m.table).Order("id").Find(&liquidityList) - if dbTx.Error != nil { - return liquidityList, dbTx.Error - } else if dbTx.RowsAffected == 0 { - return nil, types.DbErrNotFound - } - return liquidityList, nil -} - -func (m *defaultLiquidityModel) CreateLiquidityInTransact(tx *gorm.DB, liquidity []*Liquidity) error { - dbTx := tx.Table(m.table).CreateInBatches(liquidity, len(liquidity)) - if dbTx.Error != nil { - return dbTx.Error - } - if dbTx.RowsAffected != int64(len(liquidity)) { - return types.DbErrFailToCreateLiquidity - } - return nil -} - -func (m *defaultLiquidityModel) UpdateLiquidityInTransact(tx *gorm.DB, liquidity []*Liquidity) error { - for _, pendingLiquidity := range liquidity { - dbTx := tx.Table(m.table).Where("pair_index = ?", pendingLiquidity.PairIndex). - Select("*"). - Updates(&pendingLiquidity) - if dbTx.Error != nil { - return dbTx.Error - } - if dbTx.RowsAffected == 0 { - return types.DbErrFailToUpdateLiquidity - } - } - return nil -} diff --git a/dao/liquidity/liquidity_history.go b/dao/liquidity/liquidity_history.go deleted file mode 100644 index 68314b749..000000000 --- a/dao/liquidity/liquidity_history.go +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright © 2021 ZkBNB Protocol - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package liquidity - -import ( - "gorm.io/gorm" - - "github.com/bnb-chain/zkbnb/types" -) - -const ( - LiquidityHistoryTable = `liquidity_history` -) - -type ( - LiquidityHistoryModel interface { - CreateLiquidityHistoryTable() error - DropLiquidityHistoryTable() error - GetLatestLiquidityByBlockHeight(blockHeight int64, limit int, offset int) (entities []*LiquidityHistory, err error) - GetLatestLiquidityCountByBlockHeight(blockHeight int64) (count int64, err error) - CreateLiquidityHistoriesInTransact(tx *gorm.DB, histories []*LiquidityHistory) error - } - - defaultLiquidityHistoryModel struct { - table string - DB *gorm.DB - } - - LiquidityHistory struct { - gorm.Model - PairIndex int64 - AssetAId int64 - AssetA string - AssetBId int64 - AssetB string - LpAmount string - KLast string - FeeRate int64 - TreasuryAccountIndex int64 - TreasuryRate int64 - L2BlockHeight int64 - } -) - -func NewLiquidityHistoryModel(db *gorm.DB) LiquidityHistoryModel { - return &defaultLiquidityHistoryModel{ - table: LiquidityHistoryTable, - DB: db, - } -} - -func (*LiquidityHistory) TableName() string { - return LiquidityHistoryTable -} - -func (m *defaultLiquidityHistoryModel) CreateLiquidityHistoryTable() error { - return m.DB.AutoMigrate(LiquidityHistory{}) -} - -func (m *defaultLiquidityHistoryModel) DropLiquidityHistoryTable() error { - return m.DB.Migrator().DropTable(m.table) -} - -func (m *defaultLiquidityHistoryModel) GetLatestLiquidityByBlockHeight(blockHeight int64, limit int, offset int) (entities []*LiquidityHistory, err error) { - subQuery := m.DB.Table(m.table).Select("*"). - Where("pair_index = a.pair_index AND l2_block_height <= ? AND l2_block_height > a.l2_block_height", blockHeight) - - dbTx := m.DB.Table(m.table+" as a").Select("*"). - Where("NOT EXISTS (?) AND l2_block_height <= ?", subQuery, blockHeight). - Limit(limit).Offset(offset). - Order("pair_index") - - if dbTx.Find(&entities).Error != nil { - return nil, types.DbErrSqlOperation - } else if dbTx.RowsAffected == 0 { - return nil, types.DbErrNotFound - } - return entities, nil -} - -func (m *defaultLiquidityHistoryModel) GetLatestLiquidityCountByBlockHeight(blockHeight int64) (count int64, err error) { - subQuery := m.DB.Table(m.table).Select("*"). - Where("pair_index = a.pair_index AND l2_block_height <= ? AND l2_block_height > a.l2_block_height", blockHeight) - - dbTx := m.DB.Table(m.table+" as a"). - Where("NOT EXISTS (?) AND l2_block_height <= ?", subQuery, blockHeight) - - if dbTx.Count(&count).Error != nil { - return 0, dbTx.Error - } - return count, nil -} - -func (m *defaultLiquidityHistoryModel) CreateLiquidityHistoriesInTransact(tx *gorm.DB, histories []*LiquidityHistory) error { - dbTx := tx.Table(m.table).CreateInBatches(histories, len(histories)) - if dbTx.Error != nil { - return dbTx.Error - } - if dbTx.RowsAffected != int64(len(histories)) { - return types.DbErrFailToCreateLiquidityHistory - } - return nil -} diff --git a/dao/nft/nft.go b/dao/nft/nft.go index e127ac9d4..feb968c58 100644 --- a/dao/nft/nft.go +++ b/dao/nft/nft.go @@ -35,7 +35,6 @@ type ( GetLatestNftIndex() (nftIndex int64, err error) GetNftsByAccountIndex(accountIndex, limit, offset int64) (nfts []*L2Nft, err error) GetNftsCountByAccountIndex(accountIndex int64) (int64, error) - CreateNftsInTransact(tx *gorm.DB, nfts []*L2Nft) error UpdateNftsInTransact(tx *gorm.DB, nfts []*L2Nft) error } defaultL2NftModel struct { @@ -118,17 +117,6 @@ func (m *defaultL2NftModel) GetNftsCountByAccountIndex(accountIndex int64) (int6 return count, nil } -func (m *defaultL2NftModel) CreateNftsInTransact(tx *gorm.DB, nfts []*L2Nft) error { - dbTx := tx.Table(m.table).CreateInBatches(nfts, len(nfts)) - if dbTx.Error != nil { - return dbTx.Error - } - if dbTx.RowsAffected != int64(len(nfts)) { - return types.DbErrFailToCreateNft - } - return nil -} - func (m *defaultL2NftModel) UpdateNftsInTransact(tx *gorm.DB, nfts []*L2Nft) error { for _, pendingNft := range nfts { dbTx := tx.Table(m.table).Where("nft_index = ?", pendingNft.NftIndex). @@ -138,7 +126,10 @@ func (m *defaultL2NftModel) UpdateNftsInTransact(tx *gorm.DB, nfts []*L2Nft) err return dbTx.Error } if dbTx.RowsAffected == 0 { - return types.DbErrFailToUpdateNft + dbTx = tx.Table(m.table).Create(&pendingNft) + if dbTx.Error != nil { + return dbTx.Error + } } } return nil diff --git a/dao/priorityrequest/priority_request.go b/dao/priorityrequest/priority_request.go index 37c1bb7ef..e9b36fd26 100644 --- a/dao/priorityrequest/priority_request.go +++ b/dao/priorityrequest/priority_request.go @@ -38,6 +38,7 @@ type ( GetLatestHandledRequestId() (requestId int64, err error) UpdateHandledPriorityRequestsInTransact(tx *gorm.DB, requests []*PriorityRequest) (err error) CreatePriorityRequestsInTransact(tx *gorm.DB, requests []*PriorityRequest) (err error) + GetPriorityRequestsByL2TxHash(txHash string) (tx *PriorityRequest, err error) } defaultPriorityRequestModel struct { @@ -63,6 +64,8 @@ type ( ExpirationBlock int64 // status Status int + // L2TxHash for the relation to tx table + L2TxHash string `gorm:"index"` } ) @@ -119,16 +122,19 @@ func (m *defaultPriorityRequestModel) GetLatestHandledRequestId() (requestId int } func (m *defaultPriorityRequestModel) UpdateHandledPriorityRequestsInTransact(tx *gorm.DB, requests []*PriorityRequest) (err error) { - ids := make([]uint, 0, len(requests)) for _, request := range requests { - ids = append(ids, request.ID) - } - dbTx := tx.Table(m.table).Where("id in ?", ids).Update("status", HandledStatus) - if dbTx.Error != nil { - return dbTx.Error - } - if dbTx.RowsAffected != int64(len(ids)) { - return types.DbErrFailToUpdatePriorityRequest + dbTx := tx.Table(m.table).Where("id = ?", request.ID).Updates( + map[string]interface{}{ + "status": HandledStatus, + "l2_tx_hash": request.L2TxHash, + }, + ) + if dbTx.Error != nil { + return dbTx.Error + } + if dbTx.RowsAffected != 1 { + return types.DbErrFailToUpdatePriorityRequest + } } return nil } @@ -143,3 +149,15 @@ func (m *defaultPriorityRequestModel) CreatePriorityRequestsInTransact(tx *gorm. } return nil } + +func (m *defaultPriorityRequestModel) GetPriorityRequestsByL2TxHash(txHash string) (tx *PriorityRequest, err error) { + dbTx := m.DB.Table(m.table).Where("l2_tx_hash = ?", txHash).Limit(1).Find(&tx) + if dbTx.Error != nil { + return nil, types.DbErrSqlOperation + } + if dbTx.RowsAffected == 0 { + return nil, types.DbErrNotFound + } + + return tx, nil +} diff --git a/dao/tx/tx.go b/dao/tx/tx.go index f54f663ba..7be1ce3aa 100644 --- a/dao/tx/tx.go +++ b/dao/tx/tx.go @@ -71,7 +71,6 @@ type ( // Assigned after executed. GasFee string GasFeeAssetId int64 - PairIndex int64 NftIndex int64 CollectionId int64 AssetId int64 diff --git a/dao/tx/tx_detail.go b/dao/tx/tx_detail.go index 61562d3ca..04510e134 100644 --- a/dao/tx/tx_detail.go +++ b/dao/tx/tx_detail.go @@ -47,6 +47,7 @@ type ( AccountOrder int64 Nonce int64 CollectionNonce int64 + IsGas bool `gorm:"default:false"` } ) diff --git a/dao/tx/tx_pool.go b/dao/tx/tx_pool.go index 986751911..8d8866a6c 100644 --- a/dao/tx/tx_pool.go +++ b/dao/tx/tx_pool.go @@ -41,6 +41,7 @@ type ( CreateTxsInTransact(tx *gorm.DB, txs []*Tx) error UpdateTxsInTransact(tx *gorm.DB, txs []*Tx) error DeleteTxsInTransact(tx *gorm.DB, txs []*Tx) error + GetLatestTx(txTypes []int64, statuses []int) (tx *Tx, err error) } defaultTxPoolModel struct { @@ -184,3 +185,15 @@ func (m *defaultTxPoolModel) DeleteTxsInTransact(tx *gorm.DB, txs []*Tx) error { } return nil } + +func (m *defaultTxPoolModel) GetLatestTx(txTypes []int64, statuses []int) (tx *Tx, err error) { + + dbTx := m.DB.Table(m.table).Where("tx_status IN ? AND tx_type IN ?", statuses, txTypes).Order("id DESC").Limit(1).Find(&tx) + if dbTx.Error != nil { + return nil, types.DbErrSqlOperation + } else if dbTx.RowsAffected == 0 { + return nil, types.DbErrNotFound + } + + return tx, nil +} diff --git a/deploy-local.sh b/deploy-local.sh index 6573cd0f5..5f091d864 100644 --- a/deploy-local.sh +++ b/deploy-local.sh @@ -11,6 +11,7 @@ DEPLOY_PATH=~/zkbnb-deploy KEY_PATH=~/.zkbnb ZkBNB_REPO_PATH=$(cd `dirname $0`; pwd) CMC_TOKEN=cfce503f-fake-fake-fake-bbab5257dac8 +BSC_TESTNET_PRIVATE_KEY=acbaa26******************************a88367d9 export PATH=$PATH:/usr/local/go/bin:/usr/local/go/bin:/root/go/bin echo '0. stop old database/redis and docker run new database/redis' @@ -59,7 +60,7 @@ echo 'latest block number = ' $blockNumber echo '4-2. deploy contracts, register and deposit on BSC Testnet' cd ${DEPLOY_PATH} -cd ./zkbnb-contract && yarn install +cd ./zkbnb-contract && echo "BSC_TESTNET_PRIVATE_KEY=${BSC_TESTNET_PRIVATE_KEY}" > .env && npm install npx hardhat --network BSCTestnet run ./scripts/deploy-keccak256/deploy.js echo 'Recorded latest contract addresses into ${DEPLOY_PATH}/zkbnb-contract/info/addresses.json' @@ -115,6 +116,7 @@ BlockConfig: TreeDB: Driver: memorydb + AssetTreeCacheSize: 512000 " > ${DEPLOY_PATH}/zkbnb/service/prover/etc/config.yaml echo -e " @@ -140,6 +142,7 @@ CacheRedis: TreeDB: Driver: memorydb + AssetTreeCacheSize: 512000 " > ${DEPLOY_PATH}/zkbnb/service/witness/etc/config.yaml echo -e " @@ -170,6 +173,7 @@ ChainConfig: TreeDB: Driver: memorydb + AssetTreeCacheSize: 512000 " > ${DEPLOY_PATH}/zkbnb/service/monitor/etc/config.yaml echo -e " @@ -195,6 +199,7 @@ BlockConfig: TreeDB: Driver: memorydb + AssetTreeCacheSize: 512000 " > ${DEPLOY_PATH}/zkbnb/service/committer/etc/config.yaml echo -e " @@ -220,12 +225,14 @@ ChainConfig: #NetworkRPCSysConfigName: "LocalTestNetworkRpc" ConfirmBlocksCount: 0 MaxWaitingTime: 120 - MaxBlockCount: 4 - Sk: "acbaa269bd7573ff12361be4b97201aef019776ea13384681d4e5ba6a88367d9" - GasLimit: 5000000 + MaxBlockCount: 3 + Sk: "107f9d2a50ce2d8337e0c5220574e9fcf2bf60002da5acf07718f4d531ea3faa" + GasLimit: 20000000 + GasPrice: 0 TreeDB: Driver: memorydb + AssetTreeCacheSize: 512000 " > ${DEPLOY_PATH}/zkbnb/service/sender/etc/config.yaml echo -e " @@ -273,6 +280,8 @@ MemCache: BlockExpiration: 400 TxExpiration: 400 PriceExpiration: 3600000 + MaxCounterNum: 100000 + MaxKeyNum: 10000 " > ${DEPLOY_PATH}/zkbnb/service/apiserver/etc/config.yaml echo -e " diff --git a/deploy-qa.sh b/deploy-qa.sh index 1ee50f448..7ca06dc6a 100644 --- a/deploy-qa.sh +++ b/deploy-qa.sh @@ -107,6 +107,7 @@ KeyPath: TreeDB: Driver: memorydb + AssetTreeCacheSize: 512000 " > ~/zkbnb-deploy/zkbnb/service/cronjob/prover/etc/prover.yaml cd ~/zkbnb-deploy/zkbnb/service/cronjob/prover/ @@ -129,6 +130,7 @@ CacheRedis: TreeDB: Driver: memorydb + AssetTreeCacheSize: 512000 " > ~/zkbnb-deploy/zkbnb/service/cronjob/witnessGenerator/etc/witnessGenerator.yaml cd ~/zkbnb-deploy/zkbnb/service/cronjob/witnessGenerator/ @@ -162,6 +164,7 @@ ChainConfig: TreeDB: Driver: memorydb + AssetTreeCacheSize: 512000 " > ~/zkbnb-deploy/zkbnb/service/cronjob/monitor/etc/monitor.yaml cd ~/zkbnb-deploy/zkbnb/service/cronjob/monitor/ @@ -186,6 +189,7 @@ KeyPath: TreeDB: Driver: memorydb + AssetTreeCacheSize: 512000 " >> ~/zkbnb-deploy/zkbnb/service/cronjob/committer/etc/committer.yaml cd ~/zkbnb-deploy/zkbnb/service/cronjob/committer/ @@ -214,9 +218,11 @@ ChainConfig: MaxBlockCount: 4 Sk: "acbaa269bd7573ff12361be4b97201aef019776ea13384681d4e5ba6a88367d9" GasLimit: 5000000 + GasPrice: 0 TreeDB: Driver: memorydb + AssetTreeCacheSize: 512000 " > ~/zkbnb-deploy/zkbnb/service/cronjob/sender/etc/sender.yaml cd ~/zkbnb-deploy/zkbnb/service/cronjob/sender/ @@ -247,6 +253,7 @@ LogConf: TreeDB: Driver: memorydb + AssetTreeCacheSize: 512000 " > ~/zkbnb-deploy/zkbnb/service/rpc/globalRPC/etc/config.yaml cd ~/zkbnb-deploy/zkbnb/service/rpc/globalRPC/ @@ -279,6 +286,7 @@ LogConf: TreeDB: Driver: memorydb + AssetTreeCacheSize: 512000 " > ~/zkbnb-deploy/zkbnb/service/api/app/etc/app.yaml cd ~/zkbnb-deploy/zkbnb/service/api/app diff --git a/deployment/docker-compose/docker-compose.sh b/deployment/docker-compose/docker-compose.sh index 98d926092..206050781 100644 --- a/deployment/docker-compose/docker-compose.sh +++ b/deployment/docker-compose/docker-compose.sh @@ -61,6 +61,7 @@ LogConf: TreeDB: Driver: memorydb + AssetTreeCacheSize: 512000 " > ${CONFIG_PATH}/witness.yaml echo -e " @@ -104,6 +105,7 @@ BlockConfig: TreeDB: Driver: memorydb + AssetTreeCacheSize: 512000 " > ${CONFIG_PATH}/committer.yaml echo -e " @@ -173,6 +175,8 @@ MemCache: BlockExpiration: 400 TxExpiration: 400 PriceExpiration: 3600000 + MaxCounterNum: 100000 + MaxKeyNum: 10000 " > ${CONFIG_PATH}/apiserver.yaml @@ -201,4 +205,4 @@ down) *) echo "Usage: docker-compose.sh up \$block_number | down" ;; -esac \ No newline at end of file +esac diff --git a/deployment/helm/local-value/values.yaml b/deployment/helm/local-value/values.yaml index 3180cd180..b3b948391 100644 --- a/deployment/helm/local-value/values.yaml +++ b/deployment/helm/local-value/values.yaml @@ -113,5 +113,7 @@ configs: BlockExpiration: 400 TxExpiration: 400 PriceExpiration: 3600000 + MaxCounterNum: 100000 + MaxKeyNum: 10000 logLevel: error diff --git a/deployment/helm/zkbnb/values.yaml b/deployment/helm/zkbnb/values.yaml index d2fd3d3c7..3e2c9573d 100644 --- a/deployment/helm/zkbnb/values.yaml +++ b/deployment/helm/zkbnb/values.yaml @@ -112,4 +112,6 @@ configs: BlockExpiration: 400 TxExpiration: 400 PriceExpiration: 3600000 + MaxCounterNum: 100000 + MaxKeyNum: 10000 logLevel: info diff --git a/docs/api_reference.md b/docs/api_reference.md index 181155ccf..b89ce7a2b 100644 --- a/docs/api_reference.md +++ b/docs/api_reference.md @@ -303,27 +303,6 @@ Get zkbnb general info, including contract address, and count of transactions an | ---- | ----------- | ------ | | 200 | A successful response. | [Layer2BasicInfo](#layer2basicinfo) | -### /api/v1/lpValue - -#### GET - -##### Summary - -Get liquidity pool amount for a specific liquidity pair - -##### Parameters - -| Name | Located in | Description | Required | Schema | -| ---- | ---------- | ----------- | -------- | ---- | -| pair_index | query | index of pair | Yes | integer | -| lp_amount | query | lp amount | Yes | string | - -##### Responses - -| Code | Description | Schema | -| ---- | ----------- | ------ | -| 200 | A successful response. | [LpValue](#lpvalue) | - ### /api/v1/maxOfferId #### GET @@ -385,40 +364,6 @@ Get next nonce | ---- | ----------- | ------ | | 200 | A successful response. | [NextNonce](#nextnonce) | -### /api/v1/pair - -#### GET - -##### Summary - -Get liquidity pool info by its index - -##### Parameters - -| Name | Located in | Description | Required | Schema | -| ---- | ---------- | ----------- | -------- | ---- | -| index | query | index of pair | Yes | integer | - -##### Responses - -| Code | Description | Schema | -| ---- | ----------- | ------ | -| 200 | A successful response. | [Pair](#pair) | - -### /api/v1/pairs - -#### GET - -##### Summary - -Get liquidity pairs - -##### Responses - -| Code | Description | Schema | -| ---- | ----------- | ------ | -| 200 | A successful response. | [Pairs](#pairs) | - ### /api/v1/search #### GET @@ -439,29 +384,6 @@ Search with a specific keyword | ---- | ----------- | ------ | | 200 | A successful response. | [Search](#search) | -### /api/v1/swapAmount - -#### GET - -##### Summary - -Get swap amount for a specific liquidity pair and in asset amount - -##### Parameters - -| Name | Located in | Description | Required | Schema | -| ---- | ---------- | ----------- | -------- | ---- | -| pair_index | query | index of pair | Yes | integer | -| asset_id | query | id of asset | Yes | integer | -| asset_amount | query | amount of asset | Yes | string | -| is_from | query | is from asset | Yes | boolean (boolean) | - -##### Responses - -| Code | Description | Schema | -| ---- | ----------- | ------ | -| 200 | A successful response. | [SwapAmount](#swapamount) | - ### /api/v1/tx #### GET @@ -527,15 +449,15 @@ Send raw transaction #### Account -| Name | Type | Description | Required | -|--------|-----------------------------------| ----------- | -------- | -| status | integer | | Yes | -| index | long | | Yes | -| name | string | | Yes | -| pk | string | | Yes | -| nonce | long | | Yes | -| assets | [ [AccountAsset](#accountasset) ] | | Yes | -| lps | [ [AccountLp](#accountlp) ] | | Yes | +| Name | Type | Description | Required | +|--------------------|-----------------------------------| ----------- | -------- | +| status | integer | | Yes | +| index | long | | Yes | +| name | string | | Yes | +| pk | string | | Yes | +| nonce | long | | Yes | +| assets | [ [AccountAsset](#accountasset) ] | | Yes | +| total_asset_value | string | | Yes | #### AccountAsset @@ -546,13 +468,6 @@ Send raw transaction | balance | string | | Yes | | price | string | | Yes | -#### AccountLp - -| Name | Type | Description | Required | -|--------| ---- | ----------- | -------- | -| index | integer | | Yes | -| amount | string | | Yes | - #### Accounts | Name | Type | Description | Required | @@ -562,15 +477,16 @@ Send raw transaction #### Asset -| Name | Type | Description | Required | -|--------------| ---- | ----------- | -------- | +| Name | Type | Description | Required | +|--------------|---------| ----------- | -------- | | id | integer | | Yes | -| name | string | | Yes | +| name | string | | Yes | | decimals | integer | | Yes | -| symbol | string | | Yes | -| address | string | | Yes | -| price | string | | Yes | +| symbol | string | | Yes | +| address | string | | Yes | +| price | string | | Yes | | is_gas_asset | integer | | Yes | +| icon | string | | Yes | #### Assets @@ -595,6 +511,7 @@ Send raw transaction | verified_at | long | | Yes | | txs | [ [Tx](#tx) ] | | Yes | | status | long | | Yes | +| size | long | | Yes | #### Blocks @@ -658,19 +575,6 @@ Send raw transaction | today_active_user_count | long | | Yes | | contract_addresses | [ [ContractAddress](#contractaddress) ] | | Yes | -#### LpValue - -| Name | Type | Description | Required | -|----------------| ---- | ----------- | -------- | -| asset_a_id | integer | | Yes | -| asset_a_name | string | | Yes | -| asset_a_amount | string | | Yes | -| asset_a_price | string | | Yes | -| asset_b_id | integer | | Yes | -| asset_b_name | string | | Yes | -| asset_b_amount | string | | Yes | -| asset_b_price | string | | Yes | - #### MaxOfferId | Name | Type | Description | Required | @@ -703,29 +607,6 @@ Send raw transaction | total | long | | Yes | | nfts | [ [Nft](#nft) ] | | Yes | -#### Pair - -| Name | Type | Description | Required | -|-----------------| ---- | ----------- | -------- | -| index | integer | | Yes | -| asset_a_id | integer | | Yes | -| asset_a_name | string | | Yes | -| asset_a_amount | string | | Yes | -| asset_a_price | string | | Yes | -| asset_b_id | integer | | Yes | -| asset_b_name | string | | Yes | -| asset_b_amount | string | | Yes | -| asset_b_price | string | | Yes | -| fee_rate | long | | Yes | -| treasury_rate | long | | Yes | -| total_lp_amount | string | | Yes | - -#### Pairs - -| Name | Type | Description | Required | -| ---- | ---- | ----------- | -------- | -| pairs | [ [Pair](#pair) ] | | Yes | - #### ReqGetAccount | Name | Type | Description | Required | @@ -786,13 +667,6 @@ Send raw transaction | asset_id | integer | | Yes | | tx_type | integer | | Yes | -#### ReqGetLpValue - -| Name | Type | Description | Required | -| ---- | ---- | ----------- | -------- | -| pair_index | integer | | Yes | -| lp_amount | string | | Yes | - #### ReqGetMaxOfferId | Name | Type | Description | Required | @@ -805,12 +679,6 @@ Send raw transaction | ---- | ---- | ----------- | -------- | | account_index | integer | | Yes | -#### ReqGetPair - -| Name | Type | Description | Required | -| ---- | ---- | ----------- | -------- | -| index | integer | | Yes | - #### ReqGetRange | Name | Type | Description | Required | @@ -818,15 +686,6 @@ Send raw transaction | offset | integer | | Yes | | limit | integer | | Yes | -#### ReqGetSwapAmount - -| Name | Type | Description | Required | -| ---- | ---- | ----------- | -------- | -| pair_index | integer | | Yes | -| asset_id | integer | | Yes | -| asset_amount | string | | Yes | -| is_from | boolean (boolean) | | Yes | - #### ReqGetTx | Name | Type | Description | Required | @@ -867,14 +726,6 @@ Send raw transaction | status | integer | | Yes | | network_id | integer | | Yes | -#### SwapAmount - -| Name | Type | Description | Required | -| ---- | ---- | ----------- | -------- | -| asset_id | integer | | Yes | -| asset_name | string | | Yes | -| asset_amount | string | | Yes | - #### Tx | Name | Type | Description | Required | @@ -888,7 +739,6 @@ Send raw transaction | gas_fee_asset_id | long | | Yes | | gas_fee | string | | Yes | | nft_index | long | | Yes | -| pair_index | long | | Yes | | asset_id | long | | Yes | | asset_name | string | | Yes | | native_adress | string | | Yes | diff --git a/docs/assets/storage_layout.png b/docs/assets/storage_layout.png index 6a2b62500..9bafc96ae 100644 Binary files a/docs/assets/storage_layout.png and b/docs/assets/storage_layout.png differ diff --git a/docs/protocol.md b/docs/protocol.md index 19c7ded85..1cc152102 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -22,7 +22,6 @@ switch to EDCSA. ZkBNB implements a ZK rollup protocol (in short "rollup" below) for: - BNB and BEP20 fungible token deposit and transfer -- AMM-based fungible token swap on L2 - BEP721 non-fungible token deposit and transfer - mint BEP721 non-fungible tokens on L2 - NFT-marketplace on L2 @@ -30,7 +29,7 @@ ZkBNB implements a ZK rollup protocol (in short "rollup" below) for: General rollup workflow is as follows: - Users can become owners in rollup by calling registerZNS in L1 to register a short name for L2; -- Owners can transfer assets to each other, mint NFT on L2 or make a swap on L2; +- Owners can transfer assets to each other, mint NFT on L2; - Owners can withdraw assets under their control to any L1 address. Rollup operation requires the assistance of a committer, who rolls transactions together, also a prover who computes @@ -68,7 +67,7 @@ Mantissa and exponent parameters used in ZkBNB: ### State Merkle Tree(height) -We have 3 unique trees: `AccountTree(32)`, `LiquidityTree(16)`, `NftTree(40)` and one sub-tree `AssetTree(16)` which +We have 3 unique trees: `AccountTree(32)`, `NftTree(40)` and one sub-tree `AssetTree(16)` which belongs to `AccountTree(32)`. The empty leaf for all the trees is just set every attribute as `0` for every node. #### AccountTree @@ -115,12 +114,11 @@ func ComputeAccountLeafHash( ##### AssetTree -`AssetTree` is sub-tree of `AccountTree` and it stores all the assets `balance`, `lpAmount` and `offerCanceledOrFinalized`. The node of asset tree is: +`AssetTree` is sub-tree of `AccountTree` and it stores all the assets `balance`, and `offerCanceledOrFinalized`. The node of asset tree is: ```go type AssetNode struct { Balance string - LpAmount string OfferCanceledOrFinalized string // uint128 } ``` @@ -130,7 +128,6 @@ Leaf hash computation: ```go func ComputeAccountAssetLeafHash( balance string, - lpAmount string, offerCanceledOrFinalized string, ) (hashVal []byte, err error) { hFunc := mimc.NewMiMC() @@ -140,11 +137,6 @@ func ComputeAccountAssetLeafHash( logx.Errorf("[ComputeAccountAssetLeafHash] invalid balance: %s", err.Error()) return nil, err } - err = util.PaddingStringBigIntIntoBuf(&buf, lpAmount) - if err != nil { - logx.Errorf("[ComputeAccountAssetLeafHash] invalid balance: %s", err.Error()) - return nil, err - } err = util.PaddingStringBigIntIntoBuf(&buf, offerCanceledOrFinalized) if err != nil { logx.Errorf("[ComputeAccountAssetLeafHash] invalid balance: %s", err.Error()) @@ -155,73 +147,6 @@ func ComputeAccountAssetLeafHash( } ``` -#### LiquidityTree - -`LiquidityTree` is used for storing all the liquidity info and the node of the liquidity tree is: - -```go -type LiquidityNode struct { - AssetAId int64 - AssetA string - AssetBId int64 - AssetB string - LpAmount string - KLast string - FeeRate int64 - TreasuryAccountIndex int64 - TreasuryRate int64 -} -``` - -The liquidity pair is first initialized by `CreatePair` tx and will be changed by `UpdatePairRate`, `Swap`, `AddLiquidity` and `RemoveLiquidity` txs. - -Leaf hash computation: - -```go -func ComputeLiquidityAssetLeafHash( - assetAId int64, - assetA string, - assetBId int64, - assetB string, - lpAmount string, - kLast string, - feeRate int64, - treasuryAccountIndex int64, - treasuryRate int64, -) (hashVal []byte, err error) { - hFunc := mimc.NewMiMC() - var buf bytes.Buffer - util.PaddingInt64IntoBuf(&buf, assetAId) - err = util.PaddingStringBigIntIntoBuf(&buf, assetA) - if err != nil { - logx.Errorf("[ComputeLiquidityAssetLeafHash] unable to write big int to buf: %s", err.Error()) - return nil, err - } - util.PaddingInt64IntoBuf(&buf, assetBId) - err = util.PaddingStringBigIntIntoBuf(&buf, assetB) - if err != nil { - logx.Errorf("[ComputeLiquidityAssetLeafHash] unable to write big int to buf: %s", err.Error()) - return nil, err - } - err = util.PaddingStringBigIntIntoBuf(&buf, lpAmount) - if err != nil { - logx.Errorf("[ComputeLiquidityAssetLeafHash] unable to write big int to buf: %s", err.Error()) - return nil, err - } - err = util.PaddingStringBigIntIntoBuf(&buf, kLast) - if err != nil { - logx.Errorf("[ComputeLiquidityAssetLeafHash] unable to write big int to buf: %s", err.Error()) - return nil, err - } - util.PaddingInt64IntoBuf(&buf, feeRate) - util.PaddingInt64IntoBuf(&buf, treasuryAccountIndex) - util.PaddingInt64IntoBuf(&buf, treasuryRate) - hFunc.Write(buf.Bytes()) - hashVal = hFunc.Sum(nil) - return hashVal, nil -} -``` - #### NftTree `NftTree` is used for storing all the NFTs and the node info is: @@ -275,19 +200,17 @@ func ComputeNftAssetLeafHash( #### StateRoot -`StateRoot` is the final root that shows the final layer-2 state and will be stored on L1. It is computed by the root of `AccountTree`, `LiquidityTree` and `NftTree`. The computation of `StateRoot` works as follows: +`StateRoot` is the final root that shows the final layer-2 state and will be stored on L1. It is computed by the root of `AccountTree` and `NftTree`. The computation of `StateRoot` works as follows: -`StateRoot = MiMC(AccountRoot || LiquidityRoot || NftRoot)` +`StateRoot = MiMC(AccountRoot || NftRoot)` ```go func ComputeStateRootHash( accountRoot []byte, - liquidityRoot []byte, nftRoot []byte, ) []byte { hFunc := mimc.NewMiMC() hFunc.Write(accountRoot) - hFunc.Write(liquidityRoot) hFunc.Write(nftRoot) return hFunc.Sum(nil) } @@ -301,9 +224,6 @@ Rollup transactions: - EmptyTx - Transfer -- Swap -- AddLiquidity -- RemoveLiquidity - Withdraw - CreateCollection - MintNft @@ -315,8 +235,6 @@ Rollup transactions: Priority operations: - RegisterZNS -- CreatePair -- UpdatePairRate - Deposit - DepositNft - FullExit @@ -435,167 +353,6 @@ func VerifyRegisterZNSTx( } ``` -### CreatePair - -#### Description - -This is a layer-1 transaction and is used for creating a trading pair for L2. - -#### On-Chain operation - -##### Size - -| Chunks | Significant bytes | -| ------ | ----------------- | -| 6 | 15 | - -##### Structure - -| Name | Size(byte) | Comment | -| -------------------- | ---------- | ----------------------------- | -| TxType | 1 | transaction type | -| PairIndex | 2 | unique pair index | -| AssetAId | 2 | unique asset index | -| AssetBId | 2 | unique asset index | -| FeeRate | 2 | fee rate | -| TreasuryAccountIndex | 4 | unique treasury account index | -| TreasuryRate | 2 | treasury rate | - -```go -func ConvertTxToCreatePairPubData(oTx *tx.Tx) (pubData []byte, err error) { - if oTx.TxType != commonTx.TxTypeCreatePair { - logx.Errorf("[ConvertTxToCreatePairPubData] invalid tx type") - return nil, errors.New("[ConvertTxToCreatePairPubData] invalid tx type") - } - // parse tx - txInfo, err := commonTx.ParseCreatePairTxInfo(oTx.TxInfo) - if err != nil { - logx.Errorf("[ConvertTxToCreatePairPubData] unable to parse tx info: %s", err.Error()) - return nil, err - } - var buf bytes.Buffer - buf.WriteByte(uint8(oTx.TxType)) - buf.Write(Uint16ToBytes(uint16(txInfo.PairIndex))) - buf.Write(Uint16ToBytes(uint16(txInfo.AssetAId))) - buf.Write(Uint16ToBytes(uint16(txInfo.AssetBId))) - buf.Write(Uint16ToBytes(uint16(txInfo.FeeRate))) - buf.Write(Uint32ToBytes(uint32(txInfo.TreasuryAccountIndex))) - buf.Write(Uint16ToBytes(uint16(txInfo.TreasuryRate))) - chunk := SuffixPaddingBufToChunkSize(buf.Bytes()) - buf.Reset() - buf.Write(chunk) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - return buf.Bytes(), nil -} -``` - -#### User transaction - -| Name | Size(byte) | Comment | -| ------------- | ---------- | ----------------------- | -| AssetAAddress | 20 | asset a layer-1 address | -| AssetBAddress | 20 | asset b layer-1 address | - -#### Circuit - -```go -func VerifyCreatePairTx( - api API, flag Variable, - tx CreatePairTxConstraints, - liquidityBefore LiquidityConstraints, -) (pubData [PubDataSizePerTx]Variable) { - pubData = CollectPubDataFromCreatePair(api, tx) - // verify params - IsVariableEqual(api, flag, tx.PairIndex, liquidityBefore.PairIndex) - CheckEmptyLiquidityNode(api, flag, liquidityBefore) - return pubData -} -``` - -### UpdatePairRate - -#### Description - -This is a layer-1 transaction and is used for updating a trading pair for L2. - -#### On-Chain operation - -##### Size - -| Chunks | Significant bytes | -| ------ | ----------------- | -| 6 | 11 | - -##### Structure - -| Name | Size(byte) | Comment | -| -------------------- | ---------- | ----------------------------- | -| TxType | 1 | transaction type | -| PairIndex | 2 | unique pair index | -| FeeRate | 2 | fee rate | -| TreasuryAccountIndex | 4 | unique treasury account index | -| TreasuryRate | 2 | treasury rate | - -```go -func ConvertTxToUpdatePairRatePubData(oTx *tx.Tx) (pubData []byte, err error) { - if oTx.TxType != commonTx.TxTypeUpdatePairRate { - logx.Errorf("[ConvertTxToUpdatePairRatePubData] invalid tx type") - return nil, errors.New("[ConvertTxToUpdatePairRatePubData] invalid tx type") - } - // parse tx - txInfo, err := commonTx.ParseUpdatePairRateTxInfo(oTx.TxInfo) - if err != nil { - logx.Errorf("[ConvertTxToUpdatePairRatePubData] unable to parse tx info: %s", err.Error()) - return nil, err - } - var buf bytes.Buffer - buf.WriteByte(uint8(oTx.TxType)) - buf.Write(Uint16ToBytes(uint16(txInfo.PairIndex))) - buf.Write(Uint16ToBytes(uint16(txInfo.FeeRate))) - buf.Write(Uint32ToBytes(uint32(txInfo.TreasuryAccountIndex))) - buf.Write(Uint16ToBytes(uint16(txInfo.TreasuryRate))) - chunk := SuffixPaddingBufToChunkSize(buf.Bytes()) - buf.Reset() - buf.Write(chunk) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - return buf.Bytes(), nil -} -``` - -#### User transaction - -| Name | Size(byte) | Comment | -| -------------------- | ---------- | ----------------------- | -| AssetAAddress | 20 | asset a layer-1 address | -| AssetBAddress | 20 | asset b layer-1 address | -| FeeRate | 2 | fee rate | -| TreasuryAccountIndex | 4 | treasury account index | -| TreasuryRate | 2 | treasury rate | - -#### Circuit - -```go -func VerifyUpdatePairRateTx( - api API, flag Variable, - tx UpdatePairRateTxConstraints, - liquidityBefore LiquidityConstraints, -) (pubData [PubDataSizePerTx]Variable) { - pubData = CollectPubDataFromUpdatePairRate(api, tx) - // verify params - IsVariableEqual(api, flag, tx.PairIndex, liquidityBefore.PairIndex) - IsVariableLessOrEqual(api, flag, tx.TreasuryRate, tx.FeeRate) - return pubData -} -``` - ### Deposit #### Description @@ -901,519 +658,6 @@ func VerifyTransferTx( } ``` -### Swap - -#### Description - -This is a layer-2 transaction and is used for making a swap for assets in the layer-2 network. - -#### On-Chain operation - -##### Size - -| Chunks | Significant bytes | -| ------ | ----------------- | -| 6 | 25 | - -##### Structure - -| Name | Size(byte) | Comment | -| ------------------ | ---------- | --------------------- | -| TxType | 1 | transaction type | -| FromAccountIndex | 4 | from account index | -| PairIndex | 2 | unique pair index | -| AssetAAmount | 5 | packed asset amount | -| AssetBAmount | 5 | packed asset amount | -| GasFeeAccountIndex | 4 | gas fee account index | -| GasFeeAssetId | 2 | gas fee asset id | -| GasFeeAssetAmount | 2 | packed fee amount | - -```go -func ConvertTxToSwapPubData(oTx *tx.Tx) (pubData []byte, err error) { - if oTx.TxType != commonTx.TxTypeSwap { - logx.Errorf("[ConvertTxToSwapPubData] invalid tx type") - return nil, errors.New("[ConvertTxToSwapPubData] invalid tx type") - } - // parse tx - txInfo, err := commonTx.ParseSwapTxInfo(oTx.TxInfo) - if err != nil { - logx.Errorf("[ConvertTxToSwapPubData] unable to parse tx info: %s", err.Error()) - return nil, err - } - var buf bytes.Buffer - buf.WriteByte(uint8(oTx.TxType)) - buf.Write(Uint32ToBytes(uint32(txInfo.FromAccountIndex))) - buf.Write(Uint16ToBytes(uint16(txInfo.PairIndex))) - packedAssetAAmountBytes, err := AmountToPackedAmountBytes(txInfo.AssetAAmount) - if err != nil { - logx.Errorf("[ConvertTxToDepositPubData] unable to convert amount to packed amount: %s", err.Error()) - return nil, err - } - buf.Write(packedAssetAAmountBytes) - packedAssetBAmountDeltaBytes, err := AmountToPackedAmountBytes(txInfo.AssetBAmountDelta) - if err != nil { - logx.Errorf("[ConvertTxToDepositPubData] unable to convert amount to packed amount: %s", err.Error()) - return nil, err - } - buf.Write(packedAssetBAmountDeltaBytes) - buf.Write(Uint32ToBytes(uint32(txInfo.GasAccountIndex))) - buf.Write(Uint16ToBytes(uint16(txInfo.GasFeeAssetId))) - packedFeeBytes, err := FeeToPackedFeeBytes(txInfo.GasFeeAssetAmount) - if err != nil { - logx.Errorf("[ConvertTxToDepositPubData] unable to convert amount to packed fee amount: %s", err.Error()) - return nil, err - } - buf.Write(packedFeeBytes) - chunk := SuffixPaddingBufToChunkSize(buf.Bytes()) - buf.Reset() - buf.Write(chunk) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - return buf.Bytes(), nil -} -``` - -#### User transaction - -```go -type SwapTxInfo struct { - FromAccountIndex int64 - PairIndex int64 - AssetAId int64 - AssetAAmount *big.Int - AssetBId int64 - AssetBMinAmount *big.Int - AssetBAmountDelta *big.Int - GasAccountIndex int64 - GasFeeAssetId int64 - GasFeeAssetAmount *big.Int - ExpiredAt int64 - Nonce int64 - Sig []byte -} -``` - -#### Circuit - -```go -func VerifySwapTx( - api API, flag Variable, - tx *SwapTxConstraints, - accountsBefore [NbAccountsPerTx]AccountConstraints, liquidityBefore LiquidityConstraints, -) (pubData [PubDataSizePerTx]Variable) { - pubData = CollectPubDataFromSwap(api, *tx) - // verify params - // account index - IsVariableEqual(api, flag, tx.FromAccountIndex, accountsBefore[0].AccountIndex) - IsVariableEqual(api, flag, tx.GasAccountIndex, accountsBefore[1].AccountIndex) - // pair index - IsVariableEqual(api, flag, tx.PairIndex, liquidityBefore.PairIndex) - // asset id - IsVariableEqual(api, flag, tx.AssetAId, accountsBefore[0].AssetsInfo[0].AssetId) - IsVariableEqual(api, flag, tx.AssetBId, accountsBefore[0].AssetsInfo[1].AssetId) - isSameAsset := api.IsZero( - api.And( - api.IsZero(api.Sub(tx.AssetAId, liquidityBefore.AssetAId)), - api.IsZero(api.Sub(tx.AssetBId, liquidityBefore.AssetBId)), - ), - ) - isDifferentAsset := api.IsZero( - api.And( - api.IsZero(api.Sub(tx.AssetAId, liquidityBefore.AssetBId)), - api.IsZero(api.Sub(tx.AssetBId, liquidityBefore.AssetAId)), - ), - ) - IsVariableEqual( - api, flag, - api.Or( - isSameAsset, - isDifferentAsset, - ), - 1, - ) - IsVariableEqual(api, flag, tx.GasFeeAssetId, accountsBefore[0].AssetsInfo[2].AssetId) - IsVariableEqual(api, flag, tx.GasFeeAssetId, accountsBefore[1].AssetsInfo[0].AssetId) - // should have enough assets - tx.AssetAAmount = UnpackAmount(api, tx.AssetAAmount) - tx.AssetBMinAmount = UnpackAmount(api, tx.AssetBMinAmount) - tx.AssetBAmountDelta = UnpackAmount(api, tx.AssetBAmountDelta) - tx.GasFeeAssetAmount = UnpackFee(api, tx.GasFeeAssetAmount) - IsVariableLessOrEqual(api, flag, tx.AssetBMinAmount, tx.AssetBAmountDelta) - IsVariableLessOrEqual(api, flag, tx.AssetAAmount, accountsBefore[0].AssetsInfo[0].Balance) - IsVariableLessOrEqual(api, flag, tx.GasFeeAssetAmount, accountsBefore[0].AssetsInfo[2].Balance) - // pool info - isSameAsset = api.And(flag, isSameAsset) - isDifferentAsset = api.And(flag, isSameAsset) - IsVariableEqual(api, flag, liquidityBefore.FeeRate, liquidityBefore.FeeRate) - IsVariableLessOrEqual(api, flag, liquidityBefore.FeeRate, RateBase) - assetAAmount := api.Select(isSameAsset, tx.AssetAAmount, tx.AssetBAmountDelta) - assetBAmount := api.Select(isSameAsset, tx.AssetBAmountDelta, tx.AssetAAmount) - // verify AMM - r := api.Mul(api.Mul(liquidityBefore.AssetA, liquidityBefore.AssetB), RateBase) - l := api.Mul( - api.Sub( - api.Mul(RateBase, api.Add(assetAAmount, liquidityBefore.AssetA)), - api.Mul(liquidityBefore.FeeRate, assetAAmount), - ), - api.Add(assetBAmount, liquidityBefore.AssetB), - ) - IsVariableLessOrEqual(api, flag, r, l) - return pubData -} -``` - -### AddLiquidity - -#### Description - -This is a layer-2 transaction and is used for adding liquidity for a trading pair in the layer-2 network. - -#### On-Chain operation - -##### Size - -| Chunks | Significant bytes | -| ------ | ----------------- | -| 6 | 40 | - -##### Structure - -| Name | Size(byte) | Comment | -| ------------------ | ---------- | ---------------------- | -| TxType | 1 | transaction type | -| FromAccountIndex | 4 | from account index | -| PairIndex | 2 | unique pair index | -| AssetAAmount | 5 | packed asset amount | -| AssetBAmount | 5 | packed asset amount | -| LpAmount | 5 | packed asset amount | -| KLast | 5 | packed k last amount | -| TreasuryAmount | 5 | packed treasury amount | -| GasFeeAccountIndex | 4 | gas fee account index | -| GasFeeAssetId | 2 | gas fee asset id | -| GasFeeAssetAmount | 2 | packed fee amount | - -```go -func ConvertTxToAddLiquidityPubData(oTx *tx.Tx) (pubData []byte, err error) { - if oTx.TxType != commonTx.TxTypeAddLiquidity { - logx.Errorf("[ConvertTxToAddLiquidityPubData] invalid tx type") - return nil, errors.New("[ConvertTxToAddLiquidityPubData] invalid tx type") - } - // parse tx - txInfo, err := commonTx.ParseAddLiquidityTxInfo(oTx.TxInfo) - if err != nil { - logx.Errorf("[ConvertTxToAddLiquidityPubData] unable to parse tx info: %s", err.Error()) - return nil, err - } - var buf bytes.Buffer - buf.WriteByte(uint8(oTx.TxType)) - buf.Write(Uint32ToBytes(uint32(txInfo.FromAccountIndex))) - buf.Write(Uint16ToBytes(uint16(txInfo.PairIndex))) - packedAssetAAmountBytes, err := AmountToPackedAmountBytes(txInfo.AssetAAmount) - if err != nil { - logx.Errorf("[ConvertTxToDepositPubData] unable to convert amount to packed amount: %s", err.Error()) - return nil, err - } - buf.Write(packedAssetAAmountBytes) - packedAssetBAmountBytes, err := AmountToPackedAmountBytes(txInfo.AssetBAmount) - if err != nil { - logx.Errorf("[ConvertTxToDepositPubData] unable to convert amount to packed amount: %s", err.Error()) - return nil, err - } - buf.Write(packedAssetBAmountBytes) - LpAmountBytes, err := AmountToPackedAmountBytes(txInfo.LpAmount) - if err != nil { - logx.Errorf("[ConvertTxToDepositPubData] unable to convert amount to packed amount: %s", err.Error()) - return nil, err - } - buf.Write(LpAmountBytes) - KLastBytes, err := AmountToPackedAmountBytes(txInfo.KLast) - if err != nil { - logx.Errorf("[ConvertTxToDepositPubData] unable to convert amount to packed amount: %s", err.Error()) - return nil, err - } - buf.Write(KLastBytes) - chunk1 := SuffixPaddingBufToChunkSize(buf.Bytes()) - buf.Reset() - treasuryAmountBytes, err := AmountToPackedAmountBytes(txInfo.TreasuryAmount) - if err != nil { - logx.Errorf("[ConvertTxToDepositPubData] unable to convert amount to packed amount: %s", err.Error()) - return nil, err - } - buf.Write(treasuryAmountBytes) - buf.Write(Uint32ToBytes(uint32(txInfo.GasAccountIndex))) - buf.Write(Uint16ToBytes(uint16(txInfo.GasFeeAssetId))) - packedFeeBytes, err := FeeToPackedFeeBytes(txInfo.GasFeeAssetAmount) - if err != nil { - logx.Errorf("[ConvertTxToDepositPubData] unable to convert amount to packed fee amount: %s", err.Error()) - return nil, err - } - buf.Write(packedFeeBytes) - chunk2 := PrefixPaddingBufToChunkSize(buf.Bytes()) - buf.Reset() - buf.Write(chunk1) - buf.Write(chunk2) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - return buf.Bytes(), nil -} -``` - -#### User transaction - -```go -type AddLiquidityTxInfo struct { - FromAccountIndex int64 - PairIndex int64 - AssetAId int64 - AssetAAmount *big.Int - AssetBId int64 - AssetBAmount *big.Int - LpAmount *big.Int - KLast *big.Int - TreasuryAmount *big.Int - GasAccountIndex int64 - GasFeeAssetId int64 - GasFeeAssetAmount *big.Int - ExpiredAt int64 - Nonce int64 - Sig []byte -} -``` - -#### Circuit - -```go -func VerifyAddLiquidityTx( - api API, flag Variable, - tx *AddLiquidityTxConstraints, - accountsBefore [NbAccountsPerTx]AccountConstraints, liquidityBefore LiquidityConstraints, - hFunc *MiMC, -) { - CollectPubDataFromAddLiquidity(api, flag, *tx, hFunc) - // check params - // account index - IsVariableEqual(api, flag, tx.FromAccountIndex, accountsBefore[0].AccountIndex) - IsVariableEqual(api, flag, liquidityBefore.TreasuryAccountIndex, accountsBefore[1].AccountIndex) - IsVariableEqual(api, flag, tx.GasAccountIndex, accountsBefore[2].AccountIndex) - // asset id - IsVariableEqual(api, flag, tx.AssetAId, accountsBefore[0].AssetsInfo[0].AssetId) - IsVariableEqual(api, flag, tx.AssetBId, accountsBefore[0].AssetsInfo[1].AssetId) - IsVariableEqual(api, flag, tx.AssetAId, liquidityBefore.AssetAId) - IsVariableEqual(api, flag, tx.AssetBId, liquidityBefore.AssetBId) - IsVariableEqual(api, flag, tx.PairIndex, accountsBefore[1].AssetsInfo[0].AssetId) - IsVariableEqual(api, flag, tx.GasFeeAssetId, accountsBefore[0].AssetsInfo[2].AssetId) - IsVariableEqual(api, flag, tx.GasFeeAssetId, accountsBefore[2].AssetsInfo[0].AssetId) - IsVariableLessOrEqual(api, flag, 0, tx.AssetAAmount) - IsVariableLessOrEqual(api, flag, 0, tx.AssetBAmount) - // check if the user has enough balance - tx.AssetAAmount = UnpackAmount(api, tx.AssetAAmount) - tx.AssetBAmount = UnpackAmount(api, tx.AssetBAmount) - tx.LpAmount = UnpackAmount(api, tx.LpAmount) - tx.GasFeeAssetAmount = UnpackFee(api, tx.GasFeeAssetAmount) - IsVariableLessOrEqual(api, flag, tx.AssetAAmount, accountsBefore[0].AssetsInfo[0].Balance) - IsVariableLessOrEqual(api, flag, tx.AssetBAmount, accountsBefore[0].AssetsInfo[1].Balance) - IsVariableLessOrEqual(api, flag, tx.GasFeeAssetAmount, accountsBefore[0].AssetsInfo[2].Balance) - IsVariableEqual(api, flag, tx.PoolAAmount, liquidityBefore.AssetA) - IsVariableEqual(api, flag, tx.PoolBAmount, liquidityBefore.AssetB) - // TODO verify ratio - l := api.Mul(liquidityBefore.AssetA, tx.AssetAAmount) - r := api.Mul(liquidityBefore.AssetB, tx.AssetBAmount) - maxDelta := std.Max(api, liquidityBefore.AssetA, liquidityBefore.AssetB) - l = std.Max(api, l, r) - r = std.Min(api, l, r) - lrDelta := api.Sub(l, r) - IsVariableLessOrEqual(api, flag, lrDelta, maxDelta) - // TODO verify lp amount - zeroFlag := api.Compiler().IsBoolean(api.Add(liquidityBefore.AssetA, 1)) - if zeroFlag { - // lpAmount = \sqrt{x * y} - lpAmountSquare := api.Mul(tx.AssetAAmount, tx.AssetBAmount) - IsVariableEqual(api, flag, api.Mul(tx.LpAmount, tx.LpAmount), lpAmountSquare) - } else { - // lpAmount = \Delta{x} / x * poolLp - IsVariableEqual(api, flag, api.Mul(tx.LpAmount, liquidityBefore.AssetA), api.Mul(tx.AssetAAmount, liquidityBefore.LpAmount)) - } -} -``` - -### RemoveLiquidity - -#### Description - -This is a layer-2 transaction and is used for removing liquidity for a trading pair in the layer-2 network. - -#### On-Chain operation - -##### Size - -| Chunks | Significant bytes | -| ------ | ----------------- | -| 6 | 40 | - -##### Structure - -| Name | Size(byte) | Comment | -| ------------------ | ---------- | ---------------------- | -| TxType | 1 | transaction type | -| FromAccountIndex | 4 | from account index | -| PairIndex | 2 | unique pair index | -| AssetAAmount | 5 | packed asset amount | -| AssetBAmount | 5 | packed asset amount | -| LpAmount | 5 | packed asset amount | -| KLast | 5 | packed k last amount | -| TreasuryAmount | 5 | packed treasury amount | -| GasFeeAccountIndex | 4 | gas fee account index | -| GasFeeAssetId | 2 | gas fee asset id | -| GasFeeAssetAmount | 2 | packed fee amount | - -```go -func ConvertTxToRemoveLiquidityPubData(oTx *tx.Tx) (pubData []byte, err error) { - if oTx.TxType != commonTx.TxTypeRemoveLiquidity { - logx.Errorf("[ConvertTxToRemoveLiquidityPubData] invalid tx type") - return nil, errors.New("[ConvertTxToRemoveLiquidityPubData] invalid tx type") - } - // parse tx - txInfo, err := commonTx.ParseRemoveLiquidityTxInfo(oTx.TxInfo) - if err != nil { - logx.Errorf("[ConvertTxToRemoveLiquidityPubData] unable to parse tx info: %s", err.Error()) - return nil, err - } - var buf bytes.Buffer - buf.WriteByte(uint8(oTx.TxType)) - buf.Write(Uint32ToBytes(uint32(txInfo.FromAccountIndex))) - buf.Write(Uint16ToBytes(uint16(txInfo.PairIndex))) - packedAssetAAmountBytes, err := AmountToPackedAmountBytes(txInfo.AssetAAmountDelta) - if err != nil { - logx.Errorf("[ConvertTxToDepositPubData] unable to convert amount to packed amount: %s", err.Error()) - return nil, err - } - buf.Write(packedAssetAAmountBytes) - packedAssetBAmountBytes, err := AmountToPackedAmountBytes(txInfo.AssetBAmountDelta) - if err != nil { - logx.Errorf("[ConvertTxToDepositPubData] unable to convert amount to packed amount: %s", err.Error()) - return nil, err - } - buf.Write(packedAssetBAmountBytes) - LpAmountBytes, err := AmountToPackedAmountBytes(txInfo.LpAmount) - if err != nil { - logx.Errorf("[ConvertTxToDepositPubData] unable to convert amount to packed amount: %s", err.Error()) - return nil, err - } - buf.Write(LpAmountBytes) - KLastBytes, err := AmountToPackedAmountBytes(txInfo.KLast) - if err != nil { - logx.Errorf("[ConvertTxToDepositPubData] unable to convert amount to packed amount: %s", err.Error()) - return nil, err - } - buf.Write(KLastBytes) - chunk1 := SuffixPaddingBufToChunkSize(buf.Bytes()) - buf.Reset() - treasuryAmountBytes, err := AmountToPackedAmountBytes(txInfo.TreasuryAmount) - if err != nil { - logx.Errorf("[ConvertTxToDepositPubData] unable to convert amount to packed amount: %s", err.Error()) - return nil, err - } - buf.Write(treasuryAmountBytes) - buf.Write(Uint32ToBytes(uint32(txInfo.GasAccountIndex))) - buf.Write(Uint16ToBytes(uint16(txInfo.GasFeeAssetId))) - packedFeeBytes, err := FeeToPackedFeeBytes(txInfo.GasFeeAssetAmount) - if err != nil { - logx.Errorf("[ConvertTxToDepositPubData] unable to convert amount to packed fee amount: %s", err.Error()) - return nil, err - } - buf.Write(packedFeeBytes) - chunk2 := PrefixPaddingBufToChunkSize(buf.Bytes()) - buf.Reset() - buf.Write(chunk1) - buf.Write(chunk2) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - buf.Write(PrefixPaddingBufToChunkSize([]byte{})) - return buf.Bytes(), nil -} -``` - -#### User transaction - -```go -type RemoveLiquidityTxInfo struct { - FromAccountIndex int64 - PairIndex int64 - AssetAId int64 - AssetAMinAmount *big.Int - AssetBId int64 - AssetBMinAmount *big.Int - LpAmount *big.Int - AssetAAmountDelta *big.Int - AssetBAmountDelta *big.Int - KLast *big.Int - TreasuryAmount *big.Int - GasAccountIndex int64 - GasFeeAssetId int64 - GasFeeAssetAmount *big.Int - ExpiredAt int64 - Nonce int64 - Sig []byte -} -``` - -#### Circuit - -```go -func VerifyRemoveLiquidityTx( - api API, flag Variable, - tx *RemoveLiquidityTxConstraints, - accountsBefore [NbAccountsPerTx]AccountConstraints, liquidityBefore LiquidityConstraints, -) (pubData [PubDataSizePerTx]Variable, err error) { - pubData = CollectPubDataFromRemoveLiquidity(api, *tx) - // verify params - // account index - IsVariableEqual(api, flag, tx.FromAccountIndex, accountsBefore[0].AccountIndex) - IsVariableEqual(api, flag, liquidityBefore.TreasuryAccountIndex, accountsBefore[1].AccountIndex) - IsVariableEqual(api, flag, tx.GasAccountIndex, accountsBefore[2].AccountIndex) - // asset id - IsVariableEqual(api, flag, tx.AssetAId, accountsBefore[0].AssetsInfo[0].AssetId) - IsVariableEqual(api, flag, tx.AssetBId, accountsBefore[0].AssetsInfo[1].AssetId) - IsVariableEqual(api, flag, tx.GasFeeAssetId, accountsBefore[0].AssetsInfo[2].AssetId) - IsVariableEqual(api, flag, tx.GasFeeAssetId, accountsBefore[2].AssetsInfo[0].AssetId) - IsVariableEqual(api, flag, tx.AssetAId, liquidityBefore.AssetAId) - IsVariableEqual(api, flag, tx.AssetBId, liquidityBefore.AssetBId) - // should have enough lp - IsVariableLessOrEqual(api, flag, tx.LpAmount, accountsBefore[0].AssetsInfo[3].LpAmount) - // enough balance - tx.AssetAMinAmount = UnpackAmount(api, tx.AssetAMinAmount) - tx.AssetAAmountDelta = UnpackAmount(api, tx.AssetAAmountDelta) - tx.AssetBMinAmount = UnpackAmount(api, tx.AssetBMinAmount) - tx.AssetBAmountDelta = UnpackAmount(api, tx.AssetBAmountDelta) - tx.LpAmount = UnpackAmount(api, tx.LpAmount) - tx.TreasuryAmount = UnpackAmount(api, tx.TreasuryAmount) - tx.GasFeeAssetAmount = UnpackFee(api, tx.GasFeeAssetAmount) - IsVariableLessOrEqual(api, flag, tx.GasFeeAssetAmount, accountsBefore[0].AssetsInfo[3].Balance) - // TODO verify LP - kCurrent := api.Mul(liquidityBefore.AssetA, liquidityBefore.AssetB) - IsVariableLessOrEqual(api, flag, liquidityBefore.KLast, kCurrent) - IsVariableLessOrEqual(api, flag, liquidityBefore.TreasuryRate, liquidityBefore.FeeRate) - sLps, err := api.Compiler().NewHint(ComputeSLp, 1, liquidityBefore.AssetA, liquidityBefore.AssetB, liquidityBefore.KLast, liquidityBefore.FeeRate, liquidityBefore.TreasuryRate) - if err != nil { - return pubData, err - } - sLp := sLps[0] - IsVariableEqual(api, flag, tx.TreasuryAmount, sLp) - poolLpVar := api.Sub(liquidityBefore.LpAmount, sLp) - IsVariableLessOrEqual(api, flag, api.Mul(tx.AssetAAmountDelta, poolLpVar), api.Mul(tx.LpAmount, liquidityBefore.AssetA)) - IsVariableLessOrEqual(api, flag, api.Mul(tx.AssetBAmountDelta, poolLpVar), api.Mul(tx.LpAmount, liquidityBefore.AssetB)) - IsVariableLessOrEqual(api, flag, tx.AssetAMinAmount, tx.AssetAAmountDelta) - IsVariableLessOrEqual(api, flag, tx.AssetBMinAmount, tx.AssetBAmountDelta) - return pubData, nil -} -``` - ### Withdraw #### Description @@ -2528,39 +1772,6 @@ function registerZNS(string calldata _name, address _owner, bytes32 _zkbnbPubKey - `_zkbnbPubKeyX`: ZkBNB layer-2 public key X - `_zkbnbPubKeyY`: ZkBNB layer-2 public key Y -#### CreatePair - -Create a trading pair for layer-2. - -```js -function createPair(address _tokenA, address _tokenB) external -``` - -- `_tokenA`: asset A address -- `_tokenB`: asset B address - -#### UpdatePairRate - -update a trading pair rate for layer-2: - -```js -struct PairInfo { - address tokenA; - address tokenB; - uint16 feeRate; - uint32 treasuryAccountIndex; - uint16 treasuryRate; -} - -function updatePairRate(PairInfo memory _pairInfo) external -``` - -- `_assetAAddr`: asset A address -- `_assetBAddr`: asset B address -- `_feeRate`: fee rate -- `_treasuryAccountIndex`: the treasury account index in the layer-2 network -- `_treasuryRate`: treasury rate - #### Deposit BNB Deposit BNB to Rollup - transfer BNB from user L1 address into Rollup account diff --git a/docs/readme.md b/docs/readme.md index 0fa5c6720..c792249ab 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -24,8 +24,6 @@ ZkBNB implement the following features so far: cryptographic. Users do not have to trust any third parties or keep monitoring the Rollup blocks in order to prevent fraud. - **L1<>L2 Communication**. BNB, and BEP20/BEP721/BEP1155 created on BSC or ZkBNB can flow freely between BSC and ZkBNB. -- **Built-in instant AMM swap**. It allows digital assets to be traded without permission and automatically by using - liquidity pools. - **Built-in NFT marketplace**. Developer can build marketplace for crypto collectibles and non-fungible tokens (NFTs) out of box on ZkBNB. - **Fast transaction speed and faster finality**. diff --git a/docs/storage_layout.md b/docs/storage_layout.md index 1800425ea..ce97cf5ba 100644 --- a/docs/storage_layout.md +++ b/docs/storage_layout.md @@ -10,8 +10,6 @@ - `L1 Synced Block`: record block information from L1 - `Compressed Block`: record other information of L2 block - `Block`: record L2 block information - - `Liquidity`: record Liquidity related information - - `Liquidity History`: record the historical change information of Liquidity - `Pool Tx`: record pending and executed but not packed Tx messages - `L2 NFT`: record NFT related information - `L2 NFT History`: record the historical status change information of NFT @@ -27,7 +25,6 @@ There are 4 types of trees in the system. - Account Tree - Account Asset Tree - - Liquidity Tree - Nft Tree ## Account Tree @@ -37,10 +34,6 @@ Used to record and save account status under each block height. ## Account Asset Tree Each Account will maintain an Asset tree, the `Balance`, `LpAmount`, and `OfferCanceledOrFinalized` of each Asset will be calculated as a hash and written into the tree corresponding to the `AssetID`. -## Liquidity Tree -The `AssetAId`, `AssetA`, `AssetBId`, `AssetB`, `LpAmount`, `KLast`, `FeeRate`, `TreasuryAccountIndex`, and `TreasuryRate` of each liquidity resource will be calculated as a hash and written into the tree corresponding to the `PairIndex`. -Used to record and save liquidity status under each block height. - ## Nft Tree The `CreatorAccountIndex`, `OwnerAccountIndex`, `NftContentHash`, `NftL1Address`, `NftL1TokenId`, `CreatorTreasuryRate`, and `CollectionId` of each nft resource will be calculated as a hash and written into the tree corresponding to the `NftIndex`. Used to record and save nft status under each block height. diff --git a/docs/technology.md b/docs/technology.md index 0d1bfe286..5f4bbb891 100644 --- a/docs/technology.md +++ b/docs/technology.md @@ -8,7 +8,7 @@ - **prover**. Prover generates cryptographic proof based on the witness materials. - **sender**. The sender rollups the compressed l2 blocks to L1, and submit proof to verify it. - **api server**. The api server is the access endpoints for most users, it provides rich data, including - digital assets, blocks, transactions, swap info, gas fees. + digital assets, blocks, transactions, gas fees. - **recovery**. A tool to recover the sparse merkle tree in kv-rocks based on the state world in postgresql. ## Maximum throughput diff --git a/docs/tree/recovery.md b/docs/tree/recovery.md index a3f323d42..5644b7a4a 100644 --- a/docs/tree/recovery.md +++ b/docs/tree/recovery.md @@ -17,6 +17,7 @@ CacheRedis: TreeDB: Driver: leveldb + AssetTreeCacheSize: 512000 LevelDBOption: File: /tmp/test ``` diff --git a/docs/wallets.md b/docs/wallets.md index 8f0227a05..58d55f11f 100644 --- a/docs/wallets.md +++ b/docs/wallets.md @@ -180,52 +180,6 @@ Below is the typescript definition of transaction and EIP712Domain. These typed { name: 'Nonce', type: 'uint256' }, { name: 'ChainId', type: 'uint256' }, ], -``` -##### AddLiquidity -```typescript= - AddLiquidity: [ - { name: 'FromAccountIndex', type: 'uint256' }, - { name: 'PairIndex', type: 'uint256' }, - { name: 'AssetAAmount', type: 'uint256' }, - { name: 'AssetBAmount', type: 'uint256' }, - { name: 'GasAccountIndex', type: 'uint256' }, - { name: 'GasFeeAssetId', type: 'uint256' }, - { name: 'GasFeeAssetAmount', type: 'uint256' }, - { name: 'ExpiredAt', type: 'uint256' }, - { name: 'Nonce', type: 'uint256' }, - { name: 'ChainId', type: 'uint256' }, - ], -``` -##### RemoveLiquidity -```typescript= - RemoveLiquidity: [ - { name: 'FromAccountIndex', type: 'uint256' }, - { name: 'PairIndex', type: 'uint256' }, - { name: 'AssetAMinAmount', type: 'uint256' }, - { name: 'AssetBMinAmount', type: 'uint256' }, - { name: 'LpAmount', type: 'uint256' }, - { name: 'GasAccountIndex', type: 'uint256' }, - { name: 'GasFeeAssetId', type: 'uint256' }, - { name: 'GasFeeAssetAmount', type: 'uint256' }, - { name: 'ExpiredAt', type: 'uint256' }, - { name: 'Nonce', type: 'uint256' }, - { name: 'ChainId', type: 'uint256' }, - ], -``` -##### Swap -```typescript= - Swap: [ - { name: 'FromAccountIndex', type: 'uint256' }, - { name: 'PairIndex', type: 'uint256' }, - { name: 'AssetAAmount', type: 'uint256' }, - { name: 'AssetBMinAmount', type: 'uint256' }, - { name: 'GasAccountIndex', type: 'uint256' }, - { name: 'GasFeeAssetId', type: 'uint256' }, - { name: 'GasFeeAssetAmount', type: 'uint256' }, - { name: 'ExpiredAt', type: 'uint256' }, - { name: 'Nonce', type: 'uint256' }, - { name: 'ChainId', type: 'uint256' }, - ], ``` ##### CreateCollection ```typescript= diff --git a/go.mod b/go.mod index e2acd993b..a199bc164 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,10 @@ module github.com/bnb-chain/zkbnb go 1.17 require ( + github.com/dgraph-io/ristretto v0.1.0 github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/panjf2000/ants/v2 v2.5.0 + github.com/prometheus/client_golang v1.12.2 github.com/zeromicro/go-zero v1.3.4 gorm.io/gorm v1.23.4 ) @@ -21,6 +23,7 @@ require ( github.com/deckarep/golang-set v1.8.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/dustin/go-humanize v1.0.0 // indirect github.com/fatih/color v1.13.0 // indirect github.com/fxamacker/cbor/v2 v2.2.0 // indirect github.com/go-logr/logr v1.2.3 // indirect @@ -29,6 +32,7 @@ require ( github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/go-stack/stack v1.8.0 // indirect github.com/golang-jwt/jwt/v4 v4.4.1 // indirect + github.com/golang/glog v1.0.0 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/gorilla/websocket v1.4.2 // indirect @@ -52,7 +56,6 @@ require ( github.com/pegasus-kv/thrift v0.13.0 // indirect github.com/pelletier/go-toml/v2 v2.0.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.12.2 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.33.0 // indirect github.com/prometheus/procfs v0.7.3 // indirect @@ -87,16 +90,15 @@ require ( ) require ( - github.com/bnb-chain/zkbnb-crypto v0.0.6 + github.com/bnb-chain/zkbnb-crypto v0.0.7 github.com/bnb-chain/zkbnb-eth-rpc v0.0.2 - github.com/bnb-chain/zkbnb-smt v0.0.2-0.20220907130044-9c7cccbd19fa + github.com/bnb-chain/zkbnb-smt v0.0.2-0.20220919093003-13980385d38f github.com/consensys/gnark v0.7.0 github.com/consensys/gnark-crypto v0.7.0 github.com/eko/gocache/v2 v2.3.1 github.com/ethereum/go-ethereum v1.10.23 github.com/go-redis/redis/v8 v8.11.5 github.com/google/uuid v1.3.0 // indirect - github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.9.1 github.com/robfig/cron/v3 v3.0.1 github.com/stretchr/testify v1.7.2 @@ -104,7 +106,7 @@ require ( github.com/yusufpapurcu/wmi v1.2.2 // indirect golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect - golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 // indirect + golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875 // indirect google.golang.org/grpc v1.46.2 // indirect google.golang.org/protobuf v1.28.0 // indirect gorm.io/driver/postgres v1.3.6 diff --git a/go.sum b/go.sum index 5f22c67ab..b1f536444 100644 --- a/go.sum +++ b/go.sum @@ -117,12 +117,12 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= -github.com/bnb-chain/zkbnb-crypto v0.0.6 h1:UbD9XzTNQXfcEfI35MHbMMZ5IgqQFidYtvamAbHfS3o= -github.com/bnb-chain/zkbnb-crypto v0.0.6/go.mod h1:SrKwMMrqi1Bxco6IYGXmqo7PvKVn3T3TuMMc7jD4LOA= +github.com/bnb-chain/zkbnb-crypto v0.0.7 h1:IckShzkNdx/ee461Gd0kMC04phus8fcRdIeuzSz1PDE= +github.com/bnb-chain/zkbnb-crypto v0.0.7/go.mod h1:L1BEYSG945hwjJCtR5LUQ1pvRmydSsk9oU2d9YvoOrA= github.com/bnb-chain/zkbnb-eth-rpc v0.0.2 h1:1rMa8XpplDNZaxeM1ifXMjSSeH/ucJyLUjHHEw1z4AA= github.com/bnb-chain/zkbnb-eth-rpc v0.0.2/go.mod h1:T69T8enicQ5kSRPIzyPJv/jhuvRMz1UxsijPXmlis+I= -github.com/bnb-chain/zkbnb-smt v0.0.2-0.20220907130044-9c7cccbd19fa h1:aVqkz6Ge3eW7SKmINYMprpxq2VNpKp4vKQ6dEue8uUE= -github.com/bnb-chain/zkbnb-smt v0.0.2-0.20220907130044-9c7cccbd19fa/go.mod h1:mGIAve72dt/VOVQ2wu7UjcjnMspnKczi5QACE1NGVec= +github.com/bnb-chain/zkbnb-smt v0.0.2-0.20220919093003-13980385d38f h1:zBVWOWlH4w18O6wp0gZML4U2n1rxsFLb7KB7DFE8zcQ= +github.com/bnb-chain/zkbnb-smt v0.0.2-0.20220919093003-13980385d38f/go.mod h1:mGIAve72dt/VOVQ2wu7UjcjnMspnKczi5QACE1NGVec= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d h1:pVrfxiGfwelyab6n21ZBkbkmbevaf+WvMIiR7sr97hw= github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= @@ -197,6 +197,7 @@ github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/Lu github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= @@ -1197,8 +1198,10 @@ golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 h1:h+EGohizhe9XlX18rfpa8k8RAc5XyaeamM+0VHRd4lc= golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220927170352-d9d178bc13c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875 h1:AzgQNqF+FKwyQ5LbVrVqOcuuFB67N47F9+htZYH0wFM= +golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/service/apiserver/etc/server-api.yaml.example b/service/apiserver/etc/server-api.yaml.example index 0dc2a4eee..5686bb1ee 100644 --- a/service/apiserver/etc/server-api.yaml.example +++ b/service/apiserver/etc/server-api.yaml.example @@ -35,3 +35,5 @@ MemCache: BlockExpiration: 400 TxExpiration: 400 PriceExpiration: 3600000 + MaxCounterNum: 100000 + MaxKeyNum: 10000 diff --git a/service/apiserver/internal/cache/mem_cache.go b/service/apiserver/internal/cache/mem_cache.go index e8b780641..c5eb67d4f 100644 --- a/service/apiserver/internal/cache/mem_cache.go +++ b/service/apiserver/internal/cache/mem_cache.go @@ -4,7 +4,7 @@ import ( "fmt" "time" - gocache "github.com/patrickmn/go-cache" + "github.com/dgraph-io/ristretto" accdao "github.com/bnb-chain/zkbnb/dao/account" assetdao "github.com/bnb-chain/zkbnb/dao/asset" @@ -14,8 +14,7 @@ import ( ) const ( - cacheDefaultExpiration = time.Hour * 1 //gocache default expiration - cacheDefaultPurgeInterval = time.Minute * 5 // gocache purge interval + cacheDefaultExpiration = time.Hour * 1 //gocache default expiration AccountIndexNameKeyPrefix = "in:" //key for cache: accountIndex -> accountName AccountIndexPkKeyPrefix = "ip:" //key for cache: accountIndex -> accountPk @@ -40,7 +39,7 @@ const ( type fallback func() (interface{}, error) type MemCache struct { - goCache *gocache.Cache + goCache *ristretto.Cache accountModel accdao.AccountModel assetModel assetdao.AssetModel accountExpiration time.Duration @@ -50,11 +49,26 @@ type MemCache struct { priceExpiration time.Duration } -func NewMemCache(accountModel accdao.AccountModel, assetModel assetdao.AssetModel, +func MustNewMemCache(accountModel accdao.AccountModel, assetModel assetdao.AssetModel, accountExpiration, blockExpiration, txExpiration, - assetExpiration, priceExpiration int) *MemCache { + assetExpiration, priceExpiration int, maxCounterNum, maxKeyNum int64) *MemCache { + + cache, err := ristretto.NewCache(&ristretto.Config{ + NumCounters: maxCounterNum, + MaxCost: maxKeyNum, + BufferItems: 64, // official recommended value + + // Called when setting cost to 0 in `Set/SetWithTTL` + Cost: func(value interface{}) int64 { + return 1 + }, + }) + if err != nil { + panic("MemCache init failed") + } + memCache := &MemCache{ - goCache: gocache.New(cacheDefaultExpiration, cacheDefaultPurgeInterval), + goCache: cache, accountModel: accountModel, assetModel: assetModel, accountExpiration: time.Duration(accountExpiration) * time.Millisecond, @@ -75,15 +89,15 @@ func (m *MemCache) getWithSet(key string, duration time.Duration, f fallback) (i if err != nil { return nil, err } - m.goCache.Set(key, result, duration) + m.goCache.SetWithTTL(key, result, 0, duration) return result, nil } func (m *MemCache) setAccount(accountIndex int64, accountName, accountPk string) { - m.goCache.Set(fmt.Sprintf("%s%d", AccountIndexNameKeyPrefix, accountIndex), accountName, gocache.DefaultExpiration) - m.goCache.Set(fmt.Sprintf("%s%d", AccountIndexPkKeyPrefix, accountIndex), accountPk, gocache.DefaultExpiration) - m.goCache.Set(fmt.Sprintf("%s%s", AccountNameKeyPrefix, accountName), accountIndex, gocache.DefaultExpiration) - m.goCache.Set(fmt.Sprintf("%s%s", AccountPkKeyPrefix, accountPk), accountIndex, gocache.DefaultExpiration) + m.goCache.SetWithTTL(fmt.Sprintf("%s%d", AccountIndexNameKeyPrefix, accountIndex), accountName, 0, cacheDefaultExpiration) + m.goCache.SetWithTTL(fmt.Sprintf("%s%d", AccountIndexPkKeyPrefix, accountIndex), accountPk, 0, cacheDefaultExpiration) + m.goCache.SetWithTTL(fmt.Sprintf("%s%s", AccountNameKeyPrefix, accountName), accountIndex, 0, cacheDefaultExpiration) + m.goCache.SetWithTTL(fmt.Sprintf("%s%s", AccountPkKeyPrefix, accountPk), accountIndex, 0, cacheDefaultExpiration) } func (m *MemCache) GetAccountIndexByName(accountName string) (int64, error) { @@ -167,7 +181,7 @@ func (m *MemCache) GetBlockByHeightWithFallback(blockHeight int64, f fallback) ( block := b.(*blockdao.Block) key = fmt.Sprintf("%s%s", BlockByCommitmentKeyPrefix, block.BlockCommitment) - m.goCache.Set(key, block, m.blockExpiration) + m.goCache.SetWithTTL(key, block, 0, m.blockExpiration) return block, nil } @@ -180,7 +194,7 @@ func (m *MemCache) GetBlockByCommitmentWithFallback(blockCommitment string, f fa block := b.(*blockdao.Block) key = fmt.Sprintf("%s%d", BlockByHeightKeyPrefix, block.BlockHeight) - m.goCache.Set(key, block, m.blockExpiration) + m.goCache.SetWithTTL(key, block, 0, m.blockExpiration) return block, nil } @@ -226,10 +240,10 @@ func (m *MemCache) GetAssetByIdWithFallback(assetId int64, f fallback) (*assetda asset := a.(*assetdao.Asset) key = fmt.Sprintf("%s%s", AssetBySymbolKeyPrefix, asset.AssetSymbol) - m.goCache.Set(key, asset, m.assetExpiration) + m.goCache.SetWithTTL(key, asset, 0, m.assetExpiration) key = fmt.Sprintf("%s%d", AssetIdNameKeyPrefix, assetId) - m.goCache.Set(key, asset.AssetName, gocache.DefaultExpiration) + m.goCache.SetWithTTL(key, asset.AssetName, 0, cacheDefaultExpiration) return asset, nil } @@ -242,10 +256,10 @@ func (m *MemCache) GetAssetBySymbolWithFallback(assetSymbol string, f fallback) asset := a.(*assetdao.Asset) key = fmt.Sprintf("%s%d", AssetByIdKeyPrefix, asset.AssetId) - m.goCache.Set(key, asset, m.assetExpiration) + m.goCache.SetWithTTL(key, asset, 0, m.assetExpiration) key = fmt.Sprintf("%s%d", AssetIdNameKeyPrefix, asset.AssetId) - m.goCache.Set(key, asset.AssetName, gocache.DefaultExpiration) + m.goCache.SetWithTTL(key, asset.AssetName, 0, cacheDefaultExpiration) return asset, nil } @@ -260,9 +274,9 @@ func (m *MemCache) GetAssetNameById(assetId int64) (string, error) { return "", err } - m.goCache.Set(keyForName, asset.AssetName, gocache.DefaultExpiration) + m.goCache.SetWithTTL(keyForName, asset.AssetName, 0, cacheDefaultExpiration) keyForSymbol := fmt.Sprintf("%s%d", AssetIdSymbolKeyPrefix, assetId) - m.goCache.Set(keyForSymbol, asset.AssetSymbol, gocache.DefaultExpiration) + m.goCache.SetWithTTL(keyForSymbol, asset.AssetSymbol, 0, cacheDefaultExpiration) return asset.AssetName, nil } @@ -278,9 +292,9 @@ func (m *MemCache) GetAssetSymbolById(assetId int64) (string, error) { return "", err } - m.goCache.Set(keyForSymbol, asset.AssetSymbol, gocache.DefaultExpiration) + m.goCache.SetWithTTL(keyForSymbol, asset.AssetSymbol, 0, cacheDefaultExpiration) keyForName := fmt.Sprintf("%s%d", AssetIdNameKeyPrefix, assetId) - m.goCache.Set(keyForName, asset.AssetName, gocache.DefaultExpiration) + m.goCache.SetWithTTL(keyForName, asset.AssetName, 0, cacheDefaultExpiration) return asset.AssetSymbol, nil } @@ -296,12 +310,12 @@ func (m *MemCache) GetPriceWithFallback(symbol string, f fallback) (float64, err func (m *MemCache) SetPrice(symbol string, price float64) { key := fmt.Sprintf("%s%s", PriceKeyPrefix, symbol) - m.goCache.Set(key, price, m.priceExpiration) + m.goCache.SetWithTTL(key, price, int64(len(key)), m.priceExpiration) } func (m *MemCache) GetSysConfigWithFallback(configName string, f fallback) (*sysconfig.SysConfig, error) { key := fmt.Sprintf("%s%s", SysConfigKeyPrefix, configName) - c, err := m.getWithSet(key, gocache.DefaultExpiration, f) + c, err := m.getWithSet(key, cacheDefaultExpiration, f) if err != nil { return nil, err } diff --git a/service/apiserver/internal/config/config.go b/service/apiserver/internal/config/config.go index 0a835870d..bcc6315ba 100644 --- a/service/apiserver/internal/config/config.go +++ b/service/apiserver/internal/config/config.go @@ -26,5 +26,9 @@ type Config struct { BlockExpiration int TxExpiration int PriceExpiration int + // Number of 4-bit access counters to keep for admission and eviction + // Setting this to 10x the number of items you expect to keep in the cache when full + MaxCounterNum int64 + MaxKeyNum int64 } } diff --git a/service/apiserver/internal/fetcher/state/fetcher.go b/service/apiserver/internal/fetcher/state/fetcher.go index bf12aa45b..e5860c32e 100644 --- a/service/apiserver/internal/fetcher/state/fetcher.go +++ b/service/apiserver/internal/fetcher/state/fetcher.go @@ -6,38 +6,33 @@ import ( "github.com/bnb-chain/zkbnb/common/chain" accdao "github.com/bnb-chain/zkbnb/dao/account" "github.com/bnb-chain/zkbnb/dao/dbcache" - liqdao "github.com/bnb-chain/zkbnb/dao/liquidity" nftdao "github.com/bnb-chain/zkbnb/dao/nft" "github.com/bnb-chain/zkbnb/types" ) //go:generate mockgen -source api.go -destination api_mock.go -package state -// Fetcher will fetch the latest states (account,nft,liquidity) from redis, which is written by committer; +// Fetcher will fetch the latest states (account,nft) from redis, which is written by committer; // and if the required data cannot be found then database will be used. type Fetcher interface { GetLatestAccount(accountIndex int64) (accountInfo *types.AccountInfo, err error) - GetLatestLiquidity(pairIndex int64) (liquidityInfo *types.LiquidityInfo, err error) GetLatestNft(nftIndex int64) (*types.NftInfo, error) } func NewFetcher(redisCache dbcache.Cache, accountModel accdao.AccountModel, - liquidityModel liqdao.LiquidityModel, nftModel nftdao.L2NftModel) Fetcher { return &fetcher{ - redisCache: redisCache, - accountModel: accountModel, - liquidityModel: liquidityModel, - nftModel: nftModel, + redisCache: redisCache, + accountModel: accountModel, + nftModel: nftModel, } } type fetcher struct { - redisCache dbcache.Cache - accountModel accdao.AccountModel - liquidityModel liqdao.LiquidityModel - nftModel nftdao.L2NftModel + redisCache dbcache.Cache + accountModel accdao.AccountModel + nftModel nftdao.L2NftModel } func (f *fetcher) GetLatestAccount(accountIndex int64) (*types.AccountInfo, error) { @@ -63,32 +58,6 @@ func (f *fetcher) GetLatestAccount(accountIndex int64) (*types.AccountInfo, erro return fa, nil } -func (f *fetcher) GetLatestLiquidity(pairIndex int64) (liquidityInfo *types.LiquidityInfo, err error) { - l := &liqdao.Liquidity{} - - redisLiquidity, err := f.redisCache.Get(context.Background(), dbcache.LiquidityKeyByIndex(pairIndex), l) - if err == nil && redisLiquidity != "" { - } else { - l, err = f.liquidityModel.GetLiquidityByIndex(pairIndex) - if err != nil { - return nil, err - } - } - - return types.ConstructLiquidityInfo( - pairIndex, - l.AssetAId, - l.AssetA, - l.AssetBId, - l.AssetB, - l.LpAmount, - l.KLast, - l.FeeRate, - l.TreasuryAccountIndex, - l.TreasuryRate, - ) -} - func (f *fetcher) GetLatestNft(nftIndex int64) (*types.NftInfo, error) { n := &nftdao.L2Nft{} diff --git a/service/apiserver/internal/handler/pair/getlpvaluehandler.go b/service/apiserver/internal/handler/pair/getlpvaluehandler.go deleted file mode 100644 index dee9be1cd..000000000 --- a/service/apiserver/internal/handler/pair/getlpvaluehandler.go +++ /dev/null @@ -1,29 +0,0 @@ -package pair - -import ( - "net/http" - - "github.com/zeromicro/go-zero/rest/httpx" - - "github.com/bnb-chain/zkbnb/service/apiserver/internal/logic/pair" - "github.com/bnb-chain/zkbnb/service/apiserver/internal/svc" - "github.com/bnb-chain/zkbnb/service/apiserver/internal/types" -) - -func GetLpValueHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - var req types.ReqGetLpValue - if err := httpx.Parse(r, &req); err != nil { - httpx.Error(w, err) - return - } - - l := pair.NewGetLpValueLogic(r.Context(), svcCtx) - resp, err := l.GetLPValue(&req) - if err != nil { - httpx.Error(w, err) - } else { - httpx.OkJson(w, resp) - } - } -} diff --git a/service/apiserver/internal/handler/pair/getpairhandler.go b/service/apiserver/internal/handler/pair/getpairhandler.go deleted file mode 100644 index 260654145..000000000 --- a/service/apiserver/internal/handler/pair/getpairhandler.go +++ /dev/null @@ -1,29 +0,0 @@ -package pair - -import ( - "net/http" - - "github.com/zeromicro/go-zero/rest/httpx" - - "github.com/bnb-chain/zkbnb/service/apiserver/internal/logic/pair" - "github.com/bnb-chain/zkbnb/service/apiserver/internal/svc" - "github.com/bnb-chain/zkbnb/service/apiserver/internal/types" -) - -func GetPairHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - var req types.ReqGetPair - if err := httpx.Parse(r, &req); err != nil { - httpx.Error(w, err) - return - } - - l := pair.NewGetPairLogic(r.Context(), svcCtx) - resp, err := l.GetPair(&req) - if err != nil { - httpx.Error(w, err) - } else { - httpx.OkJson(w, resp) - } - } -} diff --git a/service/apiserver/internal/handler/pair/getpairshandler.go b/service/apiserver/internal/handler/pair/getpairshandler.go deleted file mode 100644 index d158ce98b..000000000 --- a/service/apiserver/internal/handler/pair/getpairshandler.go +++ /dev/null @@ -1,22 +0,0 @@ -package pair - -import ( - "net/http" - - "github.com/zeromicro/go-zero/rest/httpx" - - "github.com/bnb-chain/zkbnb/service/apiserver/internal/logic/pair" - "github.com/bnb-chain/zkbnb/service/apiserver/internal/svc" -) - -func GetPairsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - l := pair.NewGetPairsLogic(r.Context(), svcCtx) - resp, err := l.GetPairs() - if err != nil { - httpx.Error(w, err) - } else { - httpx.OkJson(w, resp) - } - } -} diff --git a/service/apiserver/internal/handler/pair/getswapamounthandler.go b/service/apiserver/internal/handler/pair/getswapamounthandler.go deleted file mode 100644 index cab782d9a..000000000 --- a/service/apiserver/internal/handler/pair/getswapamounthandler.go +++ /dev/null @@ -1,29 +0,0 @@ -package pair - -import ( - "net/http" - - "github.com/zeromicro/go-zero/rest/httpx" - - "github.com/bnb-chain/zkbnb/service/apiserver/internal/logic/pair" - "github.com/bnb-chain/zkbnb/service/apiserver/internal/svc" - "github.com/bnb-chain/zkbnb/service/apiserver/internal/types" -) - -func GetSwapAmountHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - var req types.ReqGetSwapAmount - if err := httpx.Parse(r, &req); err != nil { - httpx.Error(w, err) - return - } - - l := pair.NewGetSwapAmountLogic(r.Context(), svcCtx) - resp, err := l.GetSwapAmount(&req) - if err != nil { - httpx.Error(w, err) - } else { - httpx.OkJson(w, resp) - } - } -} diff --git a/service/apiserver/internal/handler/routes.go b/service/apiserver/internal/handler/routes.go index 64bc7050f..393256772 100644 --- a/service/apiserver/internal/handler/routes.go +++ b/service/apiserver/internal/handler/routes.go @@ -9,7 +9,6 @@ import ( block "github.com/bnb-chain/zkbnb/service/apiserver/internal/handler/block" info "github.com/bnb-chain/zkbnb/service/apiserver/internal/handler/info" nft "github.com/bnb-chain/zkbnb/service/apiserver/internal/handler/nft" - pair "github.com/bnb-chain/zkbnb/service/apiserver/internal/handler/pair" root "github.com/bnb-chain/zkbnb/service/apiserver/internal/handler/root" transaction "github.com/bnb-chain/zkbnb/service/apiserver/internal/handler/transaction" "github.com/bnb-chain/zkbnb/service/apiserver/internal/svc" @@ -108,31 +107,6 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { }, ) - server.AddRoutes( - []rest.Route{ - { - Method: http.MethodGet, - Path: "/api/v1/swapAmount", - Handler: pair.GetSwapAmountHandler(serverCtx), - }, - { - Method: http.MethodGet, - Path: "/api/v1/pairs", - Handler: pair.GetPairsHandler(serverCtx), - }, - { - Method: http.MethodGet, - Path: "/api/v1/lpValue", - Handler: pair.GetLpValueHandler(serverCtx), - }, - { - Method: http.MethodGet, - Path: "/api/v1/pair", - Handler: pair.GetPairHandler(serverCtx), - }, - }, - ) - server.AddRoutes( []rest.Route{ { diff --git a/service/apiserver/internal/logic/account/getaccountlogic.go b/service/apiserver/internal/logic/account/getaccountlogic.go index 7b373b7d4..f953042d5 100644 --- a/service/apiserver/internal/logic/account/getaccountlogic.go +++ b/service/apiserver/internal/logic/account/getaccountlogic.go @@ -2,6 +2,7 @@ package account import ( "context" + "math/big" "sort" "strconv" @@ -75,27 +76,31 @@ func (l *GetAccountLogic) GetAccount(req *types.ReqGetAccount) (resp *types.Acco Pk: account.PublicKey, Nonce: account.Nonce, Assets: make([]*types.AccountAsset, 0, len(account.AssetInfo)), - Lps: make([]*types.AccountLp, 0, len(account.AssetInfo)), } + + totalAssetValue := big.NewFloat(0) + for _, asset := range account.AssetInfo { if asset.AssetId > maxAssetId { continue //it is used for offer related, or empty balance; max ip id should be less than max asset id } - if (asset.Balance == nil || asset.Balance.Cmp(types2.ZeroBigInt) == 0) && - (asset.LpAmount == nil || asset.LpAmount.Cmp(types2.ZeroBigInt) == 0) { + if asset.Balance == nil || asset.Balance.Cmp(types2.ZeroBigInt) == 0 { continue } if asset.Balance != nil && asset.Balance.Cmp(types2.ZeroBigInt) > 0 { var assetName, assetSymbol string var assetPrice float64 - assetName, err = l.svcCtx.MemCache.GetAssetNameById(asset.AssetId) - if err != nil { - return nil, types2.AppErrInternal - } - assetSymbol, err = l.svcCtx.MemCache.GetAssetSymbolById(asset.AssetId) + + assetInfo, err := l.svcCtx.MemCache.GetAssetByIdWithFallback(asset.AssetId, func() (interface{}, error) { + + return l.svcCtx.AssetModel.GetAssetById(asset.AssetId) + }) if err != nil { return nil, types2.AppErrInternal } + assetName = assetInfo.AssetName + assetSymbol = assetInfo.AssetSymbol + assetPrice, err = l.svcCtx.PriceFetcher.GetCurrencyPrice(l.ctx, assetSymbol) if err != nil { return nil, types2.AppErrInternal @@ -106,15 +111,23 @@ func (l *GetAccountLogic) GetAccount(req *types.ReqGetAccount) (resp *types.Acco Balance: asset.Balance.String(), Price: strconv.FormatFloat(assetPrice, 'E', -1, 64), }) - } - if asset.LpAmount != nil && asset.LpAmount.Cmp(types2.ZeroBigInt) > 0 { - resp.Lps = append(resp.Lps, &types.AccountLp{ - Index: uint32(asset.AssetId), - Amount: asset.LpAmount.String(), - }) + + // BNB for example: + // 1. Convert unit of balance from wei to BNB + // 2. Calculate the result of (BNB balance * price per BNB) + balanceInFloat := new(big.Float).SetInt(asset.Balance) + unitConversion := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(assetInfo.Decimals)), nil) + assetValue := balanceInFloat.Mul( + new(big.Float).Quo(balanceInFloat, new(big.Float).SetInt(unitConversion)), + big.NewFloat(assetPrice), + ) + + totalAssetValue = totalAssetValue.Add(totalAssetValue, assetValue) } } + resp.TotalAssetValue = totalAssetValue.Text('f', -1) + sort.Slice(resp.Assets, func(i, j int) bool { return resp.Assets[i].Id < resp.Assets[j].Id }) diff --git a/service/apiserver/internal/logic/asset/getassetlogic.go b/service/apiserver/internal/logic/asset/getassetlogic.go index d788f7bca..b903860d3 100644 --- a/service/apiserver/internal/logic/asset/getassetlogic.go +++ b/service/apiserver/internal/logic/asset/getassetlogic.go @@ -2,6 +2,7 @@ package asset import ( "context" + "fmt" "strconv" "strings" @@ -15,6 +16,9 @@ import ( const ( queryById = "id" queryBySymbol = "symbol" + + // iconBaseUrl is used for showing icons for assets, asset owners should upload png files to the github repo + iconBaseUrl = "https://raw.githubusercontent.com/binance-chain/tokens-info/master/tokens/%s/%s.png" ) type GetAssetLogic struct { @@ -74,6 +78,7 @@ func (l *GetAssetLogic) GetAsset(req *types.ReqGetAsset) (resp *types.Asset, err Address: asset.L1Address, Price: strconv.FormatFloat(assetPrice, 'E', -1, 64), IsGasAsset: asset.IsGasAsset, + Icon: fmt.Sprintf(iconBaseUrl, strings.ToLower(asset.AssetSymbol), strings.ToLower(asset.AssetSymbol)), } return resp, nil } diff --git a/service/apiserver/internal/logic/asset/getassetslogic.go b/service/apiserver/internal/logic/asset/getassetslogic.go index 7a284ae0f..461f13b75 100644 --- a/service/apiserver/internal/logic/asset/getassetslogic.go +++ b/service/apiserver/internal/logic/asset/getassetslogic.go @@ -2,7 +2,9 @@ package asset import ( "context" + "fmt" "strconv" + "strings" "github.com/zeromicro/go-zero/core/logx" @@ -60,6 +62,7 @@ func (l *GetAssetsLogic) GetAssets(req *types.ReqGetRange) (resp *types.Assets, Address: asset.L1Address, Price: strconv.FormatFloat(assetPrice, 'E', -1, 64), IsGasAsset: asset.IsGasAsset, + Icon: fmt.Sprintf(iconBaseUrl, strings.ToLower(asset.AssetSymbol), strings.ToLower(asset.AssetSymbol)), }) } return resp, nil diff --git a/service/apiserver/internal/logic/block/getblocklogic.go b/service/apiserver/internal/logic/block/getblocklogic.go index 1fae671a9..8b53238f8 100644 --- a/service/apiserver/internal/logic/block/getblocklogic.go +++ b/service/apiserver/internal/logic/block/getblocklogic.go @@ -71,6 +71,7 @@ func (l *GetBlockLogic) GetBlock(req *types.ReqGetBlock) (resp *types.Block, err VerifiedTxHash: block.VerifiedTxHash, VerifiedAt: block.VerifiedAt, Status: block.BlockStatus, + Size: block.BlockSize, } for _, dbTx := range block.Txs { tx := utils.ConvertTx(dbTx) diff --git a/service/apiserver/internal/logic/block/getblockslogic.go b/service/apiserver/internal/logic/block/getblockslogic.go index 801aa6aa4..0315806b5 100644 --- a/service/apiserver/internal/logic/block/getblockslogic.go +++ b/service/apiserver/internal/logic/block/getblockslogic.go @@ -62,6 +62,7 @@ func (l *GetBlocksLogic) GetBlocks(req *types.ReqGetRange) (*types.Blocks, error VerifiedTxHash: b.VerifiedTxHash, VerifiedAt: b.VerifiedAt, Status: b.BlockStatus, + Size: b.BlockSize, } for _, dbTx := range b.Txs { tx := utils.ConvertTx(dbTx) diff --git a/service/apiserver/internal/logic/pair/getlpvaluelogic.go b/service/apiserver/internal/logic/pair/getlpvaluelogic.go deleted file mode 100644 index 8586e41c1..000000000 --- a/service/apiserver/internal/logic/pair/getlpvaluelogic.go +++ /dev/null @@ -1,80 +0,0 @@ -package pair - -import ( - "context" - "math/big" - "strconv" - - "github.com/zeromicro/go-zero/core/logx" - - "github.com/bnb-chain/zkbnb/common/chain" - "github.com/bnb-chain/zkbnb/service/apiserver/internal/svc" - "github.com/bnb-chain/zkbnb/service/apiserver/internal/types" - types2 "github.com/bnb-chain/zkbnb/types" -) - -type GetLpValueLogic struct { - logx.Logger - ctx context.Context - svcCtx *svc.ServiceContext -} - -func NewGetLpValueLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetLpValueLogic { - return &GetLpValueLogic{ - Logger: logx.WithContext(ctx), - ctx: ctx, - svcCtx: svcCtx, - } -} - -func (l *GetLpValueLogic) GetLPValue(req *types.ReqGetLpValue) (resp *types.LpValue, err error) { - amount, isTure := new(big.Int).SetString(req.LpAmount, 10) - if !isTure { - logx.Errorf("fail to convert string: %s to int", req.LpAmount) - return nil, types2.AppErrInvalidParam.RefineError("invalid LpAmount") - } - - liquidity, err := l.svcCtx.StateFetcher.GetLatestLiquidity(int64(req.PairIndex)) - if err != nil { - if err == types2.DbErrNotFound { - return nil, types2.AppErrNotFound - } - return nil, types2.AppErrInternal - } - assetAAmount, assetBAmount := big.NewInt(0), big.NewInt(0) - if liquidity.LpAmount.Cmp(types2.ZeroBigInt) > 0 { - assetAAmount, assetBAmount, err = chain.ComputeRemoveLiquidityAmount(liquidity, amount) - if err != nil { - logx.Errorf("fail to compute liquidity amount, err: %s", err.Error()) - return nil, types2.AppErrInternal - } - } - assetA, err := l.svcCtx.AssetModel.GetAssetById(liquidity.AssetAId) - if err != nil { - return nil, types2.AppErrInternal - } - assetB, err := l.svcCtx.AssetModel.GetAssetById(liquidity.AssetBId) - if err != nil { - return nil, types2.AppErrInternal - } - assetAPrice, err := l.svcCtx.PriceFetcher.GetCurrencyPrice(l.ctx, assetA.AssetSymbol) - if err != nil { - return nil, types2.AppErrInternal - } - assetBPrice, err := l.svcCtx.PriceFetcher.GetCurrencyPrice(l.ctx, assetB.AssetSymbol) - if err != nil { - return nil, types2.AppErrInternal - } - resp = &types.LpValue{ - AssetAId: uint32(liquidity.AssetAId), - AssetAName: assetA.AssetName, - AssetAAmount: assetAAmount.String(), - AssetAPrice: strconv.FormatFloat(assetAPrice, 'E', -1, 64), - AssetBId: uint32(liquidity.AssetBId), - AssetBName: assetB.AssetName, - AssetBAmount: assetBAmount.String(), - AssetBPrice: strconv.FormatFloat(assetBPrice, 'E', -1, 64), - } - - return resp, nil -} diff --git a/service/apiserver/internal/logic/pair/getpairlogic.go b/service/apiserver/internal/logic/pair/getpairlogic.go deleted file mode 100644 index b9fafe4d6..000000000 --- a/service/apiserver/internal/logic/pair/getpairlogic.go +++ /dev/null @@ -1,66 +0,0 @@ -package pair - -import ( - "context" - "strconv" - - "github.com/zeromicro/go-zero/core/logx" - - "github.com/bnb-chain/zkbnb/service/apiserver/internal/svc" - "github.com/bnb-chain/zkbnb/service/apiserver/internal/types" - types2 "github.com/bnb-chain/zkbnb/types" -) - -type GetPairLogic struct { - logx.Logger - ctx context.Context - svcCtx *svc.ServiceContext -} - -func NewGetPairLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetPairLogic { - return &GetPairLogic{ - Logger: logx.WithContext(ctx), - ctx: ctx, - svcCtx: svcCtx, - } -} - -func (l *GetPairLogic) GetPair(req *types.ReqGetPair) (resp *types.Pair, err error) { - liquidity, err := l.svcCtx.StateFetcher.GetLatestLiquidity(int64(req.Index)) - if err != nil { - logx.Errorf("fail to get pair info: %d, err: %s", req.Index, err.Error()) - if err == types2.DbErrNotFound { - return nil, types2.AppErrNotFound - } - return nil, types2.AppErrInternal - } - assetA, err := l.svcCtx.AssetModel.GetAssetById(liquidity.AssetAId) - if err != nil { - return nil, types2.AppErrInternal - } - assetB, err := l.svcCtx.AssetModel.GetAssetById(liquidity.AssetBId) - if err != nil { - return nil, types2.AppErrInternal - } - assetAPrice, err := l.svcCtx.PriceFetcher.GetCurrencyPrice(l.ctx, assetA.AssetSymbol) - if err != nil { - return nil, types2.AppErrInternal - } - assetBPrice, err := l.svcCtx.PriceFetcher.GetCurrencyPrice(l.ctx, assetB.AssetSymbol) - if err != nil { - return nil, types2.AppErrInternal - } - resp = &types.Pair{ - Index: uint32(liquidity.PairIndex), - AssetAId: uint32(liquidity.AssetAId), - AssetAName: assetA.AssetName, - AssetAAmount: liquidity.AssetA.String(), - AssetAPrice: strconv.FormatFloat(assetAPrice, 'E', -1, 64), - AssetBId: uint32(liquidity.AssetBId), - AssetBName: assetB.AssetName, - AssetBAmount: liquidity.AssetB.String(), - AssetBPrice: strconv.FormatFloat(assetBPrice, 'E', -1, 64), - TotalLpAmount: liquidity.LpAmount.String(), - } - return resp, nil -} diff --git a/service/apiserver/internal/logic/pair/getpairslogic.go b/service/apiserver/internal/logic/pair/getpairslogic.go deleted file mode 100644 index 6d75c5152..000000000 --- a/service/apiserver/internal/logic/pair/getpairslogic.go +++ /dev/null @@ -1,72 +0,0 @@ -package pair - -import ( - "context" - "strconv" - - "github.com/zeromicro/go-zero/core/logx" - - "github.com/bnb-chain/zkbnb/service/apiserver/internal/svc" - "github.com/bnb-chain/zkbnb/service/apiserver/internal/types" - types2 "github.com/bnb-chain/zkbnb/types" -) - -type GetPairsLogic struct { - logx.Logger - ctx context.Context - svcCtx *svc.ServiceContext -} - -func NewGetPairsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetPairsLogic { - return &GetPairsLogic{ - Logger: logx.WithContext(ctx), - ctx: ctx, - svcCtx: svcCtx, - } -} - -func (l *GetPairsLogic) GetPairs() (*types.Pairs, error) { - resp := &types.Pairs{Pairs: make([]*types.Pair, 0)} - - liquidityAssets, err := l.svcCtx.LiquidityModel.GetAllLiquidity() - if err != nil { - if err == types2.DbErrNotFound { - return resp, nil - } - return nil, types2.AppErrInternal - } - - for _, liquidity := range liquidityAssets { - assetA, err := l.svcCtx.AssetModel.GetAssetById(liquidity.AssetAId) - if err != nil { - return nil, types2.AppErrInternal - } - assetB, err := l.svcCtx.AssetModel.GetAssetById(liquidity.AssetBId) - if err != nil { - return nil, types2.AppErrInternal - } - assetAPrice, err := l.svcCtx.PriceFetcher.GetCurrencyPrice(l.ctx, assetA.AssetSymbol) - if err != nil { - return nil, types2.AppErrInternal - } - assetBPrice, err := l.svcCtx.PriceFetcher.GetCurrencyPrice(l.ctx, assetB.AssetSymbol) - if err != nil { - return nil, types2.AppErrInternal - } - resp.Pairs = append(resp.Pairs, &types.Pair{ - Index: uint32(liquidity.PairIndex), - AssetAId: uint32(liquidity.AssetAId), - AssetAName: assetA.AssetName, - AssetAAmount: liquidity.AssetA, - AssetAPrice: strconv.FormatFloat(assetAPrice, 'E', -1, 64), - AssetBId: uint32(liquidity.AssetBId), - AssetBName: assetB.AssetName, - AssetBAmount: liquidity.AssetB, - AssetBPrice: strconv.FormatFloat(assetBPrice, 'E', -1, 64), - FeeRate: liquidity.FeeRate, - TreasuryRate: liquidity.TreasuryRate, - TotalLpAmount: liquidity.LpAmount, - }) - } - return resp, nil -} diff --git a/service/apiserver/internal/logic/pair/getswapamountlogic.go b/service/apiserver/internal/logic/pair/getswapamountlogic.go deleted file mode 100644 index fd6e9eabe..000000000 --- a/service/apiserver/internal/logic/pair/getswapamountlogic.go +++ /dev/null @@ -1,73 +0,0 @@ -package pair - -import ( - "context" - "math/big" - - "github.com/zeromicro/go-zero/core/logx" - - "github.com/bnb-chain/zkbnb/common/chain" - "github.com/bnb-chain/zkbnb/service/apiserver/internal/svc" - "github.com/bnb-chain/zkbnb/service/apiserver/internal/types" - types2 "github.com/bnb-chain/zkbnb/types" -) - -type GetSwapAmountLogic struct { - logx.Logger - ctx context.Context - svcCtx *svc.ServiceContext -} - -func NewGetSwapAmountLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetSwapAmountLogic { - return &GetSwapAmountLogic{ - Logger: logx.WithContext(ctx), - ctx: ctx, - svcCtx: svcCtx, - } -} - -func (l *GetSwapAmountLogic) GetSwapAmount(req *types.ReqGetSwapAmount) (*types.SwapAmount, error) { - deltaAmount, isTure := new(big.Int).SetString(req.AssetAmount, 10) - if !isTure { - logx.Errorf("fail to convert string: %s to int", req.AssetAmount) - return nil, types2.AppErrInvalidParam.RefineError("invalid AssetAmount") - } - - liquidity, err := l.svcCtx.StateFetcher.GetLatestLiquidity(int64(req.PairIndex)) - if err != nil { - if err == types2.DbErrNotFound { - return nil, types2.AppErrNotFound - } - return nil, types2.AppErrInternal - } - - if liquidity.AssetA == nil || liquidity.AssetB == nil { - logx.Errorf("invalid liquidity: %v", liquidity) - return nil, types2.AppErrInternal - } - - if int64(req.AssetId) != liquidity.AssetAId && int64(req.AssetId) != liquidity.AssetBId { - logx.Errorf("invalid liquidity asset ids: %v", liquidity) - return nil, types2.AppErrInvalidParam.RefineError("invalid AssetId") - } - - if liquidity.AssetA.Cmp(types2.ZeroBigInt) == 0 || liquidity.AssetB.Cmp(types2.ZeroBigInt) == 0 { - logx.Errorf("invalid liquidity asset amount: %v", liquidity) - return nil, types2.AppErrInvalidParam.RefineError("invalid PairIndex, empty liquidity or invalid pair") - } - - var assetAmount *big.Int - var toAssetId int64 - assetAmount, toAssetId, err = chain.ComputeDelta(liquidity.AssetA, liquidity.AssetB, liquidity.AssetAId, liquidity.AssetBId, - int64(req.AssetId), req.IsFrom, deltaAmount, liquidity.FeeRate) - if err != nil { - logx.Errorf("fail to compute delta, err: %s", err.Error()) - return nil, types2.AppErrInternal - } - assetName, _ := l.svcCtx.MemCache.GetAssetNameById(toAssetId) - return &types.SwapAmount{ - AssetId: uint32(toAssetId), - AssetName: assetName, - AssetAmount: assetAmount.String(), - }, nil -} diff --git a/service/apiserver/internal/logic/transaction/getnextnoncelogic.go b/service/apiserver/internal/logic/transaction/getnextnoncelogic.go index a1f00e88a..0f1e35f31 100644 --- a/service/apiserver/internal/logic/transaction/getnextnoncelogic.go +++ b/service/apiserver/internal/logic/transaction/getnextnoncelogic.go @@ -26,7 +26,7 @@ func NewGetNextNonceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetN } func (l *GetNextNonceLogic) GetNextNonce(req *types.ReqGetNextNonce) (*types.NextNonce, error) { - bc, err := core.NewBlockChainForDryRun(l.svcCtx.AccountModel, l.svcCtx.LiquidityModel, l.svcCtx.NftModel, + bc, err := core.NewBlockChainForDryRun(l.svcCtx.AccountModel, l.svcCtx.NftModel, l.svcCtx.TxPoolModel, l.svcCtx.AssetModel, l.svcCtx.SysConfigModel, l.svcCtx.RedisCache) if err != nil { return nil, err diff --git a/service/apiserver/internal/logic/transaction/sendtxlogic.go b/service/apiserver/internal/logic/transaction/sendtxlogic.go index a6165c83c..8fca79589 100644 --- a/service/apiserver/internal/logic/transaction/sendtxlogic.go +++ b/service/apiserver/internal/logic/transaction/sendtxlogic.go @@ -37,7 +37,7 @@ func (s *SendTxLogic) SendTx(req *types.ReqSendTx) (resp *types.TxHash, err erro } resp = &types.TxHash{} - bc, err := core.NewBlockChainForDryRun(s.svcCtx.AccountModel, s.svcCtx.LiquidityModel, s.svcCtx.NftModel, s.svcCtx.TxPoolModel, + bc, err := core.NewBlockChainForDryRun(s.svcCtx.AccountModel, s.svcCtx.NftModel, s.svcCtx.TxPoolModel, s.svcCtx.AssetModel, s.svcCtx.SysConfigModel, s.svcCtx.RedisCache) if err != nil { logx.Error("fail to init blockchain runner:", err) @@ -50,7 +50,6 @@ func (s *SendTxLogic) SendTx(req *types.ReqSendTx) (resp *types.TxHash, err erro GasFeeAssetId: types2.NilAssetId, GasFee: types2.NilAssetAmount, - PairIndex: types2.NilPairIndex, NftIndex: types2.NilNftIndex, CollectionId: types2.NilCollectionNonce, AssetId: types2.NilAssetId, diff --git a/service/apiserver/internal/logic/utils/converter.go b/service/apiserver/internal/logic/utils/converter.go index 754fa3509..fab43158d 100644 --- a/service/apiserver/internal/logic/utils/converter.go +++ b/service/apiserver/internal/logic/utils/converter.go @@ -15,7 +15,6 @@ func ConvertTx(tx *tx.Tx) *types.Tx { Index: tx.TxIndex, BlockHeight: tx.BlockHeight, NftIndex: tx.NftIndex, - PairIndex: tx.PairIndex, CollectionId: tx.CollectionId, AssetId: tx.AssetId, Amount: tx.TxAmount, diff --git a/service/apiserver/internal/svc/servicecontext.go b/service/apiserver/internal/svc/servicecontext.go index 107e96cf9..4f327d548 100644 --- a/service/apiserver/internal/svc/servicecontext.go +++ b/service/apiserver/internal/svc/servicecontext.go @@ -11,7 +11,6 @@ import ( "github.com/bnb-chain/zkbnb/dao/asset" "github.com/bnb-chain/zkbnb/dao/block" "github.com/bnb-chain/zkbnb/dao/dbcache" - "github.com/bnb-chain/zkbnb/dao/liquidity" "github.com/bnb-chain/zkbnb/dao/nft" "github.com/bnb-chain/zkbnb/dao/sysconfig" "github.com/bnb-chain/zkbnb/dao/tx" @@ -26,17 +25,15 @@ type ServiceContext struct { RedisCache dbcache.Cache MemCache *cache.MemCache - DB *gorm.DB - TxPoolModel tx.TxPoolModel - AccountModel account.AccountModel - AccountHistoryModel account.AccountHistoryModel - TxModel tx.TxModel - LiquidityModel liquidity.LiquidityModel - LiquidityHistoryModel liquidity.LiquidityHistoryModel - BlockModel block.BlockModel - NftModel nft.L2NftModel - AssetModel asset.AssetModel - SysConfigModel sysconfig.SysConfigModel + DB *gorm.DB + TxPoolModel tx.TxPoolModel + AccountModel account.AccountModel + AccountHistoryModel account.AccountHistoryModel + TxModel tx.TxModel + BlockModel block.BlockModel + NftModel nft.L2NftModel + AssetModel asset.AssetModel + SysConfigModel sysconfig.SysConfigModel PriceFetcher price.Fetcher StateFetcher state.Fetcher @@ -51,29 +48,26 @@ func NewServiceContext(c config.Config) *ServiceContext { txPoolModel := tx.NewTxPoolModel(db) accountModel := account.NewAccountModel(db) - liquidityModel := liquidity.NewLiquidityModel(db) nftModel := nft.NewL2NftModel(db) assetModel := asset.NewAssetModel(db) - memCache := cache.NewMemCache(accountModel, assetModel, c.MemCache.AccountExpiration, c.MemCache.BlockExpiration, - c.MemCache.TxExpiration, c.MemCache.AssetExpiration, c.MemCache.PriceExpiration) + memCache := cache.MustNewMemCache(accountModel, assetModel, c.MemCache.AccountExpiration, c.MemCache.BlockExpiration, + c.MemCache.TxExpiration, c.MemCache.AssetExpiration, c.MemCache.PriceExpiration, c.MemCache.MaxCounterNum, c.MemCache.MaxKeyNum) return &ServiceContext{ - Config: c, - RedisCache: redisCache, - MemCache: memCache, - DB: db, - TxPoolModel: txPoolModel, - AccountModel: accountModel, - AccountHistoryModel: account.NewAccountHistoryModel(db), - TxModel: tx.NewTxModel(db), - LiquidityModel: liquidityModel, - LiquidityHistoryModel: liquidity.NewLiquidityHistoryModel(db), - BlockModel: block.NewBlockModel(db), - NftModel: nftModel, - AssetModel: assetModel, - SysConfigModel: sysconfig.NewSysConfigModel(db), + Config: c, + RedisCache: redisCache, + MemCache: memCache, + DB: db, + TxPoolModel: txPoolModel, + AccountModel: accountModel, + AccountHistoryModel: account.NewAccountHistoryModel(db), + TxModel: tx.NewTxModel(db), + BlockModel: block.NewBlockModel(db), + NftModel: nftModel, + AssetModel: assetModel, + SysConfigModel: sysconfig.NewSysConfigModel(db), PriceFetcher: price.NewFetcher(memCache, assetModel, c.CoinMarketCap.Url, c.CoinMarketCap.Token), - StateFetcher: state.NewFetcher(redisCache, accountModel, liquidityModel, nftModel), + StateFetcher: state.NewFetcher(redisCache, accountModel, nftModel), } } diff --git a/service/apiserver/server.api b/service/apiserver/server.api index 369092c4f..0c982d982 100644 --- a/service/apiserver/server.api +++ b/service/apiserver/server.api @@ -40,19 +40,14 @@ type ( Price string `json:"price"` } - AccountLp { - Index uint32 `json:"index"` - Amount string `json:"amount"` - } - Account { - Status uint32 `json:"status"` - Index int64 `json:"index"` - Name string `json:"name"` - Pk string `json:"pk"` - Nonce int64 `json:"nonce"` - Assets []*AccountAsset `json:"assets"` - Lps []*AccountLp `json:"lps"` + Status uint32 `json:"status"` + Index int64 `json:"index"` + Name string `json:"name"` + Pk string `json:"pk"` + Nonce int64 `json:"nonce"` + Assets []*AccountAsset `json:"assets"` + TotalAssetValue string `json:"total_asset_value"` } SimpleAccount { @@ -99,6 +94,7 @@ type ( Address string `json:"address"` Price string `json:"price"` IsGasAsset uint32 `json:"is_gas_asset"` + Icon string `json:"icon"` } Assets { @@ -144,6 +140,7 @@ type ( VerifiedAt int64 `json:"verified_at"` Txs []*Tx `json:"txs"` Status int64 `json:"status"` + Size uint16 `json:"size"` } Blocks { @@ -255,85 +252,6 @@ service server-api { get /api/v1/search (ReqSearch) returns (Search) } -/* =========================== Pair ==========================*/ - -type ( - SwapAmount { - AssetId uint32 `json:"asset_id"` - AssetName string `json:"asset_name"` - AssetAmount string `json:"asset_amount"` - } - - Pair { - Index uint32 `json:"index"` - AssetAId uint32 `json:"asset_a_id"` - AssetAName string `json:"asset_a_name"` - AssetAAmount string `json:"asset_a_amount"` - AssetAPrice string `json:"asset_a_price"` - AssetBId uint32 `json:"asset_b_id"` - AssetBName string `json:"asset_b_name"` - AssetBPrice string `json:"asset_b_price"` - AssetBAmount string `json:"asset_b_amount"` - FeeRate int64 `json:"fee_rate"` - TreasuryRate int64 `json:"treasury_rate"` - TotalLpAmount string `json:"total_lp_amount"` - } - Pairs { - Pairs []*Pair `json:"pairs"` - } - - LpValue { - AssetAId uint32 `json:"asset_a_id"` - AssetAName string `json:"asset_a_name"` - AssetAPrice string `json:"asset_a_price"` - AssetAAmount string `json:"asset_a_amount"` - AssetBId uint32 `json:"asset_b_id"` - AssetBName string `json:"asset_b_name"` - AssetBPrice string `json:"asset_b_price"` - AssetBAmount string `json:"asset_b_amount"` - } -) - -type ( - ReqGetSwapAmount { - PairIndex uint32 `form:"pair_index"` - AssetId uint32 `form:"asset_id"` - AssetAmount string `form:"asset_amount"` - IsFrom bool `form:"is_from"` - } - - ReqGetLpValue { - PairIndex uint32 `form:"pair_index"` - LpAmount string `form:"lp_amount"` - } - - ReqGetPair { - Index uint32 `form:"index"` - } -) - -@server( - group: pair -) - -service server-api { - @doc "Get swap amount for a specific liquidity pair and in asset amount" - @handler GetSwapAmount - get /api/v1/swapAmount (ReqGetSwapAmount) returns (SwapAmount) - - @doc "Get liquidity pairs" - @handler GetPairs - get /api/v1/pairs returns (Pairs) - - @doc "Get liquidity pool amount for a specific liquidity pair" - @handler GetLpValue - get /api/v1/lpValue (ReqGetLpValue) returns (LpValue) - - @doc "Get liquidity pool info by its index" - @handler GetPair - get /api/v1/pair (ReqGetPair) returns (Pair) -} - /* ======================= Transaction =======================*/ type ( @@ -348,7 +266,6 @@ type ( GasFee string `json:"gas_fee"` NftIndex int64 `json:"nft_index"` CollectionId int64 `json:"collection_id"` - PairIndex int64 `json:"pair_index"` AssetId int64 `json:"asset_id"` AssetName string `json:"asset_name"` NativeAddress string `json:"native_address"` diff --git a/service/apiserver/test/getblock_test.go b/service/apiserver/test/getblock_test.go index d60ee4739..b68610599 100644 --- a/service/apiserver/test/getblock_test.go +++ b/service/apiserver/test/getblock_test.go @@ -36,6 +36,7 @@ func (s *ApiServerSuite) TestGetBlock() { assert.NotNil(t, result.Height) assert.NotNil(t, result.Commitment) assert.NotNil(t, result.Status) + assert.NotNil(t, result.Size) assert.NotNil(t, result.StateRoot) fmt.Printf("result: %+v \n", result) } diff --git a/service/apiserver/test/getblocks_test.go b/service/apiserver/test/getblocks_test.go index e76a3a2d7..053c315d2 100644 --- a/service/apiserver/test/getblocks_test.go +++ b/service/apiserver/test/getblocks_test.go @@ -38,6 +38,7 @@ func (s *ApiServerSuite) TestGetBlocks() { assert.NotNil(t, result.Blocks[0].Height) assert.NotNil(t, result.Blocks[0].Commitment) assert.NotNil(t, result.Blocks[0].Status) + assert.NotNil(t, result.Blocks[0].Size) assert.NotNil(t, result.Blocks[0].StateRoot) //assert.NotNil(t, result.Blocks[0].Txs) } diff --git a/service/apiserver/test/getlpvalue_test.go b/service/apiserver/test/getlpvalue_test.go deleted file mode 100644 index e36639858..000000000 --- a/service/apiserver/test/getlpvalue_test.go +++ /dev/null @@ -1,77 +0,0 @@ -package test - -import ( - "encoding/json" - "fmt" - "io" - "math" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/bnb-chain/zkbnb/service/apiserver/internal/types" -) - -func (s *ApiServerSuite) TestGetLpValue() { - type args struct { - pairIndex int - lpAmount string - } - - type testcase struct { - name string - args args - httpCode int - } - - tests := []testcase{ - {"not found", args{math.MaxInt, "2"}, 400}, - } - - statusCode, pairs := GetPairs(s, 0, 100) - if statusCode == http.StatusOK && len(pairs.Pairs) > 0 { - for _, pair := range pairs.Pairs { - if pair.TotalLpAmount != "" && pair.TotalLpAmount != "0" { - tests = append(tests, []testcase{ - {"found by index", args{int(pair.Index), "9000"}, 200}, - }...) - break - } - } - } - - for _, tt := range tests { - s.T().Run(tt.name, func(t *testing.T) { - httpCode, result := GetLpValue(s, tt.args.pairIndex, tt.args.lpAmount) - assert.Equal(t, tt.httpCode, httpCode) - if httpCode == http.StatusOK { - assert.NotNil(t, result.AssetAId) - assert.NotNil(t, result.AssetAName) - assert.NotNil(t, result.AssetAAmount) - assert.NotNil(t, result.AssetBId) - assert.NotNil(t, result.AssetBName) - assert.NotNil(t, result.AssetBAmount) - fmt.Printf("result: %+v \n", result) - } - }) - } - -} - -func GetLpValue(s *ApiServerSuite, pairIndex int, lpAmount string) (int, *types.LpValue) { - resp, err := http.Get(fmt.Sprintf("%s/api/v1/lpValue?pair_index=%d&lp_amount=%s", s.url, pairIndex, lpAmount)) - assert.NoError(s.T(), err) - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - assert.NoError(s.T(), err) - - if resp.StatusCode != http.StatusOK { - return resp.StatusCode, nil - } - result := types.LpValue{} - //nolint: errcheck - json.Unmarshal(body, &result) - return resp.StatusCode, &result -} diff --git a/service/apiserver/test/getpair_test.go b/service/apiserver/test/getpair_test.go deleted file mode 100644 index f7de4b0b7..000000000 --- a/service/apiserver/test/getpair_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package test - -import ( - "encoding/json" - "fmt" - "io" - "math" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/bnb-chain/zkbnb/service/apiserver/internal/types" -) - -func (s *ApiServerSuite) TestGetPair() { - type testcase struct { - name string - args int //pair index - httpCode int - } - - tests := []testcase{ - {"not found", math.MaxInt, 400}, - } - - statusCode, pairs := GetPairs(s, 0, 100) - if statusCode == http.StatusOK && len(pairs.Pairs) > 0 { - tests = append(tests, []testcase{ - {"found by index", int(pairs.Pairs[0].Index), 200}, - }...) - } - - for _, tt := range tests { - s.T().Run(tt.name, func(t *testing.T) { - httpCode, result := GetPair(s, tt.args) - assert.Equal(t, tt.httpCode, httpCode) - if httpCode == http.StatusOK { - assert.NotNil(t, result.AssetAId) - assert.NotNil(t, result.AssetBId) - assert.NotNil(t, result.AssetAAmount) - assert.NotNil(t, result.AssetBAmount) - assert.NotNil(t, result.TotalLpAmount) - fmt.Printf("result: %+v \n", result) - } - }) - } - -} - -func GetPair(s *ApiServerSuite, pairIndex int) (int, *types.Pair) { - resp, err := http.Get(fmt.Sprintf("%s/api/v1/pair?index=%d", s.url, pairIndex)) - assert.NoError(s.T(), err) - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - assert.NoError(s.T(), err) - - if resp.StatusCode != http.StatusOK { - return resp.StatusCode, nil - } - result := types.Pair{} - //nolint: errcheck - json.Unmarshal(body, &result) - return resp.StatusCode, &result -} diff --git a/service/apiserver/test/getpairs_test.go b/service/apiserver/test/getpairs_test.go deleted file mode 100644 index cde54028c..000000000 --- a/service/apiserver/test/getpairs_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package test - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/bnb-chain/zkbnb/service/apiserver/internal/types" -) - -func (s *ApiServerSuite) TestGetPairs() { - - type args struct { - offset int - limit int - } - tests := []struct { - name string - args args - httpCode int - }{ - {"found", args{0, 10}, 200}, - } - - for _, tt := range tests { - s.T().Run(tt.name, func(t *testing.T) { - httpCode, result := GetPairs(s, tt.args.offset, tt.args.limit) - assert.Equal(t, tt.httpCode, httpCode) - if httpCode == http.StatusOK { - assert.NotNil(t, result.Pairs) - if len(result.Pairs) > 0 { - assert.NotNil(t, result.Pairs[0].Index) - assert.NotNil(t, result.Pairs[0].AssetAName) - assert.NotNil(t, result.Pairs[0].AssetBName) - assert.NotNil(t, result.Pairs[0].AssetAId) - assert.NotNil(t, result.Pairs[0].AssetBId) - assert.NotNil(t, result.Pairs[0].AssetAAmount) - assert.NotNil(t, result.Pairs[0].AssetBAmount) - assert.NotNil(t, result.Pairs[0].FeeRate) - assert.NotNil(t, result.Pairs[0].TreasuryRate) - } - fmt.Printf("result: %+v \n", result) - } - }) - } - -} - -func GetPairs(s *ApiServerSuite, offset, limit int) (int, *types.Pairs) { - resp, err := http.Get(fmt.Sprintf("%s/api/v1/pairs?offset=%d&limit=%d", s.url, offset, limit)) - assert.NoError(s.T(), err) - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - assert.NoError(s.T(), err) - - if resp.StatusCode != http.StatusOK { - return resp.StatusCode, nil - } - result := types.Pairs{} - //nolint: errcheck - json.Unmarshal(body, &result) - return resp.StatusCode, &result -} diff --git a/service/apiserver/test/getswapamount_test.go b/service/apiserver/test/getswapamount_test.go deleted file mode 100644 index 82630ccaf..000000000 --- a/service/apiserver/test/getswapamount_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package test - -import ( - "encoding/json" - "fmt" - "io" - "math" - "net/http" - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/bnb-chain/zkbnb/service/apiserver/internal/types" -) - -func (s *ApiServerSuite) TestGetSwapAmount() { - type args struct { - pairIndex uint32 - assetId uint32 - assetAmount string - isFrom bool - } - - type testcase struct { - name string - args args - httpCode int - } - - tests := []testcase{ - {"not found", args{math.MaxUint32, math.MaxUint32, "1", true}, 400}, - } - - statusCode, pairs := GetPairs(s, 0, 100) - if statusCode == http.StatusOK && len(pairs.Pairs) > 0 { - for _, pair := range pairs.Pairs { - if pair.TotalLpAmount != "" && pair.TotalLpAmount != "0" { - tests = append(tests, []testcase{ - {"found by index with from is true", args{pair.Index, pair.AssetAId, "9000", true}, 200}, - {"found by index with from is true", args{pair.Index, pair.AssetBId, "9000", true}, 200}, - {"found by index with from is false", args{pair.Index, pair.AssetAId, "9000", false}, 200}, - {"found by index with from is false", args{pair.Index, pair.AssetBId, "9000", false}, 200}, - }...) - break - } - } - } - - for _, tt := range tests { - s.T().Run(tt.name, func(t *testing.T) { - httpCode, result := GetSwapAmount(s, tt.args.pairIndex, tt.args.assetId, tt.args.assetAmount, tt.args.isFrom) - assert.Equal(t, tt.httpCode, httpCode) - if httpCode == http.StatusOK { - assert.NotNil(t, result.AssetId) - assert.NotNil(t, result.AssetAmount) - fmt.Printf("result: %+v \n", result) - } - }) - } - -} - -func GetSwapAmount(s *ApiServerSuite, pairIndex, assetId uint32, assetAmount string, isFrom bool) (int, *types.SwapAmount) { - resp, err := http.Get(fmt.Sprintf("%s/api/v1/swapAmount?pair_index=%d&asset_id=%d&asset_amount=%s&is_from=%v", s.url, pairIndex, assetId, assetAmount, isFrom)) - assert.NoError(s.T(), err) - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - assert.NoError(s.T(), err) - - if resp.StatusCode != http.StatusOK { - return resp.StatusCode, nil - } - result := types.SwapAmount{} - //nolint: errcheck - json.Unmarshal(body, &result) - return resp.StatusCode, &result -} diff --git a/service/apiserver/test/suite_test.go b/service/apiserver/test/suite_test.go index feb6397c8..8fc2673f4 100644 --- a/service/apiserver/test/suite_test.go +++ b/service/apiserver/test/suite_test.go @@ -78,7 +78,9 @@ func (s *ApiServerSuite) SetupSuite() { BlockExpiration int TxExpiration int PriceExpiration int - }{AccountExpiration: 10000, AssetExpiration: 10000, BlockExpiration: 10000, TxExpiration: 10000, PriceExpiration: 3600000}, + MaxCounterNum int64 + MaxKeyNum int64 + }{AccountExpiration: 10000, AssetExpiration: 10000, BlockExpiration: 10000, TxExpiration: 10000, PriceExpiration: 3600000, MaxCounterNum: 10000, MaxKeyNum: 10000}, } c.Postgres = struct{ DataSource string }{DataSource: "host=127.0.0.1 user=postgres password=ZkBNB@123 dbname=zkbnb port=5433 sslmode=disable"} c.CacheRedis = cache.CacheConf{} diff --git a/service/committer/committer/committer.go b/service/committer/committer/committer.go index 80d77d1e2..387bd9ad9 100644 --- a/service/committer/committer/committer.go +++ b/service/committer/committer/committer.go @@ -5,18 +5,33 @@ import ( "fmt" "time" + "github.com/prometheus/client_golang/prometheus" "github.com/zeromicro/go-zero/core/logx" "gorm.io/gorm" "github.com/bnb-chain/zkbnb/core" "github.com/bnb-chain/zkbnb/dao/block" "github.com/bnb-chain/zkbnb/dao/tx" + "github.com/bnb-chain/zkbnb/types" ) const ( MaxCommitterInterval = 60 * 1 ) +var ( + priorityOperationMetric = prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "zkbnb", + Name: "priority_operation_process", + Help: "Priority operation requestID metrics.", + }) + priorityOperationHeightMetric = prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "zkbnb", + Name: "priority_operation_process_height", + Help: "Priority operation height metrics.", + }) +) + type Config struct { core.ChainConfig @@ -45,6 +60,13 @@ func NewCommitter(config *Config) (*Committer, error) { return nil, fmt.Errorf("new blockchain error: %v", err) } + if err := prometheus.Register(priorityOperationMetric); err != nil { + return nil, fmt.Errorf("prometheus.Register priorityOperationMetric error: %v", err) + } + if err := prometheus.Register(priorityOperationHeightMetric); err != nil { + return nil, fmt.Errorf("prometheus.Register priorityOperationHeightMetric error: %v", err) + } + committer := &Committer{ running: true, config: config, @@ -62,6 +84,12 @@ func (c *Committer) Run() { panic("restore executed tx failed: " + err.Error()) } + latestRequestId, err := c.getLatestExecutedRequestId() + if err != nil { + logx.Error("get latest executed request ID failed:", err) + latestRequestId = -1 + } + for { if !c.running { break @@ -108,6 +136,23 @@ func (c *Committer) Run() { continue } + if types.IsPriorityOperationTx(poolTx.TxType) { + request, err := c.bc.PriorityRequestModel.GetPriorityRequestsByL2TxHash(poolTx.TxHash) + if err == nil { + + priorityOperationMetric.Set(float64(request.RequestId)) + priorityOperationHeightMetric.Set(float64(request.L1BlockHeight)) + + if latestRequestId != -1 && request.RequestId != latestRequestId+1 { + logx.Errorf("invalid request ID: %d, txHash: %s", request.RequestId, poolTx.TxHash) + return + } + latestRequestId = request.RequestId + } else { + logx.Errorf("query txHash: %s in PriorityRequestTable failed, err %v ", poolTx.TxHash, err) + } + } + // Write the proposed block into database when the first transaction executed. if len(c.bc.Statedb.Txs) == 1 { err = c.createNewBlock(curBlock, poolTx) @@ -138,7 +183,10 @@ func (c *Committer) Run() { if c.shouldCommit(curBlock) { logx.Infof("commit new block, height=%d, blockSize=%d", curBlock.BlockHeight, curBlock.BlockSize) curBlock, err = c.commitNewBlock(curBlock) + logx.Infof("commit new block success") + if err != nil { + logx.Errorf("commit new block error, err=%s", err.Error()) panic("commit new block failed: " + err.Error()) } } @@ -212,6 +260,11 @@ func (c *Committer) commitNewBlock(curBlock *block.Block) (*block.Block, error) return nil, err } + err = c.bc.Statedb.SyncPendingGasAccount() + if err != nil { + return nil, err + } + // update db err = c.bc.DB().DB.Transaction(func(tx *gorm.DB) error { // create block for commit @@ -221,65 +274,30 @@ func (c *Committer) commitNewBlock(curBlock *block.Block) (*block.Block, error) return err } } - // create new account - if len(blockStates.PendingNewAccount) != 0 { - err = c.bc.DB().AccountModel.CreateAccountsInTransact(tx, blockStates.PendingNewAccount) + // create or update account + if len(blockStates.PendingAccount) != 0 { + err = c.bc.DB().AccountModel.UpdateAccountsInTransact(tx, blockStates.PendingAccount) if err != nil { return err } } - // update account - if len(blockStates.PendingUpdateAccount) != 0 { - err = c.bc.DB().AccountModel.UpdateAccountsInTransact(tx, blockStates.PendingUpdateAccount) + // create account history + if len(blockStates.PendingAccountHistory) != 0 { + err = c.bc.DB().AccountHistoryModel.CreateAccountHistoriesInTransact(tx, blockStates.PendingAccountHistory) if err != nil { return err } } - // create new account history - if len(blockStates.PendingNewAccountHistory) != 0 { - err = c.bc.DB().AccountHistoryModel.CreateAccountHistoriesInTransact(tx, blockStates.PendingNewAccountHistory) + // create or update nft + if len(blockStates.PendingNft) != 0 { + err = c.bc.DB().L2NftModel.UpdateNftsInTransact(tx, blockStates.PendingNft) if err != nil { return err } } - // create new liquidity - if len(blockStates.PendingNewLiquidity) != 0 { - err = c.bc.DB().LiquidityModel.CreateLiquidityInTransact(tx, blockStates.PendingNewLiquidity) - if err != nil { - return err - } - } - // update liquidity - if len(blockStates.PendingUpdateLiquidity) != 0 { - err = c.bc.DB().LiquidityModel.UpdateLiquidityInTransact(tx, blockStates.PendingUpdateLiquidity) - if err != nil { - return err - } - } - // create new liquidity history - if len(blockStates.PendingNewLiquidityHistory) != 0 { - err = c.bc.DB().LiquidityHistoryModel.CreateLiquidityHistoriesInTransact(tx, blockStates.PendingNewLiquidityHistory) - if err != nil { - return err - } - } - // create new nft - if len(blockStates.PendingNewNft) != 0 { - err = c.bc.DB().L2NftModel.CreateNftsInTransact(tx, blockStates.PendingNewNft) - if err != nil { - return err - } - } - // update nft - if len(blockStates.PendingUpdateNft) != 0 { - err = c.bc.DB().L2NftModel.UpdateNftsInTransact(tx, blockStates.PendingUpdateNft) - if err != nil { - return err - } - } - // new nft history - if len(blockStates.PendingNewNftHistory) != 0 { - err = c.bc.DB().L2NftHistoryModel.CreateNftHistoriesInTransact(tx, blockStates.PendingNewNftHistory) + // create nft history + if len(blockStates.PendingNftHistory) != 0 { + err = c.bc.DB().L2NftHistoryModel.CreateNftHistoriesInTransact(tx, blockStates.PendingNftHistory) if err != nil { return err } @@ -293,7 +311,6 @@ func (c *Committer) commitNewBlock(curBlock *block.Block) (*block.Block, error) blockStates.Block.ClearTxsModel() return c.bc.DB().BlockModel.UpdateBlockInTransact(tx, blockStates.Block) }) - if err != nil { return nil, err } @@ -311,3 +328,37 @@ func (c *Committer) computeCurrentBlockSize() int { } return blockSize } + +func (c *Committer) getLatestExecutedRequestId() (int64, error) { + + statuses := []int{ + tx.StatusExecuted, + tx.StatusPacked, + tx.StatusCommitted, + tx.StatusVerified, + } + + txTypes := []int64{ + types.TxTypeRegisterZns, + types.TxTypeDeposit, + types.TxTypeDepositNft, + types.TxTypeFullExit, + types.TxTypeFullExitNft, + } + + latestTx, err := c.bc.TxPoolModel.GetLatestTx(txTypes, statuses) + if err != nil && err != types.DbErrNotFound { + logx.Errorf("get latest executed tx failed: %v", err) + return -1, err + } else if err == types.DbErrNotFound { + return -1, nil + } + + p, err := c.bc.PriorityRequestModel.GetPriorityRequestsByL2TxHash(latestTx.TxHash) + if err != nil { + logx.Errorf("get priority request by txhash: %s failed: %v", latestTx.TxHash, err) + return -1, err + } + + return p.RequestId, nil +} diff --git a/service/committer/etc/config.yaml.example b/service/committer/etc/config.yaml.example index 4d8123317..bd08cf5b1 100644 --- a/service/committer/etc/config.yaml.example +++ b/service/committer/etc/config.yaml.example @@ -12,3 +12,4 @@ BlockConfig: TreeDB: Driver: memorydb + AssetTreeCacheSize: 512000 diff --git a/service/monitor/etc/config.yaml.example b/service/monitor/etc/config.yaml.example index ac27f5e8b..0ef798c93 100644 --- a/service/monitor/etc/config.yaml.example +++ b/service/monitor/etc/config.yaml.example @@ -20,4 +20,5 @@ LogConf: Level: info TreeDB: - Driver: memorydb \ No newline at end of file + Driver: memorydb + AssetTreeCacheSize: 512000 \ No newline at end of file diff --git a/service/monitor/monitor/monitor.go b/service/monitor/monitor/monitor.go index 91223e14b..08f21ecff 100644 --- a/service/monitor/monitor/monitor.go +++ b/service/monitor/monitor/monitor.go @@ -19,6 +19,7 @@ package monitor import ( "fmt" + "github.com/prometheus/client_golang/prometheus" "github.com/zeromicro/go-zero/core/logx" "gorm.io/driver/postgres" "gorm.io/gorm" @@ -30,12 +31,27 @@ import ( "github.com/bnb-chain/zkbnb/dao/l1rolluptx" "github.com/bnb-chain/zkbnb/dao/l1syncedblock" "github.com/bnb-chain/zkbnb/dao/priorityrequest" + "github.com/bnb-chain/zkbnb/dao/proof" "github.com/bnb-chain/zkbnb/dao/sysconfig" "github.com/bnb-chain/zkbnb/dao/tx" "github.com/bnb-chain/zkbnb/service/monitor/config" "github.com/bnb-chain/zkbnb/types" ) +var ( + priorityOperationMetric = prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "zkbnb", + Name: "priority_operation_insert", + Help: "Priority operation requestID metrics.", + }) + + priorityOperationHeightMetric = prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "zkbnb", + Name: "priority_operation_insert_height", + Help: "Priority operation height metrics.", + }) +) + type Monitor struct { Config config.Config @@ -50,6 +66,7 @@ type Monitor struct { TxPoolModel tx.TxPoolModel SysConfigModel sysconfig.SysConfigModel L1RollupTxModel l1rolluptx.L1RollupTxModel + ProofModel proof.ProofModel L2AssetModel asset.AssetModel PriorityRequestModel priorityrequest.PriorityRequestModel L1SyncedBlockModel l1syncedblock.L1SyncedBlockModel @@ -68,6 +85,7 @@ func NewMonitor(c config.Config) *Monitor { TxPoolModel: tx.NewTxPoolModel(db), BlockModel: block.NewBlockModel(db), L1RollupTxModel: l1rolluptx.NewL1RollupTxModel(db), + ProofModel: proof.NewProofModel(db), L1SyncedBlockModel: l1syncedblock.NewL1SyncedBlockModel(db), L2AssetModel: asset.NewAssetModel(db), SysConfigModel: sysconfig.NewSysConfigModel(db), @@ -104,6 +122,15 @@ func NewMonitor(c config.Config) *Monitor { monitor.governanceContractAddress = governanceAddressConfig.Value monitor.cli = bscRpcCli + if err := prometheus.Register(priorityOperationMetric); err != nil { + logx.Severef("fatal error, cannot register prometheus, err: %s", err.Error()) + panic(err) + } + if err := prometheus.Register(priorityOperationHeightMetric); err != nil { + logx.Severef("fatal error, cannot register prometheus, err: %s", err.Error()) + panic(err) + } + return monitor } diff --git a/service/monitor/monitor/monitor_generic_blocks.go b/service/monitor/monitor/monitor_generic_blocks.go index 81999bdc2..1a2d0eac0 100644 --- a/service/monitor/monitor/monitor_generic_blocks.go +++ b/service/monitor/monitor/monitor_generic_blocks.go @@ -32,9 +32,12 @@ import ( zkbnb "github.com/bnb-chain/zkbnb-eth-rpc/core" "github.com/bnb-chain/zkbnb-eth-rpc/rpc" "github.com/bnb-chain/zkbnb/dao/block" + "github.com/bnb-chain/zkbnb/dao/l1rolluptx" "github.com/bnb-chain/zkbnb/dao/l1syncedblock" "github.com/bnb-chain/zkbnb/dao/priorityrequest" + "github.com/bnb-chain/zkbnb/dao/proof" "github.com/bnb-chain/zkbnb/dao/tx" + types2 "github.com/bnb-chain/zkbnb/types" ) func (m *Monitor) MonitorGenericBlocks() (err error) { @@ -153,8 +156,30 @@ func (m *Monitor) MonitorGenericBlocks() (err error) { // get pending update blocks pendingUpdateBlocks := make([]*block.Block, 0, len(relatedBlocks)) + pendingUpdateCommittedBlocks := make(map[string]*block.Block, 0) + pendingUpdateVerifiedBlocks := make(map[string]*block.Block, 0) for _, pendingUpdateBlock := range relatedBlocks { pendingUpdateBlocks = append(pendingUpdateBlocks, pendingUpdateBlock) + if pendingUpdateBlock.CommittedTxHash != "" { + b, exist := pendingUpdateCommittedBlocks[pendingUpdateBlock.CommittedTxHash] + if exist { + if b.BlockHeight < pendingUpdateBlock.BlockHeight { + pendingUpdateCommittedBlocks[pendingUpdateBlock.CommittedTxHash] = pendingUpdateBlock + } + } else { + pendingUpdateCommittedBlocks[pendingUpdateBlock.CommittedTxHash] = pendingUpdateBlock + } + } + if pendingUpdateBlock.VerifiedTxHash != "" { + b, exist := pendingUpdateVerifiedBlocks[pendingUpdateBlock.VerifiedTxHash] + if exist { + if b.BlockHeight < pendingUpdateBlock.BlockHeight { + pendingUpdateVerifiedBlocks[pendingUpdateBlock.VerifiedTxHash] = pendingUpdateBlock + } + } else { + pendingUpdateVerifiedBlocks[pendingUpdateBlock.VerifiedTxHash] = pendingUpdateBlock + } + } } //update db @@ -174,6 +199,56 @@ func (m *Monitor) MonitorGenericBlocks() (err error) { if err != nil { return err } + // update l1 rollup tx status + // maybe already updated by sender, or may be deleted by sender because of timeout + for _, val := range pendingUpdateCommittedBlocks { + _, err = m.L1RollupTxModel.GetL1RollupTxsByHash(val.CommittedTxHash) + if err == types2.DbErrNotFound { + logx.Info("monitor create commit rollup tx ", val.CommittedTxHash, val.BlockHeight) + // the rollup tx is deleted by sender + // so we insert it here + err = m.L1RollupTxModel.CreateL1RollupTx(&l1rolluptx.L1RollupTx{ + L1TxHash: val.CommittedTxHash, + TxStatus: l1rolluptx.StatusHandled, + TxType: l1rolluptx.TxTypeCommit, + L2BlockHeight: val.BlockHeight, + }) + if err != nil { + return err + } + } else if err != nil { + return err + } + } + pendingUpdateProofStatus := make(map[int64]int) + for _, val := range pendingUpdateVerifiedBlocks { + _, err = m.L1RollupTxModel.GetL1RollupTxsByHash(val.VerifiedTxHash) + if err == types2.DbErrNotFound { + logx.Info("monitor create verify rollup tx ", val.VerifiedTxHash, val.BlockHeight) + // the rollup tx is deleted by sender + // so we insert it here + err = m.L1RollupTxModel.CreateL1RollupTx(&l1rolluptx.L1RollupTx{ + L1TxHash: val.VerifiedTxHash, + TxStatus: l1rolluptx.StatusHandled, + TxType: l1rolluptx.TxTypeVerifyAndExecute, + L2BlockHeight: val.BlockHeight, + }) + if err != nil { + return err + } + } else if err != nil { + return err + } + pendingUpdateProofStatus[val.BlockHeight] = proof.Confirmed + } + // update proof status + if len(pendingUpdateProofStatus) != 0 { + err = m.ProofModel.UpdateProofsInTransact(tx, pendingUpdateProofStatus) + if err != nil { + return err + } + } + //update tx status err = m.TxModel.UpdateTxsStatusInTransact(tx, relatedBlockTxStatus) return err diff --git a/service/monitor/monitor/monitor_governance_blocks.go b/service/monitor/monitor/monitor_governance_blocks.go index f66246c93..df083576b 100644 --- a/service/monitor/monitor/monitor_governance_blocks.go +++ b/service/monitor/monitor/monitor_governance_blocks.go @@ -210,7 +210,7 @@ func (m *Monitor) MonitorGovernanceBlocks() (err error) { return err } syncedBlock := &l1syncedblock.L1SyncedBlock{ - L1BlockHeight: int64(endHeight), + L1BlockHeight: endHeight, BlockInfo: string(eventInfosBytes), Type: l1syncedblock.TypeGovernance, } diff --git a/service/monitor/monitor/monitor_priority_requests.go b/service/monitor/monitor/monitor_priority_requests.go index af8ed66e5..d1d8aef80 100644 --- a/service/monitor/monitor/monitor_priority_requests.go +++ b/service/monitor/monitor/monitor_priority_requests.go @@ -64,7 +64,6 @@ func (m *Monitor) MonitorPriorityRequests() error { GasFeeAssetId: types.NilAssetId, GasFee: types.NilAssetAmount, - PairIndex: types.NilPairIndex, NftIndex: types.NilNftIndex, CollectionId: types.NilCollectionNonce, AssetId: types.NilAssetId, @@ -74,6 +73,9 @@ func (m *Monitor) MonitorPriorityRequests() error { BlockHeight: types.NilBlockHeight, TxStatus: tx.StatusPending, } + + request.L2TxHash = txHash + // handle request based on request type var txInfoBytes []byte switch request.TxType { @@ -90,30 +92,6 @@ func (m *Monitor) MonitorPriorityRequests() error { return err } - case TxTypeCreatePair: - txInfo, err := chain.ParseCreatePairPubData(common.FromHex(request.Pubdata)) - if err != nil { - return fmt.Errorf("unable to parse registerZNS pub data: %v", err) - } - - poolTx.TxType = int64(txInfo.TxType) - txInfoBytes, err = json.Marshal(txInfo) - if err != nil { - return fmt.Errorf("unable to serialize request info : %v", err) - } - - case TxTypeUpdatePairRate: - txInfo, err := chain.ParseUpdatePairRatePubData(common.FromHex(request.Pubdata)) - if err != nil { - return fmt.Errorf("unable to parse update pair rate pub data: %v", err) - } - - poolTx.TxType = int64(txInfo.TxType) - txInfoBytes, err = json.Marshal(txInfo) - if err != nil { - return fmt.Errorf("unable to serialize request info : %v", err) - } - case TxTypeDeposit: txInfo, err := chain.ParseDepositPubData(common.FromHex(request.Pubdata)) if err != nil { @@ -183,11 +161,16 @@ func (m *Monitor) MonitorPriorityRequests() error { if err != nil { return err } - return nil }) if err != nil { return fmt.Errorf("unable to create pool tx and update priority requests, error: %v", err) } + + for _, request := range pendingRequests { + priorityOperationMetric.Set(float64(request.RequestId)) + priorityOperationHeightMetric.Set(float64(request.L1BlockHeight)) + } + return nil } diff --git a/service/monitor/monitor/types.go b/service/monitor/monitor/types.go index d8744df17..592f375a2 100644 --- a/service/monitor/monitor/types.go +++ b/service/monitor/monitor/types.go @@ -51,13 +51,11 @@ const ( PendingStatus = priorityrequest.PendingStatus - TxTypeRegisterZns = types.TxTypeRegisterZns - TxTypeCreatePair = types.TxTypeCreatePair - TxTypeUpdatePairRate = types.TxTypeUpdatePairRate - TxTypeDeposit = types.TxTypeDeposit - TxTypeDepositNft = types.TxTypeDepositNft - TxTypeFullExit = types.TxTypeFullExit - TxTypeFullExitNft = types.TxTypeFullExitNft + TxTypeRegisterZns = types.TxTypeRegisterZns + TxTypeDeposit = types.TxTypeDeposit + TxTypeDepositNft = types.TxTypeDepositNft + TxTypeFullExit = types.TxTypeFullExit + TxTypeFullExitNft = types.TxTypeFullExitNft ) var ( diff --git a/service/prover/prover/prover.go b/service/prover/prover/prover.go index 11d13f337..d250719b4 100644 --- a/service/prover/prover/prover.go +++ b/service/prover/prover/prover.go @@ -82,6 +82,10 @@ func NewProver(c config.Config) *Prover { for i := 0; i < blockConstraints.TxsCount; i++ { blockConstraints.Txs[i] = circuit.GetZeroTxConstraint() } + blockConstraints.GasAssetIds = types.GasAssets[:] + blockConstraints.GasAccountIndex = types.GasAccount + blockConstraints.Gas = circuit.GetZeroGasConstraints(types.GasAssets[:]) + logx.Infof("start compile block size %d blockConstraints", blockConstraints.TxsCount) prover.R1cs[i], err = frontend.Compile(ecc.BN254, r1cs.NewBuilder, &blockConstraints, frontend.IgnoreUnconstrainedInputs()) if err != nil { diff --git a/service/prover/verifier_parse.py b/service/prover/verifier_parse.py index 67d817f56..e220a1a7e 100644 --- a/service/prover/verifier_parse.py +++ b/service/prover/verifier_parse.py @@ -43,7 +43,7 @@ def find_and_delete_func(func_name, lines): lines = f.readlines() for nu in range(len(lines)): if lines[nu].count("function verifyingKey()"): - for i in range(8): + for i in range(6): tmp = lines[nu + 1 + i].split("uint256") for j in range(len(tmp) - 1): vks.append("".join([x for x in tmp[j+1] if x.isdigit()])) @@ -78,8 +78,8 @@ def find_and_delete_func(func_name, lines): new_lines.append(" if (block_size == " + src_block_sizes[i] + ") {\n") else: new_lines.append(" } else if (block_size == " + src_block_sizes[i] + ") {\n") - new_lines.append(" gammaABC = new uint256[](8);\n") - for j in range(8): + new_lines.append(" gammaABC = new uint256[](4);\n") + for j in range(4): new_lines.append(" gammaABC[" + str(j) + "] = " + all_vks[i][14 + j] + ";\n") new_lines.append(" return gammaABC;\n") new_lines.append(" } else {\n") @@ -101,4 +101,4 @@ def find_and_delete_func(func_name, lines): print(lines[nu + 2 + i]) """ with open(dest_filename, "w") as f: - f.writelines(update_lines) + f.writelines(update_lines) \ No newline at end of file diff --git a/service/sender/sender/sender.go b/service/sender/sender/sender.go index 0907c507b..dd76bb42e 100644 --- a/service/sender/sender/sender.go +++ b/service/sender/sender/sender.go @@ -172,7 +172,7 @@ func (s *Sender) CommitBlocks() (err error) { gasPrice, s.config.ChainConfig.GasLimit) if err != nil { - return fmt.Errorf("failed to send commit tx, errL %v", err) + return fmt.Errorf("failed to send commit tx, errL %v:%s", err, txHash) } newRollupTx := &l1rolluptx.L1RollupTx{ L1TxHash: txHash, @@ -184,7 +184,7 @@ func (s *Sender) CommitBlocks() (err error) { if err != nil { return fmt.Errorf("failed to create tx in database, err: %v", err) } - logx.Infof("new blocks have been committed(height): %v", newRollupTx.L2BlockHeight) + logx.Infof("new blocks have been committed(height): %v:%s", newRollupTx.L2BlockHeight, newRollupTx.L1TxHash) return nil } @@ -220,6 +220,10 @@ func (s *Sender) UpdateSentTxs() (err error) { continue } if receipt.Status == 0 { + // Should direct mark tx deleted + logx.Infof("delete timeout l1 rollup tx, tx_hash=%s", pendingTx.L1TxHash) + //nolint:errcheck + s.l1RollupTxModel.DeleteL1RollupTx(pendingTx) // It is critical to have any failed transactions panic(fmt.Sprintf("unexpected failed tx: %v", txHash)) } @@ -317,6 +321,12 @@ func (s *Sender) VerifyAndExecuteBlocks() (err error) { if len(blockProofs) != len(blocks) { return errors.New("related proofs not ready") } + // add sanity check + for i := range blockProofs { + if blockProofs[i].BlockNumber != blocks[i].BlockHeight { + return errors.New("proof number not match") + } + } var proofs []*big.Int for _, bProof := range blockProofs { var proofInfo *prove.FormattedProof @@ -345,7 +355,7 @@ func (s *Sender) VerifyAndExecuteBlocks() (err error) { txHash, err := zkbnb.VerifyAndExecuteBlocks(cli, authCli, zkbnbInstance, pendingVerifyAndExecuteBlocks, proofs, gasPrice, s.config.ChainConfig.GasLimit) if err != nil { - return fmt.Errorf("failed to send verify tx: %v", err) + return fmt.Errorf("failed to send verify tx: %v:%s", err, txHash) } newRollupTx := &l1rolluptx.L1RollupTx{ @@ -358,7 +368,7 @@ func (s *Sender) VerifyAndExecuteBlocks() (err error) { if err != nil { return fmt.Errorf(fmt.Sprintf("failed to create rollup tx in db %v", err)) } - logx.Infof("new blocks have been verified and executed(height): %d", newRollupTx.L2BlockHeight) + logx.Infof("new blocks have been verified and executed(height): %d:%s", newRollupTx.L2BlockHeight, newRollupTx.L1TxHash) return nil } diff --git a/service/witness/config/config.go b/service/witness/config/config.go index b2dbc2983..dfcef2a5f 100644 --- a/service/witness/config/config.go +++ b/service/witness/config/config.go @@ -15,7 +15,8 @@ type Config struct { //nolint:staticcheck LevelDBOption tree.LevelDBOption `json:",optional"` //nolint:staticcheck - RedisDBOption tree.RedisDBOption `json:",optional"` + RedisDBOption tree.RedisDBOption `json:",optional"` + AssetTreeCacheSize int } LogConf logx.LogConf } diff --git a/service/witness/etc/config.yaml.example b/service/witness/etc/config.yaml.example index d776f5740..a3e64efb6 100644 --- a/service/witness/etc/config.yaml.example +++ b/service/witness/etc/config.yaml.example @@ -5,6 +5,7 @@ Postgres: TreeDB: Driver: memorydb + AssetTreeCacheSize: 512000 LogConf: ServiceName: witness diff --git a/service/witness/witness/witness.go b/service/witness/witness/witness.go index 3f2e8eb45..e770e55d2 100644 --- a/service/witness/witness/witness.go +++ b/service/witness/witness/witness.go @@ -18,7 +18,6 @@ import ( "github.com/bnb-chain/zkbnb/dao/account" "github.com/bnb-chain/zkbnb/dao/block" "github.com/bnb-chain/zkbnb/dao/blockwitness" - "github.com/bnb-chain/zkbnb/dao/liquidity" "github.com/bnb-chain/zkbnb/dao/nft" "github.com/bnb-chain/zkbnb/dao/proof" "github.com/bnb-chain/zkbnb/service/witness/config" @@ -40,22 +39,20 @@ type Witness struct { helper *utils.WitnessHelper // Trees - treeCtx *tree.Context - accountTree smt.SparseMerkleTree - assetTrees []smt.SparseMerkleTree - liquidityTree smt.SparseMerkleTree - nftTree smt.SparseMerkleTree - taskPool *ants.Pool + treeCtx *tree.Context + accountTree smt.SparseMerkleTree + assetTrees *tree.AssetTreeCache + nftTree smt.SparseMerkleTree + taskPool *ants.Pool // The data access object - db *gorm.DB - blockModel block.BlockModel - accountModel account.AccountModel - accountHistoryModel account.AccountHistoryModel - liquidityHistoryModel liquidity.LiquidityHistoryModel - nftHistoryModel nft.L2NftHistoryModel - proofModel proof.ProofModel - blockWitnessModel blockwitness.BlockWitnessModel + db *gorm.DB + blockModel block.BlockModel + accountModel account.AccountModel + accountHistoryModel account.AccountHistoryModel + nftHistoryModel nft.L2NftHistoryModel + proofModel proof.ProofModel + blockWitnessModel blockwitness.BlockWitnessModel } func NewWitness(c config.Config) (*Witness, error) { @@ -66,15 +63,14 @@ func NewWitness(c config.Config) (*Witness, error) { } w := &Witness{ - config: c, - db: db, - blockModel: block.NewBlockModel(db), - blockWitnessModel: blockwitness.NewBlockWitnessModel(db), - accountModel: account.NewAccountModel(db), - accountHistoryModel: account.NewAccountHistoryModel(db), - liquidityHistoryModel: liquidity.NewLiquidityHistoryModel(db), - nftHistoryModel: nft.NewL2NftHistoryModel(db), - proofModel: proof.NewProofModel(db), + config: c, + db: db, + blockModel: block.NewBlockModel(db), + blockWitnessModel: blockwitness.NewBlockWitnessModel(db), + accountModel: account.NewAccountModel(db), + accountHistoryModel: account.NewAccountHistoryModel(db), + nftHistoryModel: nft.NewL2NftHistoryModel(db), + proofModel: proof.NewProofModel(db), } err = w.initState() return w, err @@ -110,17 +106,13 @@ func (w *Witness) initState() error { w.accountHistoryModel, witnessHeight, treeCtx, + w.config.TreeDB.AssetTreeCacheSize, ) // the blockHeight depends on the proof start position if err != nil { return fmt.Errorf("initMerkleTree error: %v", err) } - w.liquidityTree, err = tree.InitLiquidityTree(w.liquidityHistoryModel, witnessHeight, - treeCtx) - if err != nil { - return fmt.Errorf("initLiquidityTree error: %v", err) - } w.nftTree, err = tree.InitNftTree(w.nftHistoryModel, witnessHeight, treeCtx) if err != nil { @@ -131,7 +123,7 @@ func (w *Witness) initState() error { return err } w.taskPool = taskPool - w.helper = utils.NewWitnessHelper(w.treeCtx, w.accountTree, w.liquidityTree, w.nftTree, &w.assetTrees, w.accountModel) + w.helper = utils.NewWitnessHelper(w.treeCtx, w.accountTree, w.nftTree, w.assetTrees, w.accountModel, w.accountHistoryModel) return nil } @@ -164,7 +156,7 @@ func (w *Witness) GenerateBlockWitness() (err error) { return fmt.Errorf("failed to construct block witness, block:%d, err: %v", block.BlockHeight, err) } // Step2: commit trees for witness - err = tree.CommitTrees(w.taskPool, uint64(latestVerifiedBlockNr), w.accountTree, &w.assetTrees, w.liquidityTree, w.nftTree) + err = tree.CommitTrees(w.taskPool, uint64(latestVerifiedBlockNr), w.accountTree, w.assetTrees, w.nftTree) if err != nil { return fmt.Errorf("unable to commit trees after txs is executed, block:%d, error: %v", block.BlockHeight, err) } @@ -172,7 +164,7 @@ func (w *Witness) GenerateBlockWitness() (err error) { err = w.blockWitnessModel.CreateBlockWitness(blockWitness) if err != nil { // rollback trees - rollBackErr := tree.RollBackTrees(w.taskPool, uint64(block.BlockHeight)-1, w.accountTree, &w.assetTrees, w.liquidityTree, w.nftTree) + rollBackErr := tree.RollBackTrees(w.taskPool, uint64(block.BlockHeight)-1, w.accountTree, w.assetTrees, w.nftTree) if rollBackErr != nil { logx.Errorf("unable to rollback trees %v", rollBackErr) } @@ -251,6 +243,10 @@ func (w *Witness) constructBlockWitness(block *block.Block, latestVerifiedBlockN var oldStateRoot, newStateRoot []byte txsWitness := make([]*utils.TxWitness, 0, block.BlockSize) // scan each transaction + err := w.helper.ResetCache(block.BlockHeight) + if err != nil { + return nil, err + } for idx, tx := range block.Txs { txWitness, err := w.helper.ConstructTxWitness(tx, uint64(latestVerifiedBlockNr)) if err != nil { @@ -269,8 +265,15 @@ func (w *Witness) constructBlockWitness(block *block.Block, latestVerifiedBlockN emptyTxCount := int(block.BlockSize) - len(block.Txs) for i := 0; i < emptyTxCount; i++ { - txsWitness = append(txsWitness, circuit.EmptyTx()) + txsWitness = append(txsWitness, circuit.EmptyTx(newStateRoot)) } + + gasWitness, err := w.helper.ConstructGasWitness(block) + if err != nil { + return nil, err + } + + newStateRoot = tree.ComputeStateRootHash(w.accountTree.Root(), w.nftTree.Root()) if common.Bytes2Hex(newStateRoot) != block.StateRoot { return nil, errors.New("state root doesn't match") } @@ -282,6 +285,7 @@ func (w *Witness) constructBlockWitness(block *block.Block, latestVerifiedBlockN NewStateRoot: newStateRoot, BlockCommitment: common.FromHex(block.BlockCommitment), Txs: txsWitness, + Gas: gasWitness, } bz, err := json.Marshal(b) if err != nil { diff --git a/tools/dbinitializer/main.go b/tools/dbinitializer/main.go index 518390db6..4c0568dfc 100644 --- a/tools/dbinitializer/main.go +++ b/tools/dbinitializer/main.go @@ -34,7 +34,6 @@ import ( "github.com/bnb-chain/zkbnb/dao/compressedblock" "github.com/bnb-chain/zkbnb/dao/l1rolluptx" "github.com/bnb-chain/zkbnb/dao/l1syncedblock" - "github.com/bnb-chain/zkbnb/dao/liquidity" "github.com/bnb-chain/zkbnb/dao/nft" "github.com/bnb-chain/zkbnb/dao/priorityrequest" "github.com/bnb-chain/zkbnb/dao/proof" @@ -59,24 +58,22 @@ type contractAddr struct { } type dao struct { - sysConfigModel sysconfig.SysConfigModel - accountModel account.AccountModel - accountHistoryModel account.AccountHistoryModel - assetModel asset.AssetModel - txPoolModel tx.TxPoolModel - txDetailModel tx.TxDetailModel - txModel tx.TxModel - blockModel block.BlockModel - compressedBlockModel compressedblock.CompressedBlockModel - blockWitnessModel blockwitness.BlockWitnessModel - proofModel proof.ProofModel - l1SyncedBlockModel l1syncedblock.L1SyncedBlockModel - priorityRequestModel priorityrequest.PriorityRequestModel - l1RollupTModel l1rolluptx.L1RollupTxModel - liquidityModel liquidity.LiquidityModel - liquidityHistoryModel liquidity.LiquidityHistoryModel - nftModel nft.L2NftModel - nftHistoryModel nft.L2NftHistoryModel + sysConfigModel sysconfig.SysConfigModel + accountModel account.AccountModel + accountHistoryModel account.AccountHistoryModel + assetModel asset.AssetModel + txPoolModel tx.TxPoolModel + txDetailModel tx.TxDetailModel + txModel tx.TxModel + blockModel block.BlockModel + compressedBlockModel compressedblock.CompressedBlockModel + blockWitnessModel blockwitness.BlockWitnessModel + proofModel proof.ProofModel + l1SyncedBlockModel l1syncedblock.L1SyncedBlockModel + priorityRequestModel priorityrequest.PriorityRequestModel + l1RollupTModel l1rolluptx.L1RollupTxModel + nftModel nft.L2NftModel + nftHistoryModel nft.L2NftHistoryModel } func Initialize( @@ -95,24 +92,22 @@ func Initialize( logx.Infof("init configs: %s", string(unmarshal)) dao := &dao{ - sysConfigModel: sysconfig.NewSysConfigModel(db), - accountModel: account.NewAccountModel(db), - accountHistoryModel: account.NewAccountHistoryModel(db), - assetModel: asset.NewAssetModel(db), - txPoolModel: tx.NewTxPoolModel(db), - txDetailModel: tx.NewTxDetailModel(db), - txModel: tx.NewTxModel(db), - blockModel: block.NewBlockModel(db), - compressedBlockModel: compressedblock.NewCompressedBlockModel(db), - blockWitnessModel: blockwitness.NewBlockWitnessModel(db), - proofModel: proof.NewProofModel(db), - l1SyncedBlockModel: l1syncedblock.NewL1SyncedBlockModel(db), - priorityRequestModel: priorityrequest.NewPriorityRequestModel(db), - l1RollupTModel: l1rolluptx.NewL1RollupTxModel(db), - liquidityModel: liquidity.NewLiquidityModel(db), - liquidityHistoryModel: liquidity.NewLiquidityHistoryModel(db), - nftModel: nft.NewL2NftModel(db), - nftHistoryModel: nft.NewL2NftHistoryModel(db), + sysConfigModel: sysconfig.NewSysConfigModel(db), + accountModel: account.NewAccountModel(db), + accountHistoryModel: account.NewAccountHistoryModel(db), + assetModel: asset.NewAssetModel(db), + txPoolModel: tx.NewTxPoolModel(db), + txDetailModel: tx.NewTxDetailModel(db), + txModel: tx.NewTxModel(db), + blockModel: block.NewBlockModel(db), + compressedBlockModel: compressedblock.NewCompressedBlockModel(db), + blockWitnessModel: blockwitness.NewBlockWitnessModel(db), + proofModel: proof.NewProofModel(db), + l1SyncedBlockModel: l1syncedblock.NewL1SyncedBlockModel(db), + priorityRequestModel: priorityrequest.NewPriorityRequestModel(db), + l1RollupTModel: l1rolluptx.NewL1RollupTxModel(db), + nftModel: nft.NewL2NftModel(db), + nftHistoryModel: nft.NewL2NftHistoryModel(db), } dropTables(dao) @@ -126,9 +121,6 @@ func initSysConfig(svrConf *contractAddr, bscTestNetworkRPC, localTestNetworkRPC // to config gas for different transaction types, need to be evaluated and tune these values bnbGasFee := make(map[int]int64) bnbGasFee[types.TxTypeTransfer] = 10000000000000 - bnbGasFee[types.TxTypeSwap] = 12000000000000 - bnbGasFee[types.TxTypeAddLiquidity] = 12000000000000 - bnbGasFee[types.TxTypeRemoveLiquidity] = 12000000000000 bnbGasFee[types.TxTypeWithdraw] = 20000000000000 bnbGasFee[types.TxTypeCreateCollection] = 10000000000000 bnbGasFee[types.TxTypeMintNft] = 10000000000000 @@ -228,8 +220,6 @@ func dropTables(dao *dao) { assert.Nil(nil, dao.l1SyncedBlockModel.DropL1SyncedBlockTable()) assert.Nil(nil, dao.priorityRequestModel.DropPriorityRequestTable()) assert.Nil(nil, dao.l1RollupTModel.DropL1RollupTxTable()) - assert.Nil(nil, dao.liquidityModel.DropLiquidityTable()) - assert.Nil(nil, dao.liquidityHistoryModel.DropLiquidityHistoryTable()) assert.Nil(nil, dao.nftModel.DropL2NftTable()) assert.Nil(nil, dao.nftHistoryModel.DropL2NftHistoryTable()) } @@ -249,8 +239,6 @@ func initTable(dao *dao, svrConf *contractAddr, bscTestNetworkRPC, localTestNetw assert.Nil(nil, dao.l1SyncedBlockModel.CreateL1SyncedBlockTable()) assert.Nil(nil, dao.priorityRequestModel.CreatePriorityRequestTable()) assert.Nil(nil, dao.l1RollupTModel.CreateL1RollupTxTable()) - assert.Nil(nil, dao.liquidityModel.CreateLiquidityTable()) - assert.Nil(nil, dao.liquidityHistoryModel.CreateLiquidityHistoryTable()) assert.Nil(nil, dao.nftModel.CreateL2NftTable()) assert.Nil(nil, dao.nftHistoryModel.CreateL2NftHistoryTable()) rowsAffected, err := dao.assetModel.CreateAssets(initAssetsInfo()) diff --git a/tools/recovery/etc/config.yaml.example b/tools/recovery/etc/config.yaml.example index d05250060..c71f0d629 100644 --- a/tools/recovery/etc/config.yaml.example +++ b/tools/recovery/etc/config.yaml.example @@ -7,4 +7,5 @@ CacheRedis: Type: node TreeDB: - Driver: memorydb \ No newline at end of file + Driver: memorydb + AssetTreeCacheSize: 512000 \ No newline at end of file diff --git a/tools/recovery/internal/config/config.go b/tools/recovery/internal/config/config.go index bd6c7c342..64f646719 100644 --- a/tools/recovery/internal/config/config.go +++ b/tools/recovery/internal/config/config.go @@ -17,7 +17,8 @@ type Config struct { //nolint:staticcheck LevelDBOption tree.LevelDBOption `json:",optional"` //nolint:staticcheck - RedisDBOption tree.RedisDBOption `json:",optional"` + RedisDBOption tree.RedisDBOption `json:",optional"` + AssetTreeCacheSize int } LogConf logx.LogConf } diff --git a/tools/recovery/internal/svc/servicecontext.go b/tools/recovery/internal/svc/servicecontext.go index 9dfa7e934..23a65c705 100644 --- a/tools/recovery/internal/svc/servicecontext.go +++ b/tools/recovery/internal/svc/servicecontext.go @@ -6,7 +6,6 @@ import ( "gorm.io/gorm" "github.com/bnb-chain/zkbnb/dao/account" - "github.com/bnb-chain/zkbnb/dao/liquidity" "github.com/bnb-chain/zkbnb/dao/nft" "github.com/bnb-chain/zkbnb/tools/recovery/internal/config" ) @@ -14,10 +13,9 @@ import ( type ServiceContext struct { Config config.Config - AccountModel account.AccountModel - AccountHistoryModel account.AccountHistoryModel - LiquidityHistoryModel liquidity.LiquidityHistoryModel - NftHistoryModel nft.L2NftHistoryModel + AccountModel account.AccountModel + AccountHistoryModel account.AccountHistoryModel + NftHistoryModel nft.L2NftHistoryModel } func NewServiceContext(c config.Config) *ServiceContext { @@ -26,10 +24,9 @@ func NewServiceContext(c config.Config) *ServiceContext { logx.Errorf("gorm connect db error, err = %s", err.Error()) } return &ServiceContext{ - Config: c, - AccountModel: account.NewAccountModel(db), - AccountHistoryModel: account.NewAccountHistoryModel(db), - LiquidityHistoryModel: liquidity.NewLiquidityHistoryModel(db), - NftHistoryModel: nft.NewL2NftHistoryModel(db), + Config: c, + AccountModel: account.NewAccountModel(db), + AccountHistoryModel: account.NewAccountHistoryModel(db), + NftHistoryModel: nft.NewL2NftHistoryModel(db), } } diff --git a/tools/recovery/recovery.go b/tools/recovery/recovery.go index 6a2a3fc2b..776cb4c0c 100644 --- a/tools/recovery/recovery.go +++ b/tools/recovery/recovery.go @@ -48,20 +48,12 @@ func RecoveryTreeDB( ctx.AccountHistoryModel, blockHeight, treeCtx, + c.TreeDB.AssetTreeCacheSize, ) if err != nil { logx.Error("InitMerkleTree error:", err) return } - // dbinitializer liquidityTree - _, err = tree.InitLiquidityTree( - ctx.LiquidityHistoryModel, - blockHeight, - treeCtx) - if err != nil { - logx.Errorf("InitLiquidityTree error: %s", err.Error()) - return - } // dbinitializer nftTree _, err = tree.InitNftTree( ctx.NftHistoryModel, diff --git a/tree/account_tree.go b/tree/account_tree.go index d8cfea3e2..855ce7166 100644 --- a/tree/account_tree.go +++ b/tree/account_tree.go @@ -40,8 +40,9 @@ func InitAccountTree( accountHistoryModel account.AccountHistoryModel, blockHeight int64, ctx *Context, + assetCacheSize int, ) ( - accountTree bsmt.SparseMerkleTree, accountAssetTrees []bsmt.SparseMerkleTree, err error, + accountTree bsmt.SparseMerkleTree, accountAssetTrees *AssetTreeCache, err error, ) { accountNums, err := accountHistoryModel.GetValidAccountCount(blockHeight) if err != nil { @@ -52,17 +53,16 @@ func InitAccountTree( opts := ctx.Options(blockHeight) // init account state trees - accountAssetTrees = make([]bsmt.SparseMerkleTree, accountNums) - for index := int64(0); index < accountNums; index++ { - // create account assets tree - accountAssetTrees[index], err = bsmt.NewBASSparseMerkleTree(bsmt.NewHasher(mimc.NewMiMC()), + accountAssetTrees = NewLazyTreeCache(assetCacheSize, accountNums-1, blockHeight, func(index, block int64) bsmt.SparseMerkleTree { + tree, err := bsmt.NewBASSparseMerkleTree(bsmt.NewHasher(mimc.NewMiMC()), SetNamespace(ctx, accountAssetNamespace(index)), AssetTreeHeight, NilAccountAssetNodeHash, - opts...) + ctx.Options(block)...) if err != nil { logx.Errorf("unable to create new tree by assets: %s", err.Error()) - return nil, nil, err + panic(err.Error()) } - } + return tree + }) accountTree, err = bsmt.NewBASSparseMerkleTree(bsmt.NewHasher(mimc.NewMiMC()), SetNamespace(ctx, AccountPrefix), AccountTreeHeight, NilAccountNodeHash, opts...) @@ -86,8 +86,8 @@ func InitAccountTree( } } - for i := range accountAssetTrees { - _, err := accountAssetTrees[i].Commit(nil) + for i := int64(0); i < accountNums; i++ { + _, err := accountAssetTrees.Get(i).Commit(nil) if err != nil { logx.Errorf("unable to set asset to tree: %s", err.Error()) return nil, nil, err @@ -112,10 +112,11 @@ func InitAccountTree( } } - for i := range accountAssetTrees { - if accountAssetTrees[i].LatestVersion() > bsmt.Version(blockHeight) && !accountAssetTrees[i].IsEmpty() { - logx.Infof("asset tree %d version [%d] is higher than block, rollback to %d", i, accountAssetTrees[i].LatestVersion(), blockHeight) - err := accountAssetTrees[i].Rollback(bsmt.Version(blockHeight)) + for i := int64(0); i < accountNums; i++ { + asset := accountAssetTrees.Get(i) + if asset.LatestVersion() > bsmt.Version(blockHeight) && !asset.IsEmpty() { + logx.Infof("asset tree %d version [%d] is higher than block, rollback to %d", i, asset.LatestVersion(), blockHeight) + err := asset.Rollback(bsmt.Version(blockHeight)) if err != nil { logx.Errorf("unable to rollback asset [%d] tree: %s, version: %d", i, err.Error(), blockHeight) return nil, nil, err @@ -132,7 +133,7 @@ func reloadAccountTreeFromRDB( blockHeight int64, offset, limit int, accountTree bsmt.SparseMerkleTree, - accountAssetTrees []bsmt.SparseMerkleTree, + accountAssetTrees *AssetTreeCache, ) error { _, accountHistories, err := accountHistoryModel.GetValidAccounts(blockHeight, limit, offset) @@ -190,14 +191,13 @@ func reloadAccountTreeFromRDB( for assetId, assetInfo := range accountInfo.AssetInfo { hashVal, err := AssetToNode( assetInfo.Balance.String(), - assetInfo.LpAmount.String(), assetInfo.OfferCanceledOrFinalized.String(), ) if err != nil { logx.Errorf("unable to convert asset to node: %s", err.Error()) return err } - err = accountAssetTrees[accountIndex].Set(uint64(assetId), hashVal) + err = accountAssetTrees.Get(accountIndex).Set(uint64(assetId), hashVal) if err != nil { logx.Errorf("unable to set asset to tree: %s", err.Error()) return err @@ -208,7 +208,7 @@ func reloadAccountTreeFromRDB( accountInfoMap[accountIndex].PublicKey, accountInfoMap[accountIndex].Nonce, accountInfoMap[accountIndex].CollectionNonce, - accountAssetTrees[accountIndex].Root(), + accountAssetTrees.Get(accountIndex).Root(), ) if err != nil { logx.Errorf("unable to convert account to node: %s", err.Error()) @@ -224,8 +224,8 @@ func reloadAccountTreeFromRDB( return nil } -func AssetToNode(balance string, lpAmount string, offerCanceledOrFinalized string) (hashVal []byte, err error) { - hashVal, err = ComputeAccountAssetLeafHash(balance, lpAmount, offerCanceledOrFinalized) +func AssetToNode(balance string, offerCanceledOrFinalized string) (hashVal []byte, err error) { + hashVal, err = ComputeAccountAssetLeafHash(balance, offerCanceledOrFinalized) if err != nil { logx.Errorf("unable to compute asset leaf hash: %s", err.Error()) return nil, err @@ -255,18 +255,6 @@ func AccountToNode( return hashVal, nil } -func NewEmptyAccountAssetTree( - ctx *Context, - index int64, - blockHeight uint64, -) (tree bsmt.SparseMerkleTree, err error) { - return bsmt.NewBASSparseMerkleTree( - bsmt.NewHasher(mimc.NewMiMC()), - SetNamespace(ctx, accountAssetNamespace(index)), - AssetTreeHeight, NilAccountAssetNodeHash, - ctx.Options(int64(blockHeight))...) -} - func NewMemAccountAssetTree() (tree bsmt.SparseMerkleTree, err error) { return bsmt.NewBASSparseMerkleTree(bsmt.NewHasher(mimc.NewMiMC()), memory.NewMemoryDB(), AssetTreeHeight, NilAccountAssetNodeHash) diff --git a/tree/asset_tree_cache.go b/tree/asset_tree_cache.go new file mode 100644 index 000000000..22b735200 --- /dev/null +++ b/tree/asset_tree_cache.go @@ -0,0 +1,94 @@ +package tree + +import ( + "sync" + + lru "github.com/hashicorp/golang-lru" + + bsmt "github.com/bnb-chain/zkbnb-smt" +) + +// Lazy init cache for asset trees +type AssetTreeCache struct { + initFunction func(index, block int64) bsmt.SparseMerkleTree + nextAccountNumber int64 + blockNumber int64 + mainLock sync.RWMutex + changes map[int64]bool + changesLock sync.RWMutex + treeCache *lru.Cache +} + +// Creates new AssetTreeCache +// maxSize defines the maximum size of currently initialized trees +// accountNumber defines the number of accounts to create/or next index for new account +func NewLazyTreeCache(maxSize int, accountNumber int64, blockNumber int64, f func(index, block int64) bsmt.SparseMerkleTree) *AssetTreeCache { + cache := AssetTreeCache{initFunction: f, nextAccountNumber: accountNumber, blockNumber: blockNumber, changes: make(map[int64]bool, maxSize*10)} + cache.treeCache, _ = lru.NewWithEvict(maxSize, cache.onDelete) + return &cache +} + +// Updates current cache with new block number and with latest account index +func (c *AssetTreeCache) UpdateCache(accountNumber, latestBlock int64) { + c.mainLock.Lock() + if c.nextAccountNumber < accountNumber { + c.nextAccountNumber = accountNumber + } + if c.blockNumber < latestBlock { + c.blockNumber = latestBlock + } + c.mainLock.Unlock() +} + +// Returns index of next account +func (c *AssetTreeCache) GetNextAccountIndex() int64 { + c.mainLock.RLock() + defer c.mainLock.RUnlock() + return c.nextAccountNumber + 1 +} + +// Returns asset tree based on account index +func (c *AssetTreeCache) Get(i int64) (tree bsmt.SparseMerkleTree) { + c.mainLock.RLock() + c.treeCache.ContainsOrAdd(i, c.initFunction(i, c.blockNumber)) + c.mainLock.RUnlock() + if tmpTree, ok := c.treeCache.Get(i); ok { + tree = tmpTree.(bsmt.SparseMerkleTree) + } + return +} + +// Returns slice of indexes of asset trees that were changned +func (c *AssetTreeCache) GetChanges() []int64 { + c.mainLock.Lock() + c.changesLock.Lock() + defer c.mainLock.Unlock() + defer c.changesLock.Unlock() + for _, key := range c.treeCache.Keys() { + tree, _ := c.treeCache.Peek(key) + if tree.(bsmt.SparseMerkleTree).LatestVersion()-tree.(bsmt.SparseMerkleTree).RecentVersion() > 1 { + c.changes[key.(int64)] = true + } + } + ret := make([]int64, 0, len(c.changes)) + for key := range c.changes { + ret = append(ret, key) + } + return ret +} + +// Cleans all saved tree changes in the cache +func (c *AssetTreeCache) CleanChanges() { + c.changesLock.Lock() + c.changes = make(map[int64]bool, len(c.changes)) + c.changesLock.Unlock() +} + +// Internal method to that marks if changes happend to tree eviced from LRU +func (c *AssetTreeCache) onDelete(k, v interface{}) { + c.changesLock.Lock() + if v.(bsmt.SparseMerkleTree).LatestVersion()-v.(bsmt.SparseMerkleTree).RecentVersion() > 1 { + c.changes[k.(int64)] = true + } + c.changesLock.Unlock() +} diff --git a/tree/hash_test.go b/tree/hash_test.go new file mode 100644 index 000000000..ec9caaa87 --- /dev/null +++ b/tree/hash_test.go @@ -0,0 +1,11 @@ +package tree + +import ( + "encoding/hex" + "testing" +) + +func TestHash(t *testing.T) { + emptyHash := EmptyAccountAssetNodeHash() + println(hex.EncodeToString(emptyHash)) +} diff --git a/tree/liquidity_tree.go b/tree/liquidity_tree.go deleted file mode 100644 index a8928b2f1..000000000 --- a/tree/liquidity_tree.go +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright © 2021 ZkBNB Protocol - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package tree - -import ( - "github.com/consensys/gnark-crypto/ecc/bn254/fr/mimc" - "github.com/zeromicro/go-zero/core/logx" - - bsmt "github.com/bnb-chain/zkbnb-smt" - "github.com/bnb-chain/zkbnb/dao/liquidity" - "github.com/bnb-chain/zkbnb/types" -) - -func InitLiquidityTree( - liquidityHistoryModel liquidity.LiquidityHistoryModel, - blockHeight int64, - ctx *Context, -) ( - liquidityTree bsmt.SparseMerkleTree, err error, -) { - - liquidityTree, err = bsmt.NewBASSparseMerkleTree(bsmt.NewHasher(mimc.NewMiMC()), - SetNamespace(ctx, LiquidityPrefix), LiquidityTreeHeight, NilLiquidityNodeHash, - ctx.Options(blockHeight)...) - if err != nil { - logx.Errorf("unable to create tree from db: %s", err.Error()) - return nil, err - } - - if ctx.IsLoad() { - nums, err := liquidityHistoryModel.GetLatestLiquidityCountByBlockHeight(blockHeight) - if err != nil { - logx.Errorf("unable to get latest liquidity assets: %s", err.Error()) - return nil, err - } - for i := 0; i < int(nums); i += ctx.BatchReloadSize() { - err := loadLiquidityTreeFromRDB( - liquidityHistoryModel, blockHeight, - i, i+ctx.BatchReloadSize(), liquidityTree) - if err != nil { - return nil, err - } - _, err = liquidityTree.Commit(nil) - if err != nil { - logx.Errorf("unable to commit liquidity tree: %s", err.Error()) - return nil, err - } - } - - return liquidityTree, nil - } - - // It's not loading from RDB, need to check tree version - if liquidityTree.LatestVersion() > bsmt.Version(blockHeight) && !liquidityTree.IsEmpty() { - logx.Infof("liquidity tree version [%d] is higher than block, rollback to %d", liquidityTree.LatestVersion(), blockHeight) - err := liquidityTree.Rollback(bsmt.Version(blockHeight)) - if err != nil { - logx.Errorf("unable to rollback liquidity tree: %s, version: %d", err.Error(), blockHeight) - return nil, err - } - } - - return liquidityTree, nil -} - -func loadLiquidityTreeFromRDB( - liquidityHistoryModel liquidity.LiquidityHistoryModel, - blockHeight int64, - offset, limit int, - liquidityTree bsmt.SparseMerkleTree, -) error { - liquidityAssets, err := liquidityHistoryModel.GetLatestLiquidityByBlockHeight(blockHeight, - limit, offset) - if err != nil { - if err != types.DbErrNotFound { - logx.Errorf("unable to get latest liquidity assets: %s", err.Error()) - return err - } - } - for _, liquidityAsset := range liquidityAssets { - pairIndex := liquidityAsset.PairIndex - hashVal, err := LiquidityAssetToNode( - liquidityAsset.AssetAId, liquidityAsset.AssetA, - liquidityAsset.AssetBId, liquidityAsset.AssetB, - liquidityAsset.LpAmount, liquidityAsset.KLast, - liquidityAsset.FeeRate, liquidityAsset.TreasuryAccountIndex, liquidityAsset.TreasuryRate) - if err != nil { - logx.Errorf("unable to convert liquidity asset to node: %s", err.Error()) - return err - } - err = liquidityTree.Set(uint64(pairIndex), hashVal) - if err != nil { - logx.Errorf("unable to write liquidity asset to tree: %s", err.Error()) - return err - } - } - return nil -} - -func LiquidityAssetToNode( - assetAId int64, - assetA string, - assetBId int64, - assetB string, - lpAmount string, - kLast string, - feeRate int64, - treasuryAccountIndex int64, - treasuryFeeRate int64, -) (hashVal []byte, err error) { - hashVal, err = ComputeLiquidityAssetLeafHash( - assetAId, assetA, - assetBId, assetB, - lpAmount, - kLast, - feeRate, - treasuryAccountIndex, - treasuryFeeRate, - ) - if err != nil { - logx.Errorf("unable to compute liquidity asset leaf hash: %s", err.Error()) - return nil, err - } - return hashVal, nil -} diff --git a/tree/types.go b/tree/types.go index a84bb4207..7385e2c16 100644 --- a/tree/types.go +++ b/tree/types.go @@ -18,21 +18,22 @@ package tree import ( + "encoding/hex" + "github.com/consensys/gnark-crypto/ecc/bn254/fr/mimc" + "github.com/zeromicro/go-zero/core/logx" "github.com/bnb-chain/zkbnb-crypto/merkleTree" ) const ( - AccountTreeHeight = 32 - AssetTreeHeight = 16 - LiquidityTreeHeight = 16 - NftTreeHeight = 40 + AccountTreeHeight = 32 + AssetTreeHeight = 16 + NftTreeHeight = 40 ) const ( NFTPrefix = "nft:" - LiquidityPrefix = "liquidity:" AccountPrefix = "account:" AccountAssetPrefix = "account_asset:" ) @@ -41,11 +42,9 @@ var ( NilHash = merkleTree.NilHash NilStateRoot []byte NilAccountRoot []byte - NilLiquidityRoot []byte NilNftRoot []byte NilAccountAssetRoot []byte NilAccountNodeHash []byte - NilLiquidityNodeHash []byte NilNftNodeHash []byte NilAccountAssetNodeHash []byte ) @@ -62,7 +61,6 @@ func init() { } NilAccountNodeHash = EmptyAccountNodeHash() NilAccountRoot = NilAccountNodeHash - NilLiquidityNodeHash = EmptyLiquidityNodeHash() NilNftNodeHash = EmptyNftNodeHash() for i := 0; i < AccountTreeHeight; i++ { hFunc.Reset() @@ -70,13 +68,6 @@ func init() { hFunc.Write(NilAccountRoot) NilAccountRoot = hFunc.Sum(nil) } - NilLiquidityRoot = NilLiquidityNodeHash - for i := 0; i < LiquidityTreeHeight; i++ { - hFunc.Reset() - hFunc.Write(NilLiquidityRoot) - hFunc.Write(NilLiquidityRoot) - NilLiquidityRoot = hFunc.Sum(nil) - } NilNftRoot = NilNftNodeHash for i := 0; i < NftTreeHeight; i++ { hFunc.Reset() @@ -87,7 +78,8 @@ func init() { // nil state root hFunc.Reset() hFunc.Write(NilAccountRoot) - hFunc.Write(NilLiquidityRoot) hFunc.Write(NilNftRoot) NilStateRoot = hFunc.Sum(nil) + + logx.Infof("genesis state root: %s", hex.EncodeToString(NilStateRoot)) } diff --git a/tree/util.go b/tree/util.go index e400d7d2b..288b7d651 100644 --- a/tree/util.go +++ b/tree/util.go @@ -57,38 +57,10 @@ func EmptyAccountAssetNodeHash() []byte { zero := big.NewInt(0).FillBytes(make([]byte, 32)) /* balance - lpAmount offerCanceledOrFinalized */ hFunc.Write(zero) hFunc.Write(zero) - hFunc.Write(zero) - return hFunc.Sum(nil) -} - -func EmptyLiquidityNodeHash() []byte { - hFunc := mimc.NewMiMC() - zero := big.NewInt(0).FillBytes(make([]byte, 32)) - /* - assetAId - assetA - assetBId - assetB - lpAmount - kLast - feeRate - treasuryAccountIndex - treasuryRate - */ - hFunc.Write(zero) - hFunc.Write(zero) - hFunc.Write(zero) - hFunc.Write(zero) - hFunc.Write(zero) - hFunc.Write(zero) - hFunc.Write(zero) - hFunc.Write(zero) - hFunc.Write(zero) return hFunc.Sum(nil) } @@ -118,11 +90,13 @@ func CommitTrees( pool *ants.Pool, version uint64, accountTree bsmt.SparseMerkleTree, - assetTrees *[]bsmt.SparseMerkleTree, - liquidityTree bsmt.SparseMerkleTree, + assetTrees *AssetTreeCache, nftTree bsmt.SparseMerkleTree) error { - totalTask := len(*assetTrees) + 3 + assetTreeChanges := assetTrees.GetChanges() + defer assetTrees.CleanChanges() + totalTask := len(assetTreeChanges) + 2 + errChan := make(chan error, totalTask) defer close(errChan) @@ -142,16 +116,14 @@ func CommitTrees( return err } - for idx := range *assetTrees { - err := func(i int) error { + for _, idx := range assetTreeChanges { + err := func(i int64) error { return pool.Submit(func() { - assetPrunedVersion := bsmt.Version(version) - if (*assetTrees)[i].LatestVersion() < assetPrunedVersion { - assetPrunedVersion = (*assetTrees)[i].LatestVersion() - } - ver, err := (*assetTrees)[i].Commit(&assetPrunedVersion) + asset := assetTrees.Get(i) + version := asset.LatestVersion() + ver, err := asset.Commit(&version) if err != nil { - errChan <- errors.Wrapf(err, "unable to commit asset tree [%d], tree ver: %d, prune ver: %d", i, ver, assetPrunedVersion) + errChan <- errors.Wrapf(err, "unable to commit asset tree [%d], tree ver: %d, prune ver: %d", i, ver, version) return } errChan <- nil @@ -162,22 +134,6 @@ func CommitTrees( } } - err = pool.Submit(func() { - liquidityPrunedVersion := bsmt.Version(version) - if liquidityTree.LatestVersion() < liquidityPrunedVersion { - liquidityPrunedVersion = liquidityTree.LatestVersion() - } - ver, err := liquidityTree.Commit(&liquidityPrunedVersion) - if err != nil { - errChan <- errors.Wrapf(err, "unable to commit liquidity tree, tree ver: %d, prune ver: %d", ver, liquidityPrunedVersion) - return - } - errChan <- nil - }) - if err != nil { - return err - } - err = pool.Submit(func() { nftPrunedVersion := bsmt.Version(version) if nftTree.LatestVersion() < nftPrunedVersion { @@ -208,11 +164,12 @@ func RollBackTrees( pool *ants.Pool, version uint64, accountTree bsmt.SparseMerkleTree, - assetTrees *[]bsmt.SparseMerkleTree, - liquidityTree bsmt.SparseMerkleTree, + assetTrees *AssetTreeCache, nftTree bsmt.SparseMerkleTree) error { - totalTask := len(*assetTrees) + 3 + assetTreeChanges := assetTrees.GetChanges() + defer assetTrees.CleanChanges() + totalTask := len(assetTreeChanges) + 3 errChan := make(chan error, totalTask) defer close(errChan) @@ -231,15 +188,15 @@ func RollBackTrees( return err } - for idx := range *assetTrees { - err := func(i int) error { + for _, idx := range assetTreeChanges { + err := func(i int64) error { return pool.Submit(func() { - if (*assetTrees)[i].LatestVersion() > ver && !(*assetTrees)[i].IsEmpty() { - err := (*assetTrees)[i].Rollback(ver) - if err != nil { - errChan <- errors.Wrapf(err, "unable to rollback asset tree [%d], ver: %d", i, ver) - return - } + asset := assetTrees.Get(i) + version := asset.RecentVersion() + err := asset.Rollback(version) + if err != nil { + errChan <- errors.Wrapf(err, "unable to rollback asset tree [%d], ver: %d", i, version) + return } errChan <- nil }) @@ -249,20 +206,6 @@ func RollBackTrees( } } - err = pool.Submit(func() { - if liquidityTree.LatestVersion() > ver && !liquidityTree.IsEmpty() { - err := liquidityTree.Rollback(ver) - if err != nil { - errChan <- errors.Wrapf(err, "unable to rollback liquidity tree, ver: %d", ver) - return - } - } - errChan <- nil - }) - if err != nil { - return err - } - err = pool.Submit(func() { if nftTree.LatestVersion() > ver && !nftTree.IsEmpty() { err := nftTree.Rollback(ver) @@ -312,7 +255,6 @@ func ComputeAccountLeafHash( func ComputeAccountAssetLeafHash( balance string, - lpAmount string, offerCanceledOrFinalized string, ) (hashVal []byte, err error) { hFunc := mimc.NewMiMC() @@ -321,10 +263,6 @@ func ComputeAccountAssetLeafHash( if err != nil { return nil, err } - err = common2.PaddingStringBigIntIntoBuf(&buf, lpAmount) - if err != nil { - return nil, err - } err = common2.PaddingStringBigIntIntoBuf(&buf, offerCanceledOrFinalized) if err != nil { return nil, err @@ -333,45 +271,6 @@ func ComputeAccountAssetLeafHash( return hFunc.Sum(nil), nil } -func ComputeLiquidityAssetLeafHash( - assetAId int64, - assetA string, - assetBId int64, - assetB string, - lpAmount string, - kLast string, - feeRate int64, - treasuryAccountIndex int64, - treasuryRate int64, -) (hashVal []byte, err error) { - hFunc := mimc.NewMiMC() - var buf bytes.Buffer - common2.PaddingInt64IntoBuf(&buf, assetAId) - err = common2.PaddingStringBigIntIntoBuf(&buf, assetA) - if err != nil { - return nil, err - } - common2.PaddingInt64IntoBuf(&buf, assetBId) - err = common2.PaddingStringBigIntIntoBuf(&buf, assetB) - if err != nil { - return nil, err - } - err = common2.PaddingStringBigIntIntoBuf(&buf, lpAmount) - if err != nil { - return nil, err - } - err = common2.PaddingStringBigIntIntoBuf(&buf, kLast) - if err != nil { - return nil, err - } - common2.PaddingInt64IntoBuf(&buf, feeRate) - common2.PaddingInt64IntoBuf(&buf, treasuryAccountIndex) - common2.PaddingInt64IntoBuf(&buf, treasuryRate) - hFunc.Write(buf.Bytes()) - hashVal = hFunc.Sum(nil) - return hashVal, nil -} - func ComputeNftAssetLeafHash( creatorAccountIndex int64, ownerAccountIndex int64, @@ -403,12 +302,10 @@ func ComputeNftAssetLeafHash( func ComputeStateRootHash( accountRoot []byte, - liquidityRoot []byte, nftRoot []byte, ) []byte { hFunc := mimc.NewMiMC() hFunc.Write(accountRoot) - hFunc.Write(liquidityRoot) hFunc.Write(nftRoot) return hFunc.Sum(nil) } diff --git a/types/account.go b/types/account.go index dff244c96..ecf6f2a79 100644 --- a/types/account.go +++ b/types/account.go @@ -24,9 +24,8 @@ import ( const ( FungibleAssetType = 1 - LiquidityAssetType = 2 - NftAssetType = 3 - CollectionNonceAssetType = 4 + NftAssetType = 2 + CollectionNonceAssetType = 3 BuyOfferType = 0 SellOfferType = 1 @@ -35,7 +34,6 @@ const ( type AccountAsset struct { AssetId int64 Balance *big.Int - LpAmount *big.Int OfferCanceledOrFinalized *big.Int } @@ -43,16 +41,14 @@ func (asset *AccountAsset) DeepCopy() *AccountAsset { return &AccountAsset{ AssetId: asset.AssetId, Balance: big.NewInt(0).Set(asset.Balance), - LpAmount: big.NewInt(0).Set(asset.LpAmount), OfferCanceledOrFinalized: big.NewInt(0).Set(asset.OfferCanceledOrFinalized), } } -func ConstructAccountAsset(assetId int64, balance *big.Int, lpAmount *big.Int, offerCanceledOrFinalized *big.Int) *AccountAsset { +func ConstructAccountAsset(assetId int64, balance *big.Int, offerCanceledOrFinalized *big.Int) *AccountAsset { return &AccountAsset{ assetId, balance, - lpAmount, offerCanceledOrFinalized, } } @@ -79,13 +75,12 @@ type AccountInfo struct { L1Address string Nonce int64 CollectionNonce int64 - // map[int64]*AccountAsset - AssetInfo map[int64]*AccountAsset // key: index, value: balance - AssetRoot string - Status int + AssetInfo map[int64]*AccountAsset // key: index, value: balance + AssetRoot string + Status int } -func (ai *AccountInfo) DeepCopy() (*AccountInfo, error) { +func (ai *AccountInfo) DeepCopy() *AccountInfo { assetInfo := make(map[int64]*AccountAsset) for assetId, asset := range ai.AssetInfo { assetInfo[assetId] = asset.DeepCopy() @@ -104,5 +99,5 @@ func (ai *AccountInfo) DeepCopy() (*AccountInfo, error) { AssetRoot: ai.AssetRoot, Status: ai.Status, } - return newAccountInfo, nil + return newAccountInfo } diff --git a/types/code.go b/types/code.go index b7d81cc02..b4d89b837 100644 --- a/types/code.go +++ b/types/code.go @@ -11,35 +11,32 @@ import ( // does not use the codes. We can leave the codes for future enhancement. var ( - DbErrNotFound = sqlx.ErrNotFound - DbErrSqlOperation = errors.New("unknown sql operation error") - DbErrFailToCreateBlock = errors.New("fail to create block") - DbErrFailToUpdateBlock = errors.New("fail to update block") - DbErrFailToUpdateTx = errors.New("fail to update tx") - DbErrFailToCreateCompressedBlock = errors.New("fail to create compressed block") - DbErrFailToCreateProof = errors.New("fail to create proof") - DbErrFailToUpdateProof = errors.New("fail to update proof") - DbErrFailToCreateSysConfig = errors.New("fail to create system config") - DbErrFailToUpdateSysConfig = errors.New("fail to update system config") - DbErrFailToCreateAsset = errors.New("fail to create asset") - DbErrFailToUpdateAsset = errors.New("fail to update asset") - DbErrFailToCreateAccount = errors.New("fail to create account") - DbErrFailToUpdateAccount = errors.New("fail to update account") - DbErrFailToCreateAccountHistory = errors.New("fail to create account history") - DbErrFailToCreateL1RollupTx = errors.New("fail to create l1 rollup tx") - DbErrFailToDeleteL1RollupTx = errors.New("fail to delete l1 rollup tx") - DbErrFailToL1SyncedBlock = errors.New("fail to create l1 synced block") - DbErrFailToCreateLiquidity = errors.New("fail to create liquidity") - DbErrFailToUpdateLiquidity = errors.New("fail to update liquidity") - DbErrFailToCreateLiquidityHistory = errors.New("fail to create liquidity history") - DbErrFailToCreatePoolTx = errors.New("fail to create pool tx") - DbErrFailToUpdatePoolTx = errors.New("fail to update pool tx") - DbErrFailToDeletePoolTx = errors.New("fail to delete pool tx") - DbErrFailToCreateNft = errors.New("fail to create nft") - DbErrFailToUpdateNft = errors.New("fail to update nft") - DbErrFailToCreateNftHistory = errors.New("fail to create nft history") - DbErrFailToCreatePriorityRequest = errors.New("fail to create priority request") - DbErrFailToUpdatePriorityRequest = errors.New("fail to update priority request") + DbErrNotFound = sqlx.ErrNotFound + DbErrSqlOperation = errors.New("unknown sql operation error") + DbErrFailToCreateBlock = errors.New("fail to create block") + DbErrFailToUpdateBlock = errors.New("fail to update block") + DbErrFailToUpdateTx = errors.New("fail to update tx") + DbErrFailToCreateCompressedBlock = errors.New("fail to create compressed block") + DbErrFailToCreateProof = errors.New("fail to create proof") + DbErrFailToUpdateProof = errors.New("fail to update proof") + DbErrFailToCreateSysConfig = errors.New("fail to create system config") + DbErrFailToUpdateSysConfig = errors.New("fail to update system config") + DbErrFailToCreateAsset = errors.New("fail to create asset") + DbErrFailToUpdateAsset = errors.New("fail to update asset") + DbErrFailToCreateAccount = errors.New("fail to create account") + DbErrFailToUpdateAccount = errors.New("fail to update account") + DbErrFailToCreateAccountHistory = errors.New("fail to create account history") + DbErrFailToCreateL1RollupTx = errors.New("fail to create l1 rollup tx") + DbErrFailToDeleteL1RollupTx = errors.New("fail to delete l1 rollup tx") + DbErrFailToL1SyncedBlock = errors.New("fail to create l1 synced block") + DbErrFailToCreatePoolTx = errors.New("fail to create pool tx") + DbErrFailToUpdatePoolTx = errors.New("fail to update pool tx") + DbErrFailToDeletePoolTx = errors.New("fail to delete pool tx") + DbErrFailToCreateNft = errors.New("fail to create nft") + DbErrFailToUpdateNft = errors.New("fail to update nft") + DbErrFailToCreateNftHistory = errors.New("fail to create nft history") + DbErrFailToCreatePriorityRequest = errors.New("fail to create priority request") + DbErrFailToUpdatePriorityRequest = errors.New("fail to update priority request") JsonErrUnmarshal = errors.New("json.Unmarshal err") JsonErrMarshal = errors.New("json.Marshal err") diff --git a/types/constant.go b/types/constant.go index 92ef0863c..6a9f375ff 100644 --- a/types/constant.go +++ b/types/constant.go @@ -35,7 +35,6 @@ const ( EmptyCreatorTreasuryRate = 0 NilAccountName = "" - NilPairIndex = -1 NilNftIndex = int64(-1) NilAccountIndex = int64(-1) NilBlockHeight = -1 @@ -46,10 +45,11 @@ const ( NilExpiredAt = math.MaxInt64 NilAssetAmount = "0" - BNBAssetId = 0 - BNBDecimals = "1000000000000000000" + GasAccount = int64(1) + BNBAssetId = 0 ) var ( EmptyOfferCanceledOrFinalized = big.NewInt(0) + GasAssets = [2]int64{0, 1} ) diff --git a/types/liquidity.go b/types/liquidity.go deleted file mode 100644 index 3b8e5657b..000000000 --- a/types/liquidity.go +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright © 2021 ZkBNB Protocol - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package types - -import ( - "encoding/json" - "errors" - "math/big" -) - -type LiquidityInfo struct { - PairIndex int64 - AssetAId int64 - AssetA *big.Int - AssetBId int64 - AssetB *big.Int - LpAmount *big.Int - KLast *big.Int - FeeRate int64 - TreasuryAccountIndex int64 - TreasuryRate int64 -} - -func (info *LiquidityInfo) String() string { - infoBytes, _ := json.Marshal(info) - return string(infoBytes) -} - -func EmptyLiquidityInfo(pairIndex int64) (info *LiquidityInfo) { - return &LiquidityInfo{ - PairIndex: pairIndex, - AssetAId: 0, - AssetA: ZeroBigInt, - AssetBId: 0, - AssetB: ZeroBigInt, - LpAmount: ZeroBigInt, - KLast: ZeroBigInt, - FeeRate: 0, - TreasuryAccountIndex: 0, - TreasuryRate: 0, - } -} - -func ConstructLiquidityInfo(pairIndex int64, assetAId int64, assetAAmount string, assetBId int64, assetBAmount string, - lpAmount string, kLast string, feeRate int64, treasuryAccountIndex int64, treasuryRate int64) (info *LiquidityInfo, err error) { - assetA, isValid := new(big.Int).SetString(assetAAmount, 10) - if !isValid { - return nil, errors.New("[ConstructLiquidityInfo] invalid bit int") - } - assetB, isValid := new(big.Int).SetString(assetBAmount, 10) - if !isValid { - return nil, errors.New("[ConstructLiquidityInfo] invalid bit int") - } - lp, isValid := new(big.Int).SetString(lpAmount, 10) - if !isValid { - return nil, errors.New("[ConstructLiquidityInfo] invalid bit int") - } - kLastInt, isValid := new(big.Int).SetString(kLast, 10) - if !isValid { - return nil, errors.New("[ConstructLiquidityInfo] invalid bit int") - } - info = &LiquidityInfo{ - PairIndex: pairIndex, - AssetAId: assetAId, - AssetA: assetA, - AssetBId: assetBId, - AssetB: assetB, - LpAmount: lp, - KLast: kLastInt, - FeeRate: feeRate, - TreasuryAccountIndex: treasuryAccountIndex, - TreasuryRate: treasuryRate, - } - return info, nil -} - -func ParseLiquidityInfo(infoStr string) (info *LiquidityInfo, err error) { - err = json.Unmarshal([]byte(infoStr), &info) - if err != nil { - return nil, JsonErrUnmarshal - } - return info, nil -} diff --git a/types/system.go b/types/system.go index bfb96b191..450aa135f 100644 --- a/types/system.go +++ b/types/system.go @@ -39,6 +39,5 @@ const ( ) var ( - ZeroBigInt = big.NewInt(0) - ZeroBigIntString = "0" + ZeroBigInt = big.NewInt(0) ) diff --git a/types/tx.go b/types/tx.go index ff299212e..cd5291dae 100644 --- a/types/tx.go +++ b/types/tx.go @@ -20,21 +20,15 @@ package types import ( "encoding/json" - "github.com/bnb-chain/zkbnb-crypto/circuit" "github.com/bnb-chain/zkbnb-crypto/wasm/txtypes" ) const ( TxTypeEmpty = iota TxTypeRegisterZns - TxTypeCreatePair - TxTypeUpdatePairRate TxTypeDeposit TxTypeDepositNft TxTypeTransfer - TxTypeSwap - TxTypeAddLiquidity - TxTypeRemoveLiquidity TxTypeWithdraw TxTypeCreateCollection TxTypeMintNft @@ -49,9 +43,6 @@ const ( func IsL2Tx(txType int64) bool { if txType == TxTypeTransfer || - txType == TxTypeSwap || - txType == TxTypeAddLiquidity || - txType == TxTypeRemoveLiquidity || txType == TxTypeWithdraw || txType == TxTypeCreateCollection || txType == TxTypeMintNft || @@ -64,16 +55,25 @@ func IsL2Tx(txType int64) bool { return false } +func IsPriorityOperationTx(txType int64) bool { + if txType == TxTypeRegisterZns || + txType == TxTypeDeposit || + txType == TxTypeDepositNft || + txType == TxTypeFullExit || + txType == TxTypeFullExitNft { + return true + } + return false +} + const ( TxTypeBytesSize = 1 - IsNewNftSize = 1 AddressBytesSize = 20 AccountIndexBytesSize = 4 AccountNameBytesSize = 32 AccountNameHashBytesSize = 32 PubkeyBytesSize = 32 AssetIdBytesSize = 2 - PairIndexBytesSize = 2 StateAmountBytesSize = 16 NftIndexBytesSize = 5 NftTokenIdBytesSize = 32 @@ -83,13 +83,9 @@ const ( RegisterZnsPubDataSize = TxTypeBytesSize + AccountIndexBytesSize + AccountNameBytesSize + AccountNameHashBytesSize + PubkeyBytesSize + PubkeyBytesSize - CreatePairPubDataSize = TxTypeBytesSize + PairIndexBytesSize + - AssetIdBytesSize + AssetIdBytesSize + FeeRateBytesSize + AccountIndexBytesSize + FeeRateBytesSize - UpdatePairRatePubdataSize = TxTypeBytesSize + PairIndexBytesSize + - FeeRateBytesSize + AccountIndexBytesSize + FeeRateBytesSize DepositPubDataSize = TxTypeBytesSize + AccountIndexBytesSize + AccountNameHashBytesSize + AssetIdBytesSize + StateAmountBytesSize - DepositNftPubDataSize = TxTypeBytesSize + IsNewNftSize + AccountIndexBytesSize + NftIndexBytesSize + AddressBytesSize + + DepositNftPubDataSize = TxTypeBytesSize + AccountIndexBytesSize + NftIndexBytesSize + AddressBytesSize + AccountIndexBytesSize + FeeRateBytesSize + NftContentHashBytesSize + NftTokenIdBytesSize + AccountNameHashBytesSize + CollectionIdBytesSize FullExitPubDataSize = TxTypeBytesSize + AccountIndexBytesSize + @@ -106,14 +102,12 @@ const ( TypeAccountName TypeAccountNameOmitSpace TypeAccountPk - TypePairIndex TypeLimit TypeOffset TypeHash TypeBlockHeight TypeTxType TypeChainId - TypeLPAmount TypeAssetAmount TypeBoolean TypeGasFee @@ -121,7 +115,6 @@ const ( const ( AddressSize = 20 - FeeRateBase = circuit.RateBase EmptyStringKeccak = "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" ) @@ -133,22 +126,6 @@ func ParseRegisterZnsTxInfo(txInfoStr string) (txInfo *txtypes.RegisterZnsTxInfo return txInfo, nil } -func ParseCreatePairTxInfo(txInfoStr string) (txInfo *txtypes.CreatePairTxInfo, err error) { - err = json.Unmarshal([]byte(txInfoStr), &txInfo) - if err != nil { - return nil, err - } - return txInfo, nil -} - -func ParseUpdatePairRateTxInfo(txInfoStr string) (txInfo *txtypes.UpdatePairRateTxInfo, err error) { - err = json.Unmarshal([]byte(txInfoStr), &txInfo) - if err != nil { - return nil, err - } - return txInfo, nil -} - func ParseDepositTxInfo(txInfoStr string) (txInfo *txtypes.DepositTxInfo, err error) { err = json.Unmarshal([]byte(txInfoStr), &txInfo) if err != nil { @@ -197,30 +174,6 @@ func ParseTransferTxInfo(txInfoStr string) (txInfo *txtypes.TransferTxInfo, err return txInfo, nil } -func ParseSwapTxInfo(txInfoStr string) (txInfo *txtypes.SwapTxInfo, err error) { - err = json.Unmarshal([]byte(txInfoStr), &txInfo) - if err != nil { - return nil, err - } - return txInfo, nil -} - -func ParseAddLiquidityTxInfo(txInfoStr string) (txInfo *txtypes.AddLiquidityTxInfo, err error) { - err = json.Unmarshal([]byte(txInfoStr), &txInfo) - if err != nil { - return nil, err - } - return txInfo, nil -} - -func ParseRemoveLiquidityTxInfo(txInfoStr string) (txInfo *txtypes.RemoveLiquidityTxInfo, err error) { - err = json.Unmarshal([]byte(txInfoStr), &txInfo) - if err != nil { - return nil, err - } - return txInfo, nil -} - func ParseMintNftTxInfo(txInfoStr string) (txInfo *txtypes.MintNftTxInfo, err error) { err = json.Unmarshal([]byte(txInfoStr), &txInfo) if err != nil {