Merge pull request #4719 from filecoin-project/frrist/msig-diffing

polish: add msig pendingtxn diffing and comp
This commit is contained in:
Łukasz Magiera 2020-11-06 16:47:29 +01:00 committed by GitHub
commit 6bb8521a55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 186 additions and 0 deletions

View File

@ -0,0 +1,134 @@
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
}

View File

@ -1,6 +1,7 @@
package multisig
import (
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
@ -47,6 +48,10 @@ type State interface {
Signers() ([]address.Address, error)
ForEachPendingTxn(func(id int64, txn Transaction) error) error
PendingTxnChanged(State) (bool, error)
transactions() (adt.Map, error)
decodeTransaction(val *cbg.Deferred) (Transaction, error)
}
type Transaction = msig0.Transaction

View File

@ -1,17 +1,20 @@
package multisig
import (
"bytes"
"encoding/binary"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors/adt"
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
multisig0 "github.com/filecoin-project/specs-actors/v2/actors/builtin/multisig"
)
var _ State = (*state0)(nil)
@ -68,3 +71,24 @@ func (s *state0) ForEachPendingTxn(cb func(id int64, txn Transaction) error) err
return cb(txid, (Transaction)(out))
})
}
func (s *state0) PendingTxnChanged(other State) (bool, error) {
other0, ok := other.(*state0)
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return !s.State.PendingTxns.Equals(other0.PendingTxns), nil
}
func (s *state0) transactions() (adt.Map, error) {
return adt0.AsMap(s.store, s.PendingTxns)
}
func (s *state0) decodeTransaction(val *cbg.Deferred) (Transaction, error) {
var tx multisig0.Transaction
if err := tx.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return Transaction{}, err
}
return tx, nil
}

View File

@ -1,11 +1,13 @@
package multisig
import (
"bytes"
"encoding/binary"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/chain/actors/adt"
@ -68,3 +70,24 @@ func (s *state2) ForEachPendingTxn(cb func(id int64, txn Transaction) error) err
return cb(txid, (Transaction)(out))
})
}
func (s *state2) PendingTxnChanged(other State) (bool, error) {
other2, ok := other.(*state2)
if !ok {
// treat an upgrade as a change, always
return true, nil
}
return !s.State.PendingTxns.Equals(other2.PendingTxns), nil
}
func (s *state2) transactions() (adt.Map, error) {
return adt2.AsMap(s.store, s.PendingTxns)
}
func (s *state2) decodeTransaction(val *cbg.Deferred) (Transaction, error) {
var tx msig2.Transaction
if err := tx.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil {
return Transaction{}, err
}
return tx, nil
}