Skip to content

Commit

Permalink
sign and complete transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
cbarraford committed Jul 2, 2019
1 parent e3cb76b commit 3407441
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 23 deletions.
29 changes: 17 additions & 12 deletions x/multisig/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,24 @@ const (
)

var (
NewMsgCreateWallet = types.NewMsgCreateWallet
NewMultiSigWallet = types.NewMultiSigWallet
NewMsgCreateTransaction = types.NewMsgCreateTransaction
NewTransaction = types.NewTransaction
ModuleCdc = types.ModuleCdc
RegisterCodec = types.RegisterCodec
NewMsgCreateWallet = types.NewMsgCreateWallet
NewMultiSigWallet = types.NewMultiSigWallet
NewMsgCreateTransaction = types.NewMsgCreateTransaction
NewMsgSignTransaction = types.NewMsgSignTransaction
NewMsgCompleteTransaction = types.NewMsgCompleteTransaction
NewTransaction = types.NewTransaction
ModuleCdc = types.ModuleCdc
RegisterCodec = types.RegisterCodec
)

type (
MsgCreateWallet = types.MsgCreateWallet
MsgCreateTransaction = types.MsgCreateTransaction
QueryResResolve = types.QueryResResolve
QueryResNames = types.QueryResNames
Transaction = types.Transaction
MultiSigWallet = types.MultiSigWallet
MsgCreateWallet = types.MsgCreateWallet
MsgCreateTransaction = types.MsgCreateTransaction
MsgSignTransaction = types.MsgSignTransaction
MsgCompleteTransaction = types.MsgCompleteTransaction
QueryResResolve = types.QueryResResolve
QueryResNames = types.QueryResNames
Transaction = types.Transaction
Signature = types.Signature
MultiSigWallet = types.MultiSigWallet
)
60 changes: 57 additions & 3 deletions x/multisig/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ func NewHandler(keeper Keeper) sdk.Handler {
switch msg := msg.(type) {
case MsgCreateWallet:
return handleMsgCreateWallet(ctx, keeper, msg)
case MsgCreateTransaction:
return handleMsgCreateTransaction(ctx, keeper, msg)
case MsgSignTransaction:
return handleMsgSignTransaction(ctx, keeper, msg)
case MsgCompleteTransaction:
return handleMsgCompleteTransaction(ctx, keeper, msg)
default:
errMsg := fmt.Sprintf("Unrecognized multisig Msg type: %v", msg.Type())
return sdk.ErrUnknownRequest(errMsg).Result()
Expand All @@ -33,7 +39,7 @@ func handleMsgCreateWallet(ctx sdk.Context, keeper Keeper, msg MsgCreateWallet)
fmt.Sprintf("Error creating new wallet: %s", err.Error()),
).Result()
}
keeper.CreateWallet(ctx, wallet)
keeper.SetWallet(ctx, wallet)
return sdk.Result{}
}

Expand All @@ -44,7 +50,55 @@ func handleMsgCreateTransaction(ctx sdk.Context, keeper Keeper, msg MsgCreateTra
if !transaction.From.Empty() {
return sdk.ErrUnauthorized("Transaction already exists").Result()
}
transaction = NewTransaction(msg.From, msg.To, msg.Coins, ctx.BlockHeight())
keeper.CreateTransaction(ctx, transaction)
wallet := keeper.GetWallet(ctx, msg.From.String())
if !wallet.Address.Empty() {
return sdk.ErrUnauthorized("No registered multi-signature wallet for 'from' address").Result()
}
sigs := make([]Signature, len(wallet.PubKeys))
for i, pubkey := range wallet.PubKeys {
var err error
sigs[i].PubKey, err = sdk.GetAccPubKeyBech32(pubkey)
if err != nil {
return sdk.ErrUnknownRequest(
fmt.Sprintf("Error creating new transaction: %s", err.Error()),
).Result()
}
}
transaction = NewTransaction(
msg.From,
msg.To,
msg.Coins,
ctx.BlockHeight(),
sigs,
)
keeper.SetTransaction(ctx, transaction)
return sdk.Result{}
}

// Handle a message to sign transaction
func handleMsgSignTransaction(ctx sdk.Context, keeper Keeper, msg MsgSignTransaction) sdk.Result {
var err error
transaction := keeper.GetTransaction(ctx, msg.UUID)
if !transaction.From.Empty() {
return sdk.ErrUnauthorized("No transaction found.").Result()
}
err = transaction.AddSignature(msg.Signature)
if err != nil {
return sdk.ErrUnauthorized(
fmt.Sprintf("Failed to sign transaction: %s", err.Error()),
).Result()
}
keeper.SetTransaction(ctx, transaction)
return sdk.Result{}
}

// Handle a message to complete transaction
func handleMsgCompleteTransaction(ctx sdk.Context, keeper Keeper, msg MsgCompleteTransaction) sdk.Result {
transaction := keeper.GetTransaction(ctx, msg.UUID)
if !transaction.From.Empty() {
return sdk.ErrUnauthorized("No transaction found.").Result()
}
transaction.TxID = msg.TxID
keeper.SetTransaction(ctx, transaction)
return sdk.Result{}
}
4 changes: 2 additions & 2 deletions x/multisig/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (k Keeper) GetWallet(ctx sdk.Context, address string) MultiSigWallet {
}

