diff --git a/chain33.fork.toml b/chain33.fork.toml index 79c79eece..d4337f148 100644 --- a/chain33.fork.toml +++ b/chain33.fork.toml @@ -168,6 +168,7 @@ Enable=0 [fork.sub.multisig] Enable=0 +ForkMultiSigFixStaleWeight=0 [fork.sub.norm] Enable=0 diff --git a/chain33.para.toml b/chain33.para.toml index 00afc4248..094c27f2e 100644 --- a/chain33.para.toml +++ b/chain33.para.toml @@ -500,6 +500,7 @@ Enable=0 [fork.sub.multisig] Enable=0 +ForkMultiSigFixStaleWeight=0 [fork.sub.mix] Enable=0 diff --git a/plugin/dapp/evm/cmd/ci2/chain33.proxyminer.toml b/plugin/dapp/evm/cmd/ci2/chain33.proxyminer.toml index 1316dafbb..d5eb0f7d3 100644 --- a/plugin/dapp/evm/cmd/ci2/chain33.proxyminer.toml +++ b/plugin/dapp/evm/cmd/ci2/chain33.proxyminer.toml @@ -676,6 +676,7 @@ Enable=0 [fork.sub.multisig] Enable=0 +ForkMultiSigFixStaleWeight=0 [fork.sub.norm] Enable=0 diff --git a/plugin/dapp/multisig/executor/action.go b/plugin/dapp/multisig/executor/action.go index 7fbac020c..30ef37b61 100644 --- a/plugin/dapp/multisig/executor/action.go +++ b/plugin/dapp/multisig/executor/action.go @@ -41,6 +41,11 @@ func newAction(t *MultiSig, tx *types.Transaction, index int32) *action { t.GetBlockTime(), t.GetHeight(), index, dapp.ExecAddress(string(tx.Execer)), t.GetAPI()} } +// isFixStaleWeight 判定当前高度是否启用确认权重按owner当前权重重算的修复分叉 +func (a *action) isFixStaleWeight() bool { + return a.api.GetConfig().IsDappFork(a.height, mty.MultiSigX, mty.ForkMultiSigFixStaleWeight) +} + // MultiSigAccCreate 创建多重签名账户 func (a *action) MultiSigAccCreate(accountCreate *mty.MultiSigAccCreate) (*types.Receipt, error) { var logs []*types.ReceiptLog @@ -364,7 +369,7 @@ func (a *action) MultiSigConfirmTx(ConfirmTx *mty.MultiSigConfirmTx) (*types.Rec } multiSigTxOwner := &mty.MultiSigTxOwner{MultiSigAddr: multiSigAccAddr, Txid: ConfirmTx.TxId, ConfirmedOwner: owner} - isConfirm := isConfirmed(multiSigAcc.RequiredWeight, multiSigTx) + isConfirm := isConfirmed(multiSigAcc.RequiredWeight, multiSigTx, multiSigAcc, a.isFixStaleWeight()) //权重未达到要求或者撤销确认交易,构造MultiSigConfirmTx的receiptLog if !isConfirm || !ConfirmTx.ConfirmOrRevoke { @@ -757,7 +762,7 @@ func (a *action) executeTransferTx(multiSigAcc *mty.MultiSig, newMultiSigTx *mty //确认此交易额度是否在每日限额之内,或者权重已达到要求 amount := transfer.Amount - confirmed := isConfirmed(multiSigAcc.RequiredWeight, newMultiSigTx) + confirmed := isConfirmed(multiSigAcc.RequiredWeight, newMultiSigTx, multiSigAcc, a.isFixStaleWeight()) underLimit, newlastday := isUnderLimit(a.blocktime, uint64(amount), curDailyLimit) //新的一天更新lastday和spenttoday的值 @@ -838,7 +843,7 @@ func (a *action) executeTransferTx(multiSigAcc *mty.MultiSig, newMultiSigTx *mty func (a *action) executeAccOperateTx(multiSigAcc *mty.MultiSig, newMultiSigTx *mty.MultiSigTx, accountOperate *mty.MultiSigAccOperate, confOwner *mty.Owner, subOrConfirm bool) (*types.Receipt, error) { //确认权重是否已达到要求 - confirmed := isConfirmed(multiSigAcc.RequiredWeight, newMultiSigTx) + confirmed := isConfirmed(multiSigAcc.RequiredWeight, newMultiSigTx, multiSigAcc, a.isFixStaleWeight()) prevExecuted := newMultiSigTx.Executed var logs []*types.ReceiptLog @@ -899,7 +904,7 @@ func (a *action) executeOwnerOperateTx(multiSigAccount *mty.MultiSig, newMultiSi var receiptLog *types.ReceiptLog var err error //确认权重是否已达到要求 - confirmed := isConfirmed(multiSigAccount.RequiredWeight, newMultiSigTx) + confirmed := isConfirmed(multiSigAccount.RequiredWeight, newMultiSigTx, multiSigAccount, a.isFixStaleWeight()) prevExecuted := newMultiSigTx.Executed flag := accountOperate.OperateFlag diff --git a/plugin/dapp/multisig/executor/multisig.go b/plugin/dapp/multisig/executor/multisig.go index 794626795..c041416a8 100644 --- a/plugin/dapp/multisig/executor/multisig.go +++ b/plugin/dapp/multisig/executor/multisig.go @@ -931,10 +931,20 @@ func getOwnerInfoByAddr(multiSigAcc *mty.MultiSig, oldowner string) (uint64, int } // 确认某笔交易是否已经达到确认需要的权重 -func isConfirmed(requiredWeight uint64, multiSigTx *mty.MultiSigTx) bool { +// useCurWeight为true时忽略确认时记录的权重快照,按owner当前权重重新累计, +// 防止owner权重被modify/del/replace后仍按过期权重凑足阈值执行交易 +func isConfirmed(requiredWeight uint64, multiSigTx *mty.MultiSigTx, multiSigAcc *mty.MultiSig, useCurWeight bool) bool { var totalweight uint64 for _, owner := range multiSigTx.ConfirmedOwner { - totalweight += owner.Weight + weight := owner.Weight + if useCurWeight { + curWeight, isowner := isOwner(multiSigAcc, owner.OwnerAddr) + if !isowner { + continue + } + weight = curWeight + } + totalweight += weight } return totalweight >= requiredWeight } diff --git a/plugin/dapp/multisig/executor/security_fix_test.go b/plugin/dapp/multisig/executor/security_fix_test.go new file mode 100644 index 000000000..f2c253008 --- /dev/null +++ b/plugin/dapp/multisig/executor/security_fix_test.go @@ -0,0 +1,37 @@ +package executor + +import ( + "testing" + + mty "github.com/33cn/plugin/plugin/dapp/multisig/types" + "github.com/stretchr/testify/assert" +) + +// TestIsConfirmedUsesCurrentWeight 确认修复分叉后按 owner 当前权重累计,不再使用确认时的过期快照 +func TestIsConfirmedUsesCurrentWeight(t *testing.T) { + acc := &mty.MultiSig{ + RequiredWeight: 10, + Owners: []*mty.Owner{ + {OwnerAddr: "ownerA", Weight: 5}, + {OwnerAddr: "ownerB", Weight: 5}, + }, + } + tx := &mty.MultiSigTx{ + ConfirmedOwner: []*mty.Owner{ + {OwnerAddr: "ownerA", Weight: 5}, + {OwnerAddr: "ownerB", Weight: 5}, + }, + } + assert.True(t, isConfirmed(10, tx, acc, false)) + assert.True(t, isConfirmed(10, tx, acc, true)) + + // ownerB 被删除后:旧快照仍能凑足阈值,按当前 owner 权重则不能 + acc.Owners = acc.Owners[:1] + assert.True(t, isConfirmed(10, tx, acc, false), "pre-fork keeps the stale snapshot behavior") + assert.False(t, isConfirmed(10, tx, acc, true), "post-fork must ignore removed owner") + + // ownerA 被降权后,按当前权重重新累计也不能凑足阈值 + acc2 := &mty.MultiSig{RequiredWeight: 10, Owners: []*mty.Owner{{OwnerAddr: "ownerA", Weight: 2}}} + assert.True(t, isConfirmed(10, tx, acc2, false)) + assert.False(t, isConfirmed(10, tx, acc2, true)) +} diff --git a/plugin/dapp/multisig/types/const.go b/plugin/dapp/multisig/types/const.go index e3d8b12f0..7fe8e6251 100644 --- a/plugin/dapp/multisig/types/const.go +++ b/plugin/dapp/multisig/types/const.go @@ -37,6 +37,11 @@ var ( Multisiglog = log15.New("module", MultiSigX) ) +const ( + // ForkMultiSigFixStaleWeight 修复确认权重判定使用过期权重快照的问题,按owner当前权重重新累计确认权重 + ForkMultiSigFixStaleWeight = "ForkMultiSigFixStaleWeight" +) + // MultiSig 交易的actionid const ( ActionMultiSigAccCreate = 10000 diff --git a/plugin/dapp/multisig/types/types.go b/plugin/dapp/multisig/types/types.go index 82452fe6a..fc5ca3d5c 100644 --- a/plugin/dapp/multisig/types/types.go +++ b/plugin/dapp/multisig/types/types.go @@ -19,6 +19,7 @@ func init() { // InitFork ... func InitFork(cfg *types.Chain33Config) { cfg.RegisterDappFork(MultiSigX, "Enable", 0) + cfg.RegisterDappFork(MultiSigX, ForkMultiSigFixStaleWeight, 0) } // InitExecutor ...