diff --git a/chain33.fork.toml b/chain33.fork.toml index 79c79eece..868dfd848 100644 --- a/chain33.fork.toml +++ b/chain33.fork.toml @@ -165,6 +165,8 @@ Enable=0 [fork.sub.mix] Enable=0 +ForkMixAmountOverflow=0 +ForkMixDupNullifier=0 [fork.sub.multisig] Enable=0 diff --git a/chain33.para.toml b/chain33.para.toml index 00afc4248..48662b57e 100644 --- a/chain33.para.toml +++ b/chain33.para.toml @@ -503,6 +503,8 @@ Enable=0 [fork.sub.mix] Enable=0 +ForkMixAmountOverflow=0 +ForkMixDupNullifier=0 [fork.sub.unfreeze] Enable=0 diff --git a/plugin/dapp/evm/cmd/ci2/chain33.proxyminer.toml b/plugin/dapp/evm/cmd/ci2/chain33.proxyminer.toml index 1316dafbb..25531d421 100644 --- a/plugin/dapp/evm/cmd/ci2/chain33.proxyminer.toml +++ b/plugin/dapp/evm/cmd/ci2/chain33.proxyminer.toml @@ -673,6 +673,8 @@ Enable=0 [fork.sub.mix] Enable=0 +ForkMixAmountOverflow=0 +ForkMixDupNullifier=0 [fork.sub.multisig] Enable=0 diff --git a/plugin/dapp/mix/executor/deposit.go b/plugin/dapp/mix/executor/deposit.go index ee3c985ac..f4c32633e 100644 --- a/plugin/dapp/mix/executor/deposit.go +++ b/plugin/dapp/mix/executor/deposit.go @@ -5,6 +5,8 @@ package executor import ( + "math" + "github.com/33cn/chain33/common/address" "github.com/33cn/chain33/types" mixTy "github.com/33cn/plugin/plugin/dapp/mix/types" @@ -42,6 +44,8 @@ func (a *action) depositVerify(proof *mixTy.ZkProofInfo) (*mixTy.DepositCircuit, 4. add new commits to merkle tree */ func (a *action) Deposit(deposit *mixTy.MixDepositAction) (*types.Receipt, error) { + cfg := a.api.GetConfig() + checkOverflow := cfg.IsDappFork(a.height, mixTy.MixX, mixTy.ForkMixAmountOverflow) var notes []string var sum uint64 //1. zk-proof校验 @@ -54,6 +58,10 @@ func (a *action) Deposit(deposit *mixTy.MixDepositAction) (*types.Receipt, error if err != nil { return nil, err } + //分叉后校验累加溢出,防止存入金额回绕(同时避免sum超出int64范围) + if checkOverflow && v.Uint64() > math.MaxInt64-sum { + return nil, errors.Wrapf(mixTy.ErrAmountOverflow, "deposit amount sum overflow,sum=%d,amount=%d", sum, v.Uint64()) + } sum += v.Uint64() noteHash, err := mixTy.VariableToElement(input.NoteHash) if err != nil { @@ -63,7 +71,6 @@ func (a *action) Deposit(deposit *mixTy.MixDepositAction) (*types.Receipt, error } //存款 - cfg := a.api.GetConfig() execer, symbol := mixTy.GetAssetExecSymbol(cfg, deposit.AssetExec, deposit.AssetSymbol) accoutDb, err := createAccount(cfg, execer, symbol, a.db) if err != nil { diff --git a/plugin/dapp/mix/executor/withdraw.go b/plugin/dapp/mix/executor/withdraw.go index a4491a3f8..13206a13c 100644 --- a/plugin/dapp/mix/executor/withdraw.go +++ b/plugin/dapp/mix/executor/withdraw.go @@ -86,10 +86,13 @@ func (a *action) withdrawVerify(exec, symbol string, proof *mixTy.ZkProofInfo) ( 3. set nullifier exist */ func (a *action) Withdraw(withdraw *mixTy.MixWithdrawAction) (*types.Receipt, error) { - exec, symbol := mixTy.GetAssetExecSymbol(a.api.GetConfig(), withdraw.AssetExec, withdraw.AssetSymbol) + cfg := a.api.GetConfig() + exec, symbol := mixTy.GetAssetExecSymbol(cfg, withdraw.AssetExec, withdraw.AssetSymbol) + checkDupNullifier := cfg.IsDappFork(a.height, mixTy.MixX, mixTy.ForkMixDupNullifier) var nulliferSet []string var sumValue uint64 + nullifierDup := make(map[string]struct{}) for _, k := range withdraw.Proofs { input, err := a.withdrawVerify(exec, symbol, k) if err != nil { @@ -104,6 +107,13 @@ func (a *action) Withdraw(withdraw *mixTy.MixWithdrawAction) (*types.Receipt, er if err != nil { return nil, err } + //分叉后校验交易内nullifier唯一:nullifier在交易结束才落库,同一交易内重复proof会双花 + if checkDupNullifier { + if _, ok := nullifierDup[nullHash.String()]; ok { + return nil, errors.Wrapf(mixTy.ErrNulliferHashExist, "duplicate nullifier in tx,nullifier=%s", nullHash.String()) + } + nullifierDup[nullHash.String()] = struct{}{} + } nulliferSet = append(nulliferSet, nullHash.String()) } @@ -112,7 +122,6 @@ func (a *action) Withdraw(withdraw *mixTy.MixWithdrawAction) (*types.Receipt, er } //withdraw value - cfg := a.api.GetConfig() accoutDb, err := createAccount(cfg, exec, symbol, a.db) if err != nil { return nil, err diff --git a/plugin/dapp/mix/types/errors.go b/plugin/dapp/mix/types/errors.go index e1cb040ba..5e378202c 100644 --- a/plugin/dapp/mix/types/errors.go +++ b/plugin/dapp/mix/types/errors.go @@ -18,6 +18,8 @@ var ( //ErrNulliferHashExist exist ErrNulliferHashExist = errors.New("ErrNulliferHashExist") + //ErrAmountOverflow amount sum overflow + ErrAmountOverflow = errors.New("ErrAmountOverflow") //ErrAuthorizeHashExist exist ErrAuthorizeHashExist = errors.New("ErrAuthorizeHashExist") diff --git a/plugin/dapp/mix/types/type.go b/plugin/dapp/mix/types/type.go index b3328987d..29b04234a 100644 --- a/plugin/dapp/mix/types/type.go +++ b/plugin/dapp/mix/types/type.go @@ -19,6 +19,13 @@ var ( glog = log.New("module", MixX) ) +const ( + // ForkMixAmountOverflow 修复存款金额以uint64累加无溢出检查的漏洞 + ForkMixAmountOverflow = "ForkMixAmountOverflow" + // ForkMixDupNullifier 修复同一笔Withdraw交易内重复proof双花的漏洞 + ForkMixDupNullifier = "ForkMixDupNullifier" +) + func init() { // init executor type types.AllowUserExec = append(types.AllowUserExec, []byte(MixX)) @@ -30,7 +37,8 @@ func init() { // InitFork ... func InitFork(cfg *types.Chain33Config) { cfg.RegisterDappFork(MixX, "Enable", 0) - + cfg.RegisterDappFork(MixX, ForkMixAmountOverflow, 0) + cfg.RegisterDappFork(MixX, ForkMixDupNullifier, 0) } // InitExecutor ...