package multisig import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" cbg "github.com/whyrusleeping/cbor-gen" "github.com/filecoin-project/lotus/chain/actors/adt" ) type PendingTransactionChanges struct { Added []TransactionChange Modified []TransactionModification Removed []TransactionChange } type TransactionChange struct { TxID int64 Tx Transaction } type TransactionModification struct { TxID int64 From Transaction To Transaction } func DiffPendingTransactions(pre, cur State) (*PendingTransactionChanges, error) { results := new(PendingTransactionChanges) if changed, err := pre.PendingTxnChanged(cur); err != nil { return nil, err } else if !changed { // if nothing has changed then return an empty result and bail. return results, nil } pret, err := pre.transactions() if err != nil { return nil, err } curt, err := cur.transactions() if err != nil { return nil, err } if err := adt.DiffAdtMap(pret, curt, &transactionDiffer{results, pre, cur}); err != nil { return nil, err } return results, nil } type transactionDiffer struct { Results *PendingTransactionChanges pre, after State } func (t *transactionDiffer) AsKey(key string) (abi.Keyer, error) { txID, err := abi.ParseIntKey(key) if err != nil { return nil, err } return abi.IntKey(txID), nil } func (t *transactionDiffer) Add(key string, val *cbg.Deferred) error { txID, err := abi.ParseIntKey(key) if err != nil { return err } tx, err := t.after.decodeTransaction(val) if err != nil { return err } t.Results.Added = append(t.Results.Added, TransactionChange{ TxID: txID, Tx: tx, }) return nil } func (t *transactionDiffer) Modify(key string, from, to *cbg.Deferred) error { txID, err := abi.ParseIntKey(key) if err != nil { return err } txFrom, err := t.pre.decodeTransaction(from) if err != nil { return err } txTo, err := t.after.decodeTransaction(to) if err != nil { return err } if approvalsChanged(txFrom.Approved, txTo.Approved) { t.Results.Modified = append(t.Results.Modified, TransactionModification{ TxID: txID, From: txFrom, To: txTo, }) } return nil } func approvalsChanged(from, to []address.Address) bool { if len(from) != len(to) { return true } for idx := range from { if from[idx] != to[idx] { return true } } return false } func (t *transactionDiffer) Remove(key string, val *cbg.Deferred) error { txID, err := abi.ParseIntKey(key) if err != nil { return err } tx, err := t.pre.decodeTransaction(val) if err != nil { return err } t.Results.Removed = append(t.Results.Removed, TransactionChange{ TxID: txID, Tx: tx, }) return nil }