Implement rest of the methods
License: MIT Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
This commit is contained in:
parent
a48d38d976
commit
d2edad5d04
@ -1,11 +1,24 @@
|
|||||||
package actors
|
package actors
|
||||||
|
|
||||||
import (
|
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/actors/aerrors"
|
||||||
"github.com/filecoin-project/go-lotus/chain/address"
|
"github.com/filecoin-project/go-lotus/chain/address"
|
||||||
"github.com/filecoin-project/go-lotus/chain/types"
|
"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 MultiSigActor struct{}
|
||||||
type MultiSigActorState struct {
|
type MultiSigActorState struct {
|
||||||
Signers []address.Address
|
Signers []address.Address
|
||||||
@ -47,6 +60,16 @@ type MTransaction struct {
|
|||||||
RetCode uint8
|
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 {
|
type musigMethods struct {
|
||||||
MultiSigConstructor uint64
|
MultiSigConstructor uint64
|
||||||
Propose uint64
|
Propose uint64
|
||||||
@ -64,6 +87,14 @@ var MultiSigMethods = musigMethods{1, 2, 3, 4, 5, 6, 7, 8, 9}
|
|||||||
func (msa MultiSigActor) Exports() []interface{} {
|
func (msa MultiSigActor) Exports() []interface{} {
|
||||||
return []interface{}{
|
return []interface{}{
|
||||||
1: msa.MultiSigConstructor,
|
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
|
Params []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (MultiSigActor) Propose(act *types.Actor, vmctx types.VMContext,
|
func (MultiSigActor) load(vmctx types.VMContext) (cid.Cid, *MultiSigActorState, ActorError) {
|
||||||
params *MultiSigProposeParams) ([]byte, ActorError) {
|
|
||||||
var self MultiSigActorState
|
var self MultiSigActorState
|
||||||
head := vmctx.Storage().GetHead()
|
head := vmctx.Storage().GetHead()
|
||||||
|
|
||||||
err := vmctx.Storage().Get(head, &self)
|
err := vmctx.Storage().Get(head, &self)
|
||||||
if err != nil {
|
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) {
|
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
|
txid := self.NextTxId
|
||||||
@ -133,43 +194,29 @@ func (MultiSigActor) Propose(act *types.Actor, vmctx types.VMContext,
|
|||||||
|
|
||||||
self.Transactions = append(self.Transactions, tx)
|
self.Transactions = append(self.Transactions, tx)
|
||||||
|
|
||||||
newHead, err := vmctx.Storage().Put(self)
|
err = msa.save(vmctx, head, self)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, aerrors.Wrap(err, "could not put new head")
|
return nil, aerrors.Wrap(err, "saving state")
|
||||||
}
|
|
||||||
err = vmctx.Storage().Commit(head, newHead)
|
|
||||||
if err != nil {
|
|
||||||
return nil, aerrors.Wrap(err, "could not commit new head")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return SerializeParams(tx.TxID)
|
return SerializeParams(tx.TxID)
|
||||||
}
|
}
|
||||||
|
|
||||||
type MultiSigApproveParams struct {
|
type MultiSigTxID struct {
|
||||||
TxID uint64
|
TxID uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (MultiSigActor) Approve(act *types.Actor, vmctx types.VMContext,
|
func (msa MultiSigActor) Approve(act *types.Actor, vmctx types.VMContext,
|
||||||
params *MultiSigApproveParams) ([]byte, ActorError) {
|
params *MultiSigTxID) ([]byte, ActorError) {
|
||||||
var self MultiSigActorState
|
|
||||||
head := vmctx.Storage().GetHead()
|
|
||||||
|
|
||||||
err := vmctx.Storage().Get(head, &self)
|
head, self, err := msa.loadAndVerify(vmctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, aerrors.Wrap(err, "could not get self")
|
return nil, err
|
||||||
}
|
|
||||||
|
|
||||||
if !self.isSigner(vmctx.Message().From) {
|
|
||||||
return nil, aerrors.New(1, "not authorized")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tx := self.getTransaction(params.TxID)
|
tx := self.getTransaction(params.TxID)
|
||||||
|
if err := tx.Active(); err != nil {
|
||||||
if tx.Complete {
|
return nil, aerrors.Wrap(err, "could not approve")
|
||||||
return nil, aerrors.New(2, "transaction already completed")
|
|
||||||
}
|
|
||||||
if tx.Canceled {
|
|
||||||
return nil, aerrors.New(3, "transaction canceled")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, signer := range tx.Approved {
|
for _, signer := range tx.Approved {
|
||||||
@ -198,3 +245,146 @@ func (MultiSigActor) Approve(act *types.Actor, vmctx types.VMContext,
|
|||||||
|
|
||||||
return nil, nil
|
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)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user