diff --git a/chain/actors/builtin/init/diff.go b/chain/actors/builtin/init/diff.go new file mode 100644 index 00000000000..593171322f7 --- /dev/null +++ b/chain/actors/builtin/init/diff.go @@ -0,0 +1,152 @@ +package init + +import ( + "bytes" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + typegen "github.com/whyrusleeping/cbor-gen" + + "github.com/filecoin-project/lotus/chain/actors/adt" +) + +func DiffAddressMap(pre, cur State) (*AddressMapChanges, error) { + prem, err := pre.addressMap() + if err != nil { + return nil, err + } + + curm, err := cur.addressMap() + if err != nil { + return nil, err + } + + preRoot, err := prem.Root() + if err != nil { + return nil, err + } + + curRoot, err := curm.Root() + if err != nil { + return nil, err + } + + results := new(AddressMapChanges) + // no change. + if curRoot.Equals(preRoot) { + return results, nil + } + + err = adt.DiffAdtMap(prem, curm, &addressMapDiffer{results, pre, cur}) + if err != nil { + return nil, err + } + + return results, nil +} + +type addressMapDiffer struct { + Results *AddressMapChanges + pre, adter State +} + +type AddressMapChanges struct { + Added []AddressPair + Modified []AddressChange + Removed []AddressPair +} + +func (i *addressMapDiffer) AsKey(key string) (abi.Keyer, error) { + addr, err := address.NewFromBytes([]byte(key)) + if err != nil { + return nil, err + } + return abi.AddrKey(addr), nil +} + +func (i *addressMapDiffer) Add(key string, val *typegen.Deferred) error { + pkAddr, err := address.NewFromBytes([]byte(key)) + if err != nil { + return err + } + id := new(typegen.CborInt) + if err := id.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { + return err + } + idAddr, err := address.NewIDAddress(uint64(*id)) + if err != nil { + return err + } + i.Results.Added = append(i.Results.Added, AddressPair{ + ID: idAddr, + PK: pkAddr, + }) + return nil +} + +func (i *addressMapDiffer) Modify(key string, from, to *typegen.Deferred) error { + pkAddr, err := address.NewFromBytes([]byte(key)) + if err != nil { + return err + } + + fromID := new(typegen.CborInt) + if err := fromID.UnmarshalCBOR(bytes.NewReader(from.Raw)); err != nil { + return err + } + fromIDAddr, err := address.NewIDAddress(uint64(*fromID)) + if err != nil { + return err + } + + toID := new(typegen.CborInt) + if err := toID.UnmarshalCBOR(bytes.NewReader(to.Raw)); err != nil { + return err + } + toIDAddr, err := address.NewIDAddress(uint64(*toID)) + if err != nil { + return err + } + + i.Results.Modified = append(i.Results.Modified, AddressChange{ + From: AddressPair{ + ID: fromIDAddr, + PK: pkAddr, + }, + To: AddressPair{ + ID: toIDAddr, + PK: pkAddr, + }, + }) + return nil +} + +func (i *addressMapDiffer) Remove(key string, val *typegen.Deferred) error { + pkAddr, err := address.NewFromBytes([]byte(key)) + if err != nil { + return err + } + id := new(typegen.CborInt) + if err := id.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { + return err + } + idAddr, err := address.NewIDAddress(uint64(*id)) + if err != nil { + return err + } + i.Results.Removed = append(i.Results.Removed, AddressPair{ + ID: idAddr, + PK: pkAddr, + }) + return nil +} + +type AddressChange struct { + From AddressPair + To AddressPair +} + +type AddressPair struct { + ID address.Address + PK address.Address +} diff --git a/chain/actors/builtin/init/init.go b/chain/actors/builtin/init/init.go index 60dbdf4fea4..466af6a6c0f 100644 --- a/chain/actors/builtin/init/init.go +++ b/chain/actors/builtin/init/init.go @@ -57,4 +57,6 @@ type State interface { // Sets the network's name. This should only be used on upgrade/fork. SetNetworkName(name string) error + + addressMap() (adt.Map, error) } diff --git a/chain/actors/builtin/init/v0.go b/chain/actors/builtin/init/v0.go index ceb87f97083..c019705b1e2 100644 --- a/chain/actors/builtin/init/v0.go +++ b/chain/actors/builtin/init/v0.go @@ -79,3 +79,7 @@ func (s *state0) Remove(addrs ...address.Address) (err error) { s.State.AddressMap = amr return nil } + +func (s *state0) addressMap() (adt.Map, error) { + return adt0.AsMap(s.store, s.AddressMap) +} diff --git a/chain/actors/builtin/init/v2.go b/chain/actors/builtin/init/v2.go index 5aa0ddc1839..420243be496 100644 --- a/chain/actors/builtin/init/v2.go +++ b/chain/actors/builtin/init/v2.go @@ -79,3 +79,7 @@ func (s *state2) Remove(addrs ...address.Address) (err error) { s.State.AddressMap = amr return nil } + +func (s *state2) addressMap() (adt.Map, error) { + return adt2.AsMap(s.store, s.AddressMap) +} diff --git a/chain/events/state/predicates.go b/chain/events/state/predicates.go index 99b8480dc52..551b776c221 100644 --- a/chain/events/state/predicates.go +++ b/chain/events/state/predicates.go @@ -1,7 +1,6 @@ package state import ( - "bytes" "context" "github.com/filecoin-project/lotus/chain/actors/builtin/miner" @@ -10,7 +9,6 @@ import ( "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/big" cbor "github.com/ipfs/go-ipld-cbor" - typegen "github.com/whyrusleeping/cbor-gen" "github.com/filecoin-project/lotus/api/apibstore" "github.com/filecoin-project/lotus/chain/actors/adt" @@ -419,179 +417,17 @@ type AddressPair struct { PK address.Address } -type InitActorAddressChanges struct { - Added []AddressPair - Modified []AddressChange - Removed []AddressPair -} - -type AddressChange struct { - From AddressPair - To AddressPair -} - type DiffInitActorStateFunc func(ctx context.Context, oldState init_.State, newState init_.State) (changed bool, user UserData, err error) -func (i *InitActorAddressChanges) AsKey(key string) (abi.Keyer, error) { - addr, err := address.NewFromBytes([]byte(key)) - if err != nil { - return nil, err - } - return abi.AddrKey(addr), nil -} - -func (i *InitActorAddressChanges) Add(key string, val *typegen.Deferred) error { - pkAddr, err := address.NewFromBytes([]byte(key)) - if err != nil { - return err - } - id := new(typegen.CborInt) - if err := id.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { - return err - } - idAddr, err := address.NewIDAddress(uint64(*id)) - if err != nil { - return err - } - i.Added = append(i.Added, AddressPair{ - ID: idAddr, - PK: pkAddr, - }) - return nil -} - -func (i *InitActorAddressChanges) Modify(key string, from, to *typegen.Deferred) error { - pkAddr, err := address.NewFromBytes([]byte(key)) - if err != nil { - return err - } - - fromID := new(typegen.CborInt) - if err := fromID.UnmarshalCBOR(bytes.NewReader(from.Raw)); err != nil { - return err - } - fromIDAddr, err := address.NewIDAddress(uint64(*fromID)) - if err != nil { - return err - } - - toID := new(typegen.CborInt) - if err := toID.UnmarshalCBOR(bytes.NewReader(to.Raw)); err != nil { - return err - } - toIDAddr, err := address.NewIDAddress(uint64(*toID)) - if err != nil { - return err - } - - i.Modified = append(i.Modified, AddressChange{ - From: AddressPair{ - ID: fromIDAddr, - PK: pkAddr, - }, - To: AddressPair{ - ID: toIDAddr, - PK: pkAddr, - }, - }) - return nil -} - -func (i *InitActorAddressChanges) Remove(key string, val *typegen.Deferred) error { - pkAddr, err := address.NewFromBytes([]byte(key)) - if err != nil { - return err - } - id := new(typegen.CborInt) - if err := id.UnmarshalCBOR(bytes.NewReader(val.Raw)); err != nil { - return err - } - idAddr, err := address.NewIDAddress(uint64(*id)) - if err != nil { - return err - } - i.Removed = append(i.Removed, AddressPair{ - ID: idAddr, - PK: pkAddr, - }) - return nil -} - func (sp *StatePredicates) OnAddressMapChange() DiffInitActorStateFunc { return func(ctx context.Context, oldState, newState init_.State) (changed bool, user UserData, err error) { - addressChanges := &InitActorAddressChanges{ - Added: []AddressPair{}, - Modified: []AddressChange{}, - Removed: []AddressPair{}, - } - - err = oldState.ForEachActor(func(oldId abi.ActorID, oldAddress address.Address) error { - oldIdAddress, err := address.NewIDAddress(uint64(oldId)) - if err != nil { - return err - } - - newIdAddress, found, err := newState.ResolveAddress(oldAddress) - if err != nil { - return err - } - - if !found { - addressChanges.Removed = append(addressChanges.Removed, AddressPair{ - ID: oldIdAddress, - PK: oldAddress, - }) - } - - if oldIdAddress != newIdAddress { - addressChanges.Modified = append(addressChanges.Modified, AddressChange{ - From: AddressPair{ - ID: oldIdAddress, - PK: oldAddress, - }, - To: AddressPair{ - ID: newIdAddress, - PK: oldAddress, - }, - }) - } - - return nil - }) - + addressChanges, err := init_.DiffAddressMap(oldState, newState) if err != nil { return false, nil, err } - - err = newState.ForEachActor(func(newId abi.ActorID, newAddress address.Address) error { - newIdAddress, err := address.NewIDAddress(uint64(newId)) - if err != nil { - return err - } - - _, found, err := newState.ResolveAddress(newAddress) - if err != nil { - return err - } - - if !found { - addressChanges.Added = append(addressChanges.Added, AddressPair{ - ID: newIdAddress, - PK: newAddress, - }) - } - - return nil - }) - - if err != nil { - return false, nil, err - } - - if len(addressChanges.Added)+len(addressChanges.Removed)+len(addressChanges.Modified) == 0 { + if len(addressChanges.Added)+len(addressChanges.Modified)+len(addressChanges.Removed) == 0 { return false, nil, nil } - return true, addressChanges, nil } }