Skip to content

Commit 903b975

Browse files
authored
Use owners instead of public keys. (#3160)
## Motivation For #3162 we need to stop using `ChainOwnership` as a lookup table for public keys. In general, we are using `PublicKey` in several places where we should be using the `Owner` type. ## Proposal Remove public keys from `ChainOwnership`. Add the signer's public key directly to the `BlockProposal` instead. When creating key pairs, assigning chains and changing chain ownership via CLI commands, node service mutations or system API calls, use `Owner` instead of `PublicKey`. ## Test Plan Several tests have been updated. ## Release Plan - Nothing to do / These changes follow the usual release cycle. ## Links - Closes #3165. - [reviewer checklist](https://github.com/linera-io/linera-protocol/blob/main/CONTRIBUTING.md#reviewer-checklist)
1 parent 6a8789e commit 903b975

File tree

50 files changed

+492
-614
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+492
-614
lines changed

CLI.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ A Byzantine-fault tolerant sidechain with low-latency finality and high throughp
9292
* `publish-and-create` — Create an application, and publish the required bytecode
9393
* `request-application` — Request an application from another chain, so it can be used on this one
9494
* `keygen` — Create an unassigned key-pair
95-
* `assign` — Link a key owned by the wallet to a chain that was just created for that key
95+
* `assign` — Link an owner with a key pair in the wallet to a chain that was created for that owner
9696
* `retry-pending-block` — Retry a block we unsuccessfully tried to propose earlier
9797
* `wallet` — Show the contents of the wallet
9898
* `project` — Manage Linera projects
@@ -178,7 +178,7 @@ Open (i.e. activate) a new chain deriving the UID from an existing one
178178
###### **Options:**
179179

180180
* `--from <CHAIN_ID>` — Chain ID (must be one of our chains)
181-
* `--to-public-key <PUBLIC_KEY>`Public key of the new owner (otherwise create a key pair and remember it)
181+
* `--owner <OWNER>`The new owner (otherwise create a key pair and remember it)
182182
* `--initial-balance <BALANCE>` — The initial balance of the new chain. This is subtracted from the parent chain's balance
183183

184184
Default value: `0`
@@ -194,8 +194,8 @@ Open (i.e. activate) a new multi-owner chain deriving the UID from an existing o
194194
###### **Options:**
195195

196196
* `--from <CHAIN_ID>` — Chain ID (must be one of our chains)
197-
* `--super-owner-public-keys <SUPER_OWNER_PUBLIC_KEYS>`Public keys of the new super owners
198-
* `--owner-public-keys <OWNER_PUBLIC_KEYS>`Public keys of the new regular owners
197+
* `--super-owners <SUPER_OWNERS>`The new super owners
198+
* `--owners <OWNERS>`The new regular owners
199199
* `--owner-weights <OWNER_WEIGHTS>` — Weights for the new owners.
200200

201201
If they are specified there must be exactly one weight for each owner. If no weights are given, every owner will have weight 100.
@@ -230,8 +230,8 @@ Specify the complete set of new owners, by public key. Existing owners that are
230230
###### **Options:**
231231

232232
* `--chain-id <CHAIN_ID>` — The ID of the chain whose owners will be changed
233-
* `--super-owner-public-keys <SUPER_OWNER_PUBLIC_KEYS>`Public keys of the new super owners
234-
* `--owner-public-keys <OWNER_PUBLIC_KEYS>`Public keys of the new regular owners
233+
* `--super-owners <SUPER_OWNERS>`The new super owners
234+
* `--owners <OWNERS>`The new regular owners
235235
* `--owner-weights <OWNER_WEIGHTS>` — Weights for the new owners.
236236

237237
If they are specified there must be exactly one weight for each owner. If no weights are given, every owner will have weight 100.
@@ -679,13 +679,13 @@ Create an unassigned key-pair
679679

680680
## `linera assign`
681681

682-
Link a key owned by the wallet to a chain that was just created for that key
682+
Link an owner with a key pair in the wallet to a chain that was created for that owner
683683

684-
**Usage:** `linera assign --key <KEY> --message-id <MESSAGE_ID>`
684+
**Usage:** `linera assign --owner <OWNER> --message-id <MESSAGE_ID>`
685685

686686
###### **Options:**
687687

688-
* `--key <KEY>` — The public key to assign
688+
* `--owner <OWNER>` — The owner to assign
689689
* `--message-id <MESSAGE_ID>` — The ID of the message that created the chain. (This uniquely describes the chain and where it was created.)
690690

691691

examples/amm/README.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -257,13 +257,10 @@ In addition, we make an AMM operation per block mandatory, so owners cannot spam
257257
with empty blocks.
258258

259259
```bash
260-
PUB_KEY_AMM=fcf518d56455283ace2bbc11c71e684eb58af81bc98b96a18129e825ce24ea84
261-
PUB_KEY_2=ca909dcf60df014c166be17eb4a9f6e2f9383314a57510206a54cd841ade455e
262-
263260
kill %% && sleep 1 # Kill the service so we can use CLI commands for chain 1.
264261

265262
linera --wait-for-outgoing-messages change-ownership \
266-
--owner-public-keys $PUB_KEY_AMM $PUB_KEY_2
263+
--owners $OWNER_AMM $OWNER_2
267264

268265
linera --wait-for-outgoing-messages change-application-permissions \
269266
--execute-operations $AMM_APPLICATION_ID \

examples/hex-game/README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ APP_ID=$(linera -w0 --wait-for-outgoing-messages \
6161
\"blockDelay\": 100000000
6262
}")
6363

64-
PUB_KEY_1=$(linera -w0 keygen)
65-
PUB_KEY_2=$(linera -w1 keygen)
64+
OWNER_1=$(linera -w0 keygen)
65+
OWNER_2=$(linera -w1 keygen)
6666

6767
linera -w0 service --port 8080 &
6868
sleep 1
@@ -77,8 +77,8 @@ on the URL you get by running `echo "http://localhost:8080/chains/$CHAIN_1/appli
7777
mutation {
7878
start(
7979
players: [
80-
"$PUB_KEY_1",
81-
"$PUB_KEY_2"
80+
"$OWNER_1",
81+
"$OWNER_2"
8282
],
8383
boardSize: 11,
8484
feeBudget: "1"
@@ -101,7 +101,7 @@ It contains the temporary chain's ID, and the ID of the message that created it:
101101
```gql,uri=http://localhost:8080/chains/$CHAIN_1/applications/$APP_ID
102102
query {
103103
gameChains {
104-
entry(key: "$PUB_KEY_1") {
104+
entry(key: "$OWNER_1") {
105105
value {
106106
messageId chainId
107107
}
@@ -120,8 +120,8 @@ kill %% && sleep 1 # Kill the service so we can use CLI commands for wallet 0
120120
HEX_CHAIN=$(echo "$QUERY_RESULT" | jq -r '.gameChains.entry.value[0].chainId')
121121
MESSAGE_ID=$(echo "$QUERY_RESULT" | jq -r '.gameChains.entry.value[0].messageId')
122122

123-
linera -w0 assign --key $PUB_KEY_1 --message-id $MESSAGE_ID
124-
linera -w1 assign --key $PUB_KEY_2 --message-id $MESSAGE_ID
123+
linera -w0 assign --owner $OWNER_1 --message-id $MESSAGE_ID
124+
linera -w1 assign --owner $OWNER_2 --message-id $MESSAGE_ID
125125

126126
linera -w0 service --port 8080 &
127127
linera -w1 service --port 8081 &

examples/hex-game/src/contract.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use async_graphql::ComplexObject;
99
use hex_game::{Board, Clock, HexAbi, HexOutcome, Operation, Timeouts};
1010
use linera_sdk::{
1111
base::{
12-
Amount, ApplicationPermissions, ChainId, ChainOwnership, Owner, PublicKey, TimeoutConfig,
12+
Amount, ApplicationPermissions, ChainId, ChainOwnership, Owner, TimeoutConfig,
1313
WithContractAbi,
1414
},
1515
views::{RootView, View},
@@ -75,9 +75,7 @@ impl Contract for HexContract {
7575
} => {
7676
let clock = Clock::new(self.runtime.system_time(), &timeouts);
7777
self.state.clock.set(clock);
78-
let owners = [Owner::from(&players[0]), Owner::from(&players[1])];
79-
self.state.public_keys.set(Some(players));
80-
self.state.owners.set(Some(owners));
78+
self.state.owners.set(Some(players));
8179
self.state.board.set(Board::new(board_size));
8280
}
8381
Message::End { winner, loser } => {
@@ -143,7 +141,7 @@ impl HexContract {
143141

144142
async fn execute_start(
145143
&mut self,
146-
players: [PublicKey; 2],
144+
players: [Owner; 2],
147145
board_size: u16,
148146
fee_budget: Amount,
149147
timeouts: Option<Timeouts>,
@@ -157,10 +155,10 @@ impl HexContract {
157155
let app_id = self.runtime.application_id();
158156
let permissions = ApplicationPermissions::new_single(app_id.forget_abi());
159157
let (message_id, chain_id) = self.runtime.open_chain(ownership, permissions, fee_budget);
160-
for public_key in &players {
158+
for owner in &players {
161159
self.state
162160
.game_chains
163-
.get_mut_or_default(public_key)
161+
.get_mut_or_default(owner)
164162
.await
165163
.unwrap()
166164
.insert(GameChain {
@@ -183,8 +181,8 @@ impl HexContract {
183181
let HexOutcome::Winner(player) = outcome else {
184182
return outcome;
185183
};
186-
let winner = self.state.public_keys.get().unwrap()[player.index()];
187-
let loser = self.state.public_keys.get().unwrap()[player.other().index()];
184+
let winner = self.state.owners.get().unwrap()[player.index()];
185+
let loser = self.state.owners.get().unwrap()[player.other().index()];
188186
let chain_id = self.main_chain_id();
189187
let message = Message::End { winner, loser };
190188
self.runtime.send_message(chain_id, message);
@@ -202,14 +200,14 @@ pub enum Message {
202200
/// Initializes a game. Sent from the main chain to a temporary chain.
203201
Start {
204202
/// The players.
205-
players: [PublicKey; 2],
203+
players: [Owner; 2],
206204
/// The side length of the board. A typical size is 11.
207205
board_size: u16,
208206
/// Settings that determine how much time the players have to think about their turns.
209207
timeouts: Timeouts,
210208
},
211209
/// Reports the outcome of a game. Sent from a closed chain to the main chain.
212-
End { winner: PublicKey, loser: PublicKey },
210+
End { winner: Owner, loser: Owner },
213211
}
214212

215213
/// This implementation is only nonempty in the service.

examples/hex-game/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::iter;
77

88
use async_graphql::{Enum, InputObject, Request, Response, SimpleObject};
99
use linera_sdk::{
10-
base::{Amount, ContractAbi, PublicKey, ServiceAbi, TimeDelta, Timestamp},
10+
base::{Amount, ContractAbi, Owner, ServiceAbi, TimeDelta, Timestamp},
1111
graphql::GraphQLMutationRoot,
1212
};
1313
use serde::{Deserialize, Serialize};
@@ -23,7 +23,7 @@ pub enum Operation {
2323
/// Start a game on a new temporary chain, with the given settings.
2424
Start {
2525
/// The public keys of player 1 and 2, respectively.
26-
players: [PublicKey; 2],
26+
players: [Owner; 2],
2727
/// The side length of the board. A typical size is 11.
2828
board_size: u16,
2929
/// An amount transferred to the temporary chain to cover the fees.

examples/hex-game/src/state.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::collections::BTreeSet;
66
use async_graphql::SimpleObject;
77
use hex_game::{Board, Clock, Timeouts};
88
use linera_sdk::{
9-
base::{ChainId, MessageId, Owner, PublicKey},
9+
base::{ChainId, MessageId, Owner},
1010
views::{linera_views, MapView, RegisterView, RootView, ViewStorageContext},
1111
};
1212
use serde::{Deserialize, Serialize};
@@ -27,14 +27,12 @@ pub struct GameChain {
2727
pub struct HexState {
2828
/// The `Owner`s controlling players `One` and `Two`.
2929
pub owners: RegisterView<Option<[Owner; 2]>>,
30-
/// The players' public keys.
31-
pub public_keys: RegisterView<Option<[PublicKey; 2]>>,
3230
/// The current game state.
3331
pub board: RegisterView<Board>,
3432
/// The game clock.
3533
pub clock: RegisterView<Clock>,
3634
/// The timeouts.
3735
pub timeouts: RegisterView<Timeouts>,
3836
/// Temporary chains for individual games, by player.
39-
pub game_chains: MapView<PublicKey, BTreeSet<GameChain>>,
37+
pub game_chains: MapView<Owner, BTreeSet<GameChain>>,
4038
}

examples/hex-game/tests/hex_game.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ async fn hex_game() {
2323
.add_block(|block| {
2424
let operation = Operation::Start {
2525
board_size: 2,
26-
players: [key_pair1.public(), key_pair2.public()],
26+
players: [key_pair1.public().into(), key_pair2.public().into()],
2727
fee_budget: Amount::ZERO,
2828
timeouts: None,
2929
};
@@ -97,7 +97,7 @@ async fn hex_game_clock() {
9797
.add_block(|block| {
9898
let operation = Operation::Start {
9999
board_size: 2,
100-
players: [key_pair1.public(), key_pair2.public()],
100+
players: [key_pair1.public().into(), key_pair2.public().into()],
101101
fee_budget: Amount::ZERO,
102102
timeouts: None,
103103
};

examples/matching-engine/README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,6 @@ OWNER_2=a477cb966190661c0dfbe50602616a78a48d2bef6cb5288d49deb3e05585d579
6464
OWNER_3=d2115775b5b3c5c1ed3c1516319a7e850c75d0786a74b39f5250cf9decc88124
6565
CHAIN_1=e476187f6ddfeb9d588c7b45d3df334d5501d6499b3f9ad5595cae86cce16a65
6666
CHAIN_2=69705f85ac4c9fef6c02b4d83426aaaf05154c645ec1c61665f8e450f0468bc0
67-
PUB_KEY_1=fcf518d56455283ace2bbc11c71e684eb58af81bc98b96a18129e825ce24ea84
68-
PUB_KEY_2=ca909dcf60df014c166be17eb4a9f6e2f9383314a57510206a54cd841ade455e
6967
```
7068

7169
Publish and create two `fungible` applications whose IDs will be used as a
@@ -170,7 +168,7 @@ Engine to close the chain.
170168
kill %% && sleep 1 # Kill the service so we can use CLI commands for chain 1.
171169

172170
linera --wait-for-outgoing-messages change-ownership \
173-
--owner-public-keys $PUB_KEY_1 $PUB_KEY_2
171+
--owners $OWNER_1 $OWNER_2
174172

175173
linera --wait-for-outgoing-messages change-application-permissions \
176174
--execute-operations $MATCHING_ENGINE \

linera-base/src/ownership.rs

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@
44
//! Structures defining the set of owners and super owners, as well as the consensus
55
//! round types and timeouts for chains.
66
7-
use std::{collections::BTreeMap, iter};
7+
use std::{
8+
collections::{BTreeMap, BTreeSet},
9+
iter,
10+
};
811

912
use custom_debug_derive::Debug;
1013
use linera_witty::{WitLoad, WitStore, WitType};
1114
use serde::{Deserialize, Serialize};
1215
use thiserror::Error;
1316

1417
use crate::{
15-
crypto::PublicKey,
1618
data_types::{Round, TimeDelta},
1719
doc_scalar,
1820
identifiers::Owner,
@@ -50,11 +52,11 @@ impl Default for TimeoutConfig {
5052
)]
5153
pub struct ChainOwnership {
5254
/// Super owners can propose fast blocks in the first round, and regular blocks in any round.
53-
#[debug(skip_if = BTreeMap::is_empty)]
54-
pub super_owners: BTreeMap<Owner, PublicKey>,
55+
#[debug(skip_if = BTreeSet::is_empty)]
56+
pub super_owners: BTreeSet<Owner>,
5557
/// The regular owners, with their weights that determine how often they are round leader.
5658
#[debug(skip_if = BTreeMap::is_empty)]
57-
pub owners: BTreeMap<Owner, (PublicKey, u64)>,
59+
pub owners: BTreeMap<Owner, u64>,
5860
/// The number of initial rounds after 0 in which all owners are allowed to propose blocks.
5961
pub multi_leader_rounds: u32,
6062
/// The timeout configuration: how long fast, multi-leader and single-leader rounds last.
@@ -63,46 +65,42 @@ pub struct ChainOwnership {
6365

6466
impl ChainOwnership {
6567
/// Creates a `ChainOwnership` with a single super owner.
66-
pub fn single_super(public_key: PublicKey) -> Self {
68+
pub fn single_super(owner: Owner) -> Self {
6769
ChainOwnership {
68-
super_owners: iter::once((Owner::from(public_key), public_key)).collect(),
70+
super_owners: iter::once(owner).collect(),
6971
owners: BTreeMap::new(),
7072
multi_leader_rounds: 2,
7173
timeout_config: TimeoutConfig::default(),
7274
}
7375
}
7476

7577
/// Creates a `ChainOwnership` with a single regular owner.
76-
pub fn single(public_key: PublicKey) -> Self {
78+
pub fn single(owner: Owner) -> Self {
7779
ChainOwnership {
78-
super_owners: BTreeMap::new(),
79-
owners: iter::once((Owner::from(public_key), (public_key, 100))).collect(),
80+
super_owners: BTreeSet::new(),
81+
owners: iter::once((owner, 100)).collect(),
8082
multi_leader_rounds: 2,
8183
timeout_config: TimeoutConfig::default(),
8284
}
8385
}
8486

8587
/// Creates a `ChainOwnership` with the specified regular owners.
8688
pub fn multiple(
87-
keys_and_weights: impl IntoIterator<Item = (PublicKey, u64)>,
89+
owners_and_weights: impl IntoIterator<Item = (Owner, u64)>,
8890
multi_leader_rounds: u32,
8991
timeout_config: TimeoutConfig,
9092
) -> Self {
9193
ChainOwnership {
92-
super_owners: BTreeMap::new(),
93-
owners: keys_and_weights
94-
.into_iter()
95-
.map(|(public_key, weight)| (Owner::from(public_key), (public_key, weight)))
96-
.collect(),
94+
super_owners: BTreeSet::new(),
95+
owners: owners_and_weights.into_iter().collect(),
9796
multi_leader_rounds,
9897
timeout_config,
9998
}
10099
}
101100

102101
/// Adds a regular owner.
103-
pub fn with_regular_owner(mut self, public_key: PublicKey, weight: u64) -> Self {
104-
self.owners
105-
.insert(Owner::from(public_key), (public_key, weight));
102+
pub fn with_regular_owner(mut self, owner: Owner, weight: u64) -> Self {
103+
self.owners.insert(owner, weight);
106104
self
107105
}
108106

@@ -113,13 +111,9 @@ impl ChainOwnership {
113111
|| self.timeout_config.fallback_duration == TimeDelta::ZERO
114112
}
115113

116-
/// Returns the given owner's public key, if they are an owner or super owner.
117-
pub fn verify_owner(&self, owner: &Owner) -> Option<PublicKey> {
118-
if let Some(public_key) = self.super_owners.get(owner) {
119-
Some(*public_key)
120-
} else {
121-
self.owners.get(owner).map(|(public_key, _)| *public_key)
122-
}
114+
/// Returns `true` if this is an owner or super owner.
115+
pub fn verify_owner(&self, owner: &Owner) -> bool {
116+
self.super_owners.contains(owner) || self.owners.contains_key(owner)
123117
}
124118

125119
/// Returns the duration of the given round.
@@ -157,14 +151,7 @@ impl ChainOwnership {
157151

158152
/// Returns an iterator over all super owners, followed by all owners.
159153
pub fn all_owners(&self) -> impl Iterator<Item = &Owner> {
160-
self.super_owners.keys().chain(self.owners.keys())
161-
}
162-
163-
/// Returns an iterator over all super owners' keys, followed by all owners'.
164-
pub fn all_public_keys(&self) -> impl Iterator<Item = &PublicKey> {
165-
self.super_owners
166-
.values()
167-
.chain(self.owners.values().map(|(public_key, _)| public_key))
154+
self.super_owners.iter().chain(self.owners.keys())
168155
}
169156

170157
/// Returns the round following the specified one, if any.
@@ -207,8 +194,8 @@ mod tests {
207194
let owner = Owner::from(pub_key);
208195

209196
let ownership = ChainOwnership {
210-
super_owners: BTreeMap::from_iter([(super_owner, super_pub_key)]),
211-
owners: BTreeMap::from_iter([(owner, (pub_key, 100))]),
197+
super_owners: BTreeSet::from_iter([super_owner]),
198+
owners: BTreeMap::from_iter([(owner, 100)]),
212199
multi_leader_rounds: 10,
213200
timeout_config: TimeoutConfig {
214201
fast_round_duration: Some(TimeDelta::from_secs(5)),

0 commit comments

Comments
 (0)