Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(x/accounts): On-chain multisig #19988

Merged
merged 27 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
882fb6e
initial
facundomedica Mar 11, 2024
2e349fb
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into facu…
facundomedica Mar 14, 2024
17cd92e
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into facu…
facundomedica Mar 14, 2024
a99e516
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into facu…
facundomedica Mar 20, 2024
8d18378
progress
facundomedica Mar 21, 2024
52c42e4
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into facu…
facundomedica Mar 27, 2024
e027903
progress
facundomedica Mar 27, 2024
de459bb
progress
facundomedica Mar 27, 2024
7c3b59c
small update
facundomedica Mar 27, 2024
2983fa6
commit before starting with overhaul
facundomedica Mar 28, 2024
2f204ff
merge from main
facundomedica Apr 9, 2024
a7b8661
progress
facundomedica Apr 9, 2024
b374ec5
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into facu…
facundomedica Apr 22, 2024
2431bd9
small update
facundomedica Apr 23, 2024
ef2303b
progress
facundomedica Apr 25, 2024
cab1923
add events and queries
facundomedica Apr 25, 2024
8cd1447
fix
facundomedica Apr 25, 2024
4018918
fix
facundomedica Apr 25, 2024
5117ed9
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into facu…
facundomedica Apr 26, 2024
2b89d30
added tests
facundomedica Apr 26, 2024
fba4307
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into facu…
facundomedica Apr 26, 2024
ac97d6c
add docs
facundomedica Apr 26, 2024
746f61a
Merge branch 'main' into facu/accmultisig
facundomedica Apr 26, 2024
7375fc1
check dup members and prune votes after tallying. also some fixes
facundomedica Apr 30, 2024
0cdcc2c
Merge branch 'facu/accmultisig' of https://github.com/cosmos/cosmos-s…
facundomedica Apr 30, 2024
b57d3a1
godocs + cl
facundomedica Apr 30, 2024
5ba3d59
lint
facundomedica Apr 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9,246 changes: 9,246 additions & 0 deletions api/cosmos/accounts/defaults/multisig/v1/multisig.pulsar.go

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions x/accounts/accountstd/test_util.go
Expand Up @@ -25,3 +25,7 @@ func NewMockContext(
ctx, ss, accNumber, accountAddr, sender, funds, moduleExec, moduleExecUntyped, moduleQuery,
), ss
}

func SetSender(ctx context.Context, sender []byte) context.Context {
return implementation.SetSender(ctx, sender)
}
1 change: 1 addition & 0 deletions x/accounts/defaults/base/account.go
Expand Up @@ -38,6 +38,7 @@ func NewAccount(name string, handlerMap *signing.HandlerMap) accountstd.AccountC
Sequence: collections.NewSequence(deps.SchemaBuilder, SequencePrefix, "sequence"),
addrCodec: deps.AddressCodec,
signingHandlers: handlerMap,
hs: deps.Environment.HeaderService,
}, nil
}
}
Expand Down
153 changes: 153 additions & 0 deletions x/accounts/defaults/multisig/README.md
@@ -0,0 +1,153 @@
# Multisig Accounts