// Sets the entire wallet metadata struct for a multisig wallet
func (k Keeper) CreateWallet(ctx sdk.Context, wallet MultiSigWallet) {
func (k Keeper) SetWallet(ctx sdk.Context, wallet MultiSigWallet) {
address := fmt.Sprintf("wallet-%s", wallet.Address.String())
store := ctx.KVStore(k.storeKey)
store.Set([]byte(address), k.cdc.MustMarshalBinaryBare(wallet))
Expand All @@ -65,7 +65,7 @@ func (k Keeper) GetTransaction(ctx sdk.Context, uid uuid.UUID) Transaction {
return transaction
}

func (k Keeper) CreateTransaction(ctx sdk.Context, transaction Transaction) {
func (k Keeper) SetTransaction(ctx sdk.Context, transaction Transaction) {
key := fmt.Sprintf("transaction-%s", transaction.UUID)
store := ctx.KVStore(k.storeKey)
store.Set([]byte(key), k.cdc.MustMarshalBinaryBare(transaction))
Expand Down
85 changes: 85 additions & 0 deletions x/multisig/types/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,88 @@ func (msg MsgCreateTransaction) GetSignBytes() []byte {
func (msg MsgCreateTransaction) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{msg.From}
}

// MsgSignTransaction defines a SignTransaction message
type MsgSignTransaction struct {
UUID uuid.UUID `json:"uuid"`
Signature Signature `json:"signature"`
}

// NewMsgSignTransaction is a constructor function for MsgCreateTransaction
func NewMsgSignTransaction(uid uuid.UUID, sig Signature) MsgSignTransaction {
return MsgSignTransaction{
UUID: uid,
Signature: sig,
}
}

// Route should return the name of the module
func (msg MsgSignTransaction) Route() string { return RouterKey }

// Type should return the action
func (msg MsgSignTransaction) Type() string { return "sign_transaction" }

// ValidateBasic runs stateless checks on the message
func (msg MsgSignTransaction) ValidateBasic() sdk.Error {
if len(msg.UUID) == 0 {
return sdk.ErrUnknownRequest("UUID cannot be blank")
}
if len(msg.Signature.PubKey.Bytes()) == 0 {
return sdk.ErrUnknownRequest("Pubkey cannot be blank")
}
if msg.Signature.Signature == "" {
return sdk.ErrUnknownRequest("Signature cannot be blank")
}
return nil
}

// GetSignBytes encodes the message for signing
func (msg MsgSignTransaction) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg))
}

// GetSigners defines whose signature is required
func (msg MsgSignTransaction) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{}
}

// MsgCompleteTransaction defines complete a transaction
type MsgCompleteTransaction struct {
UUID uuid.UUID `json:"uuid"`
TxID string `json:"tx_id"`
}

// NewMsgCompleteTransaction is a constructor function for MsgCompleteTransaction
func NewMsgCompleteTransaction(uid uuid.UUID, txID string) MsgCompleteTransaction {
return MsgCompleteTransaction{
UUID: uid,
TxID: txID,
}
}

// Route should return the name of the module
func (msg MsgCompleteTransaction) Route() string { return RouterKey }

// Type should return the action
func (msg MsgCompleteTransaction) Type() string { return "sign_transaction" }

// ValidateBasic runs stateless checks on the message
func (msg MsgCompleteTransaction) ValidateBasic() sdk.Error {
if len(msg.UUID) == 0 {
return sdk.ErrUnknownRequest("UUID cannot be blank")
}
if msg.TxID == "" {
return sdk.ErrUnknownRequest("Transaction ID cannot be blank")
}
return nil
}

// GetSignBytes encodes the message for signing
func (msg MsgCompleteTransaction) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(msg))
}

// GetSigners defines whose signature is required
func (msg MsgCompleteTransaction) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{}
}
25 changes: 19 additions & 6 deletions x/multisig/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,19 +89,32 @@ type Transaction struct {
To sdk.AccAddress `json:"to_address"`
Coins sdk.Coins `json:"coins"`
Signatures []Signature `json:"signatures"`
TxID string `json:"tx_id"`
CreatedAt int64 `json:"created_at"` // block height
}

func NewTransaction(from, to sdk.AccAddress, coins sdk.Coins, height int64) Transaction {
func NewTransaction(from, to sdk.AccAddress, coins sdk.Coins, height int64, signatures []Signature) Transaction {
return Transaction{
UUID: uuid.New(),
From: from,
To: to,
Coins: coins,
CreatedAt: height,
UUID: uuid.New(),
From: from,
To: to,
Coins: coins,
CreatedAt: height,
Signatures: signatures,
}
}

// adds a signature to Transaction. If signature already exists, overwrite
func (t *Transaction) AddSignature(input Signature) error {
for i, sig := range t.Signatures {
if sig.PubKey == input.PubKey {
t.Signatures[i].Signature = input.Signature
return nil
}
}
return fmt.Errorf("Unable to add signature")
}

func (t Transaction) String() string {
return strings.TrimSpace(
fmt.Sprintf(
Expand Down

0 comments on commit 3407441

Please sign in to comment.