Implement rest of the methods

License: MIT
Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
This commit is contained in:
Jakub Sztandera 2019-07-29 23:19:34 +02:00
parent a48d38d976
commit d2edad5d04

View File

@ -1,11 +1,24 @@
package actors
import (
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/go-lotus/chain/actors/aerrors"
"github.com/filecoin-project/go-lotus/chain/address"
"github.com/filecoin-project/go-lotus/chain/types"
)
func init() {
cbor.RegisterCborType(MultiSigActorState{})
cbor.RegisterCborType(MultiSigConstructorParams{})
cbor.RegisterCborType(MultiSigProposeParams{})
cbor.RegisterCborType(MultiSigTxID{})
cbor.RegisterCborType(MultiSigSigner{})
cbor.RegisterCborType(MultiSigSwapSignerParams{})
cbor.RegisterCborType(MultiSigChangeReqParams{})
}
type MultiSigActor struct{}
type MultiSigActorState struct {
Signers []address.Address
@ -47,6 +60,16 @@ type MTransaction struct {
RetCode uint8
}
func (tx MTransaction) Active() ActorError {
if tx.Complete {
return aerrors.New(2, "transaction already completed")
}
if tx.Canceled {
return aerrors.New(3, "transaction canceled")
}
return nil
}
type musigMethods struct {
MultiSigConstructor uint64
Propose uint64
@ -64,6 +87,14 @@ var MultiSigMethods = musigMethods{1, 2, 3, 4, 5, 6, 7, 8, 9}
func (msa MultiSigActor) Exports() []interface{} {
return []interface{}{
1: msa.MultiSigConstructor,
2: msa.Approve,
3: msa.Propose,
4: msa.Cancel,
//5: msa.ClearCompleted,
6: msa.AddSigner,
7: msa.RemoveSigner,
8: msa.SwapSigner,
9: msa.ChangeRequirement,
}
}
@ -96,18 +127,48 @@ type MultiSigProposeParams struct {
Params []byte
}
func (MultiSigActor) Propose(act *types.Actor, vmctx types.VMContext,
params *MultiSigProposeParams) ([]byte, ActorError) {
func (MultiSigActor) load(vmctx types.VMContext) (cid.Cid, *MultiSigActorState, ActorError) {
var self MultiSigActorState
head := vmctx.Storage().GetHead()
err := vmctx.Storage().Get(head, &self)
if err != nil {
return nil, aerrors.Wrap(err, "could not get self")
return cid.Undef, nil, aerrors.Wrap(err, "could not get self")
}
return head, &self, nil
}
func (msa MultiSigActor) loadAndVerify(vmctx types.VMContext) (cid.Cid, *MultiSigActorState, ActorError) {
head, self, err := msa.load(vmctx)
if err != nil {
return cid.Undef, nil, err
}
if !self.isSigner(vmctx.Message().From) {
return nil, aerrors.New(1, "not authorized")
return cid.Undef, nil, aerrors.New(1, "not authorized")
}
return head, self, nil
}
func (MultiSigActor) save(vmctx types.VMContext, oldHead cid.Cid, self *MultiSigActorState) ActorError {
newHead, err := vmctx.Storage().Put(self)
if err != nil {
return aerrors.Wrap(err, "could not put new head")
}
err = vmctx.Storage().Commit(oldHead, newHead)
if err != nil {
return aerrors.Wrap(err, "could not commit new head")
}
return nil
}
func (msa MultiSigActor) Propose(act *types.Actor, vmctx types.VMContext,
params *MultiSigProposeParams) ([]byte, ActorError) {
head, self, err := msa.loadAndVerify(vmctx)
if err != nil {
return nil, err
}
txid := self.NextTxId
@ -133,43 +194,29 @@ func (MultiSigActor) Propose(act *types.Actor, vmctx types.VMContext,
self.Transactions = append(self.Transactions, tx)
newHead, err := vmctx.Storage().Put(self)
err = msa.save(vmctx, head, self)
if err != nil {
return nil, aerrors.Wrap(err, "could not put new head")
}
err = vmctx.Storage().Commit(head, newHead)
if err != nil {
return nil, aerrors.Wrap(err, "could not commit new head")
return nil, aerrors.Wrap(err, "saving state")
}
return SerializeParams(tx.TxID)
}
type MultiSigApproveParams struct {
type MultiSigTxID struct {
TxID uint64
}
func (MultiSigActor) Approve(act *types.Actor, vmctx types.VMContext,
params *MultiSigApproveParams) ([]byte, ActorError) {
var self MultiSigActorState
head := vmctx.Storage().GetHead()
func (msa MultiSigActor) Approve(act *types.Actor, vmctx types.VMContext,
params *MultiSigTxID) ([]byte, ActorError) {
err := vmctx.Storage().Get(head, &self)
head, self, err := msa.loadAndVerify(vmctx)
if err != nil {
return nil, aerrors.Wrap(err, "could not get self")
}
if !self.isSigner(vmctx.Message().From) {
return nil, aerrors.New(1, "not authorized")
return nil, err
}
tx := self.getTransaction(params.TxID)
if tx.Complete {
return nil, aerrors.New(2, "transaction already completed")
}
if tx.Canceled {
return nil, aerrors.New(3, "transaction canceled")
if err := tx.Active(); err != nil {
return nil, aerrors.Wrap(err, "could not approve")
}
for _, signer := range tx.Approved {
@ -198,3 +245,146 @@ func (MultiSigActor) Approve(act *types.Actor, vmctx types.VMContext,
return nil, nil
}
func (msa MultiSigActor) Cancel(act *types.Actor, vmctx types.VMContext,
params *MultiSigTxID) ([]byte, ActorError) {
head, self, err := msa.loadAndVerify(vmctx)
if err != nil {
return nil, err
}
tx := self.getTransaction(params.TxID)
if err := tx.Active(); err != nil {
return nil, aerrors.Wrap(err, "could not cancel")
}
proposer := tx.Approved[0]
if proposer != vmctx.Message().From && self.isSigner(proposer) {
return nil, aerrors.New(4, "cannot cancel another signers transaction")
}
tx.Canceled = true
newHead, err := vmctx.Storage().Put(self)
if err != nil {
return nil, aerrors.Wrap(err, "could not put new head")
}
err = vmctx.Storage().Commit(head, newHead)
if err != nil {
return nil, aerrors.Wrap(err, "could not commit new head")
}
return nil, nil
}
type MultiSigSigner struct {
Signer address.Address
}
func (msa MultiSigActor) AddSigner(act *types.Actor, vmctx types.VMContext,
params *MultiSigSigner) ([]byte, ActorError) {
head, self, err := msa.load(vmctx)
if err != nil {
return nil, err
}
msg := vmctx.Message()
if msg.From != msg.To {
return nil, aerrors.New(4, "add signer must be called by wallet itself")
}
if self.isSigner(params.Signer) {
return nil, aerrors.New(5, "new address is already a signer")
}
self.Signers = append(self.Signers, params.Signer)
return nil, msa.save(vmctx, head, self)
}
func (msa MultiSigActor) RemoveSigner(act *types.Actor, vmctx types.VMContext,
params *MultiSigSigner) ([]byte, ActorError) {
head, self, err := msa.load(vmctx)
if err != nil {
return nil, err
}
msg := vmctx.Message()
if msg.From != msg.To {
return nil, aerrors.New(4, "remove signer must be called by wallet itself")
}
if !self.isSigner(params.Signer) {
return nil, aerrors.New(5, "given address was not a signer")
}
newSigners := make([]address.Address, 0, len(self.Signers)-1)
for _, s := range self.Signers {
if s != params.Signer {
newSigners = append(newSigners, s)
}
}
self.Signers = newSigners
return nil, msa.save(vmctx, head, self)
}
type MultiSigSwapSignerParams struct {
From address.Address
To address.Address
}
func (msa MultiSigActor) SwapSigner(act *types.Actor, vmctx types.VMContext,
params *MultiSigSwapSignerParams) ([]byte, ActorError) {
head, self, err := msa.load(vmctx)
if err != nil {
return nil, err
}
msg := vmctx.Message()
if msg.From != msg.To {
return nil, aerrors.New(4, "swap signer must be called by wallet itself")
}
if !self.isSigner(params.From) {
return nil, aerrors.New(5, "given old address was not a signer")
}
if self.isSigner(params.To) {
return nil, aerrors.New(6, "given new address was already a signer")
}
newSigners := make([]address.Address, 0, len(self.Signers)-1)
for _, s := range self.Signers {
if s != params.From {
newSigners = append(newSigners, s)
}
}
newSigners = append(newSigners, params.To)
self.Signers = newSigners
return nil, msa.save(vmctx, head, self)
}
type MultiSigChangeReqParams struct {
Req uint32
}
func (msa MultiSigActor) ChangeRequirement(act *types.Actor, vmctx types.VMContext,
params *MultiSigChangeReqParams) ([]byte, ActorError) {
head, self, err := msa.load(vmctx)
if err != nil {
return nil, err
}
msg := vmctx.Message()
if msg.From != msg.To {
return nil, aerrors.New(4, "change requirement must be called by wallet itself")
}
if params.Req < 1 {
return nil, aerrors.New(5, "requirement must be at least 1")
}
self.Required = params.Req
return nil, msa.save(vmctx, head, self)
}