* [State](#state)
* [Config](#config)
* [Proposal](#proposal)
* [Members](#members)
* [Methods](#methods)
* [MsgInit](#msginit)
* [MsgUpdateConfig](#msgupdateconfig)
* [MsgCreateProposal](#msgcreateproposal)
* [MsgVote](#msgvote)
* [MsgExecuteProposal](#msgexecuteproposal)
Comment on lines +9 to +13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation of list items is inconsistent with Markdown standards.

-    * [MsgInit](#msginit)
-    * [MsgUpdateConfig](#msgupdateconfig)
-    * [MsgCreateProposal](#msgcreateproposal)
-    * [MsgVote](#msgvote)
-    * [MsgExecuteProposal](#msgexecuteproposal)
+  * [MsgInit](#msginit)
+  * [MsgUpdateConfig](#msgupdateconfig)
+  * [MsgCreateProposal](#msgcreateproposal)
+  * [MsgVote](#msgvote)
+  * [MsgExecuteProposal](#msgexecuteproposal)

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
* [MsgInit](#msginit)
* [MsgUpdateConfig](#msgupdateconfig)
* [MsgCreateProposal](#msgcreateproposal)
* [MsgVote](#msgvote)
* [MsgExecuteProposal](#msgexecuteproposal)
* [MsgInit](#msginit)
* [MsgUpdateConfig](#msgupdateconfig)
* [MsgCreateProposal](#msgcreateproposal)
* [MsgVote](#msgvote)
* [MsgExecuteProposal](#msgexecuteproposal)


The x/accounts/defaults/multisig module provides the implementation for multisig accounts within the x/accounts module.

## State

The multisig account keeps its members as a map of addresses and weights (`<[]byte, uint64>`), a config struct, a map of proposals and a map of votes.

```go
type Account struct {
Members collections.Map[[]byte, uint64]
Sequence collections.Sequence
Config collections.Item[v1.Config]

addrCodec address.Codec
headerService header.Service
eventService event.Service

Proposals collections.Map[uint64, v1.Proposal]
Votes collections.Map[collections.Pair[uint64, []byte], int32] // key: proposalID + voter address
}
Comment on lines +23 to +33
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace hard tabs with spaces to maintain consistency in indentation.

-	Members  collections.Map[[]byte, uint64]
-	Sequence collections.Sequence
-	Config   collections.Item[v1.Config]
-	addrCodec     address.Codec
-	headerService header.Service
-	eventService  event.Service
-	Proposals collections.Map[uint64, v1.Proposal]
-	Votes     collections.Map[collections.Pair[uint64, []byte], int32] // key: proposalID + voter address
+  Members  collections.Map[[]byte, uint64]
+  Sequence collections.Sequence
+  Config   collections.Item[v1.Config]
+  addrCodec     address.Codec
+  headerService header.Service
+  eventService  event.Service
+  Proposals collections.Map[uint64, v1.Proposal]
+  Votes     collections.Map[collections.Pair[uint64, []byte], int32] // key: proposalID + voter address

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
Members collections.Map[[]byte, uint64]
Sequence collections.Sequence
Config collections.Item[v1.Config]
addrCodec address.Codec
headerService header.Service
eventService event.Service
Proposals collections.Map[uint64, v1.Proposal]
Votes collections.Map[collections.Pair[uint64, []byte], int32] // key: proposalID + voter address
}
Members collections.Map[[]byte, uint64]
Sequence collections.Sequence
Config collections.Item[v1.Config]
addrCodec address.Codec
headerService header.Service
eventService event.Service
Proposals collections.Map[uint64, v1.Proposal]
Votes collections.Map[collections.Pair[uint64, []byte], int32] // key: proposalID + voter address

```

### Config

The config contains the basic rules defining how the multisig will work. All of these fields can be modified afterwards by calling [MsgUpdateConfig](#msgupdateconfig).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using "afterward" instead of "afterwards" to align with American English conventions.

- All of these fields can be modified afterwards by calling [MsgUpdateConfig](#msgupdateconfig).
+ All of these fields can be modified afterward by calling [MsgUpdateConfig](#msgupdateconfig).

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
The config contains the basic rules defining how the multisig will work. All of these fields can be modified afterwards by calling [MsgUpdateConfig](#msgupdateconfig).
The config contains the basic rules defining how the multisig will work. All of these fields can be modified afterward by calling [MsgUpdateConfig](#msgupdateconfig).


```protobuf
message Config {
int64 threshold = 1;

int64 quorum = 2;

// voting_period is the duration in seconds for the voting period.
int64 voting_period = 3;

// revote defines if members can change their vote.
bool revote = 4;

// early_execution defines if the multisig can be executed before the voting period ends.
bool early_execution = 5;
}
```

### Proposal

The proposal contains the title, summary, messages and the status of the proposal. The messages are stored as `google.protobuf.Any` to allow for any type of message to be stored.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a space after the period for better readability.

- The proposal contains the title, summary, messages and the status of the proposal. The messages are stored as `google.protobuf.Any` to allow for any type of message to be stored.
+ The proposal contains the title, summary, messages and the status of the proposal. The messages are stored as `google.protobuf.Any` to allow for any type of message to be stored.

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
The proposal contains the title, summary, messages and the status of the proposal. The messages are stored as `google.protobuf.Any` to allow for any type of message to be stored.
The proposal contains the title, summary, messages and the status of the proposal. The messages are stored as `google.protobuf.Any` to allow for any type of message to be stored.


```protobuf
message Proposal {
string title = 1;
string summary = 2;
repeated google.protobuf.Any messages = 3;

// if true, the proposal will execute as soon as the quorum is reached (last voter will execute).
bool execute = 4;

// voting_period_end will be set by the account when the proposal is created.
int64 voting_period_end = 5;

ProposalStatus status = 6;
}
```

### Members

Members are stored as a map of addresses and weights. The weight is used to determine the voting power of the member.


## Methods

### MsgInit

The `MsgInit` message initializes a multisig account with the given members and config.

```protobuf
message MsgInit {
repeated Member members = 1;
Config Config = 2;
}
```

### MsgUpdateConfig

The `MsgUpdateConfig` message updates the config of the multisig account. Only the members that are changing are required, and if their weight is 0, they are removed. If the config is nil, then it will not be updated.

```protobuf
message MsgUpdateConfig {
// only the members that are changing are required, if their weight is 0, they are removed.
repeated Member update_members = 1;

// not all fields from Config can be changed
Config Config = 2;
}
```

### MsgCreateProposal

Only a member can create a proposal. The proposal will be stored in the account and the members will be able to vote on it.

If a voting period is not set, the proposal will be created using the voting period from the config. If the proposal has a voting period, it will be used instead.

```protobuf
message MsgCreateProposal {
Proposal proposal = 1;
}
```

### MsgVote

The `MsgVote` message allows a member to vote on a proposal. The vote can be either `Yes`, `No` or `Abstain`.

```protobuf
message MsgVote {
uint64 proposal_id = 1;
VoteOption vote = 2;
}

// VoteOption enumerates the valid vote options for a given proposal.
enum VoteOption {
// VOTE_OPTION_UNSPECIFIED defines a no-op vote option.
VOTE_OPTION_UNSPECIFIED = 0;
// VOTE_OPTION_YES defines the yes proposal vote option.
VOTE_OPTION_YES = 1;
// VOTE_OPTION_ABSTAIN defines the abstain proposal vote option.
VOTE_OPTION_ABSTAIN = 2;
// VOTE_OPTION_NO defines the no proposal vote option.
VOTE_OPTION_NO = 3;
}
```


### MsgExecuteProposal

The `MsgExecuteProposal` message allows a member to execute a proposal. The proposal must have reached the quorum and the voting period must have ended.

```protobuf
message MsgExecuteProposal {
uint64 proposal_id = 1;
}
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure the file ends with a single newline character.