Skip to content

Commit 5f582a7

Browse files
authored
Make Chain a variant of AccountOwner (#3560)
## Motivation We want to fix and expand our notion of Address (currently Owner, GenericApplicationId, etc.) to different type of addresses (32-byte Linera/Solana, 20-byte EVM). In order to do that we need to prepare the code for the introduction of new variants. ## Proposal Inline a `Chain` into `AccountOwner` enum to identify cases where transactions (mostly token transfers) are targeting or using chain's account balance. Previously that case was handled with the usage of `Option<AccountOwner>`. This made refactoring more difficult. ## Test Plan CI should catch regressions. ## Release Plan - Nothing to do / These changes follow the usual release cycle. ## Links <!-- Optional section for related PRs, related issues, and other references. If needed, please create issues to track future improvements and link them here. --> - [reviewer checklist](https://github.com/linera-io/linera-protocol/blob/main/CONTRIBUTING.md#reviewer-checklist)
1 parent 524c61a commit 5f582a7

File tree

40 files changed

+231
-191
lines changed

40 files changed

+231
-191
lines changed

examples/amm/src/contract.rs

+3
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,9 @@ impl AmmContract {
326326
"Unauthorized"
327327
)
328328
}
329+
AccountOwner::Chain => {
330+
panic!("Using chain balance is not authorized")
331+
}
329332
}
330333
}
331334

examples/fungible/src/contract.rs

+3
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ impl FungibleTokenContract {
143143
"The requested transfer is not correctly authenticated."
144144
)
145145
}
146+
AccountOwner::Chain => {
147+
panic!("Chain account is not supported")
148+
}
146149
}
147150
}
148151

examples/gen-nft/src/contract.rs

+3
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ impl GenNftContract {
140140
"The requested transfer is not correctly authenticated."
141141
)
142142
}
143+
AccountOwner::Chain => {
144+
panic!("Chain account is not supported")
145+
}
143146
}
144147
}
145148

examples/matching-engine/src/contract.rs

+3
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ impl MatchingEngineContract {
166166
"Unauthorized"
167167
)
168168
}
169+
AccountOwner::Chain => {
170+
panic!("Chain account is not supported")
171+
}
169172
}
170173
}
171174

examples/native-fungible/src/contract.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ impl Contract for NativeFungibleTokenContract {
3838
for (owner, amount) in state.accounts {
3939
let account = Account {
4040
chain_id: self.runtime.chain_id(),
41-
owner: Some(owner),
41+
owner,
4242
};
43-
self.runtime.transfer(None, account, amount);
43+
self.runtime.transfer(AccountOwner::Chain, account, amount);
4444
}
4545
}
4646

@@ -63,7 +63,7 @@ impl Contract for NativeFungibleTokenContract {
6363
let fungible_target_account = target_account;
6464
let target_account = self.normalize_account(target_account);
6565

66-
self.runtime.transfer(Some(owner), target_account, amount);
66+
self.runtime.transfer(owner, target_account, amount);
6767

6868
self.transfer(fungible_target_account.chain_id);
6969
FungibleResponse::Ok
@@ -129,7 +129,7 @@ impl NativeFungibleTokenContract {
129129
fn normalize_account(&self, account: fungible::Account) -> Account {
130130
Account {
131131
chain_id: account.chain_id,
132-
owner: Some(account.owner),
132+
owner: account.owner,
133133
}
134134
}
135135

@@ -144,6 +144,9 @@ impl NativeFungibleTokenContract {
144144
);
145145
}
146146
AccountOwner::Application(_) => panic!("Applications not supported yet"),
147+
AccountOwner::Chain => {
148+
panic!("Chain accounts are not supported")
149+
}
147150
}
148151
}
149152
}

examples/non-fungible/src/contract.rs

+3
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ impl NonFungibleTokenContract {
144144
"The requested transfer is not correctly authenticated."
145145
)
146146
}
147+
AccountOwner::Chain => {
148+
panic!("Chain account is not supported")
149+
}
147150
}
148151
}
149152

linera-base/src/identifiers.rs

+15-11
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ pub enum AccountOwner {
3737
/// An account owned by a user.
3838
User(Owner),
3939
/// An account for an application.
40-
Application(ApplicationId),
40+
Application(UserApplicationId),
41+
/// Chain account.
42+
Chain,
4143
}
4244

4345
/// A system account.
@@ -48,34 +50,30 @@ pub struct Account {
4850
/// The chain of the account.
4951
pub chain_id: ChainId,
5052
/// The owner of the account, or `None` for the chain balance.
51-
#[debug(skip_if = Option::is_none)]
52-
pub owner: Option<AccountOwner>,
53+
pub owner: AccountOwner,
5354
}
5455

5556
impl Account {
5657
/// Creates an [`Account`] representing the balance shared by a chain's owners.
5758
pub fn chain(chain_id: ChainId) -> Self {
5859
Account {
5960
chain_id,
60-
owner: None,
61+
owner: AccountOwner::Chain,
6162
}
6263
}
6364

6465
/// Creates an [`Account`] for a specific [`Owner`] on a chain.
6566
pub fn owner(chain_id: ChainId, owner: impl Into<AccountOwner>) -> Self {
6667
Account {
6768
chain_id,
68-
owner: Some(owner.into()),
69+
owner: owner.into(),
6970
}
7071
}
7172
}
7273

7374
impl Display for Account {
7475
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75-
match self.owner {
76-
Some(owner) => write!(f, "{}:{}", self.chain_id, owner),
77-
None => write!(f, "{}", self.chain_id),
78-
}
76+
write!(f, "{}:{}", self.chain_id, self.owner)
7977
}
8078
}
8179

@@ -306,7 +304,7 @@ pub struct ApplicationId<A = ()> {
306304

307305
/// Alias for `ApplicationId`. Use this alias in the core
308306
/// protocol where the distinction with the more general enum `GenericApplicationId` matters.
309-
pub type UserApplicationId<A = ()> = ApplicationId<A>;
307+
pub type UserApplicationId = ApplicationId<()>;
310308

311309
/// A unique identifier for an application.
312310
#[derive(
@@ -328,7 +326,7 @@ pub enum GenericApplicationId {
328326
/// The system application.
329327
System,
330328
/// A user application.
331-
User(ApplicationId),
329+
User(UserApplicationId),
332330
}
333331

334332
impl GenericApplicationId {
@@ -951,6 +949,7 @@ impl<'de> serde::de::Visitor<'de> for OwnerVisitor {
951949
enum SerializableAccountOwner {
952950
User(Owner),
953951
Application(ApplicationId),
952+
Chain,
954953
}
955954

956955
impl Serialize for AccountOwner {
@@ -961,6 +960,7 @@ impl Serialize for AccountOwner {
961960
match self {
962961
AccountOwner::Application(app_id) => SerializableAccountOwner::Application(*app_id),
963962
AccountOwner::User(owner) => SerializableAccountOwner::User(*owner),
963+
AccountOwner::Chain => SerializableAccountOwner::Chain,
964964
}
965965
.serialize(serializer)
966966
}
@@ -980,6 +980,7 @@ impl<'de> Deserialize<'de> for AccountOwner {
980980
Ok(AccountOwner::Application(app_id))
981981
}
982982
SerializableAccountOwner::User(owner) => Ok(AccountOwner::User(owner)),
983+
SerializableAccountOwner::Chain => Ok(AccountOwner::Chain),
983984
}
984985
}
985986
}
@@ -990,6 +991,7 @@ impl Display for AccountOwner {
990991
match self {
991992
AccountOwner::User(owner) => write!(f, "User:{}", owner)?,
992993
AccountOwner::Application(app_id) => write!(f, "Application:{}", app_id)?,
994+
AccountOwner::Chain => write!(f, "Chain")?,
993995
};
994996

995997
Ok(())
@@ -1008,6 +1010,8 @@ impl FromStr for AccountOwner {
10081010
Ok(AccountOwner::Application(
10091011
ApplicationId::from_str(app_id).context("Getting ApplicationId should not fail")?,
10101012
))
1013+
} else if s.strip_prefix("Chain").is_some() {
1014+
Ok(AccountOwner::Chain)
10111015
} else {
10121016
Err(anyhow!("Invalid enum! Enum: {}", s))
10131017
}

linera-base/src/unit_tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ fn send_message_request_test_case() -> SendMessageRequest<Vec<u8>> {
8989
fn account_test_case() -> Account {
9090
Account {
9191
chain_id: ChainId::root(10),
92-
owner: Some(AccountOwner::User(Owner(CryptoHash::test_hash("account")))),
92+
owner: AccountOwner::User(Owner(CryptoHash::test_hash("account"))),
9393
}
9494
}
9595

linera-core/src/chain_worker/state/temporary_changes.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,14 @@ where
219219
if query.request_committees {
220220
info.requested_committees = Some(chain.execution_state.system.committees.get().clone());
221221
}
222-
if let Some(owner) = query.request_owner_balance {
223-
info.requested_owner_balance =
224-
chain.execution_state.system.balances.get(&owner).await?;
222+
match query.request_owner_balance {
223+
owner @ AccountOwner::Application(_) | owner @ AccountOwner::User(_) => {
224+
info.requested_owner_balance =
225+
chain.execution_state.system.balances.get(&owner).await?;
226+
}
227+
AccountOwner::Chain => {
228+
info.requested_owner_balance = Some(*chain.execution_state.system.balance.get());
229+
}
225230
}
226231
if let Some(next_block_height) = query.test_next_block_height {
227232
ensure!(

linera-core/src/client/mod.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -2260,7 +2260,7 @@ where
22602260
#[instrument(level = "trace", skip(application_id, query))]
22612261
pub async fn query_user_application<A: Abi>(
22622262
&self,
2263-
application_id: UserApplicationId<A>,
2263+
application_id: ApplicationId<A>,
22642264
query: &A::Query,
22652265
) -> Result<QueryOutcome<A::QueryResponse>, ChainClientError> {
22662266
let query = Query::user(application_id, query)?;
@@ -2294,7 +2294,7 @@ where
22942294
/// block.
22952295
#[instrument(level = "trace")]
22962296
pub async fn query_balance(&self) -> Result<Amount, ChainClientError> {
2297-
let (balance, _) = self.query_balances_with_owner(None).await?;
2297+
let (balance, _) = self.query_balances_with_owner(AccountOwner::Chain).await?;
22982298
Ok(balance)
22992299
}
23002300

@@ -2310,7 +2310,7 @@ where
23102310
owner: AccountOwner,
23112311
) -> Result<Amount, ChainClientError> {
23122312
Ok(self
2313-
.query_balances_with_owner(Some(owner))
2313+
.query_balances_with_owner(owner)
23142314
.await?
23152315
.1
23162316
.unwrap_or(Amount::ZERO))
@@ -2325,7 +2325,7 @@ where
23252325
#[instrument(level = "trace", skip(owner))]
23262326
async fn query_balances_with_owner(
23272327
&self,
2328-
owner: Option<AccountOwner>,
2328+
owner: AccountOwner,
23292329
) -> Result<(Amount, Option<Amount>), ChainClientError> {
23302330
let incoming_bundles = self.pending_message_bundles().await?;
23312331
let (previous_block_hash, height, timestamp) = {
@@ -2343,10 +2343,11 @@ where
23432343
operations: Vec::new(),
23442344
previous_block_hash,
23452345
height,
2346-
authenticated_signer: owner.and_then(|owner| match owner {
2346+
authenticated_signer: match owner {
23472347
AccountOwner::User(user) => Some(user),
23482348
AccountOwner::Application(_) => None,
2349-
}),
2349+
AccountOwner::Chain => None, // These should be unreachable?
2350+
},
23502351
timestamp,
23512352
};
23522353
match self
@@ -2382,7 +2383,7 @@ where
23822383
/// Does not process the inbox or attempt to synchronize with validators.
23832384
#[instrument(level = "trace")]
23842385
pub async fn local_balance(&self) -> Result<Amount, ChainClientError> {
2385-
let (balance, _) = self.local_balances_with_owner(None).await?;
2386+
let (balance, _) = self.local_balances_with_owner(AccountOwner::Chain).await?;
23862387
Ok(balance)
23872388
}
23882389

@@ -2395,7 +2396,7 @@ where
23952396
owner: AccountOwner,
23962397
) -> Result<Amount, ChainClientError> {
23972398
Ok(self
2398-
.local_balances_with_owner(Some(owner))
2399+
.local_balances_with_owner(owner)
23992400
.await?
24002401
.1
24012402
.unwrap_or(Amount::ZERO))
@@ -2407,7 +2408,7 @@ where
24072408
#[instrument(level = "trace", skip(owner))]
24082409
async fn local_balances_with_owner(
24092410
&self,
2410-
owner: Option<AccountOwner>,
2411+
owner: AccountOwner,
24112412
) -> Result<(Amount, Option<Amount>), ChainClientError> {
24122413
let next_block_height = self.next_block_height();
24132414
ensure!(
@@ -2936,7 +2937,7 @@ where
29362937
parameters: &Parameters,
29372938
instantiation_argument: &InstantiationArgument,
29382939
required_application_ids: Vec<UserApplicationId>,
2939-
) -> Result<ClientOutcome<(UserApplicationId<A>, ConfirmedBlockCertificate)>, ChainClientError>
2940+
) -> Result<ClientOutcome<(ApplicationId<A>, ConfirmedBlockCertificate)>, ChainClientError>
29402941
{
29412942
let instantiation_argument = serde_json::to_vec(instantiation_argument)?;
29422943
let parameters = serde_json::to_vec(parameters)?;

linera-core/src/data_types.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ pub struct ChainInfoQuery {
7171
#[debug(skip_if = Option::is_none)]
7272
pub test_next_block_height: Option<BlockHeight>,
7373
/// Request the balance of a given [`AccountOwner`].
74-
#[debug(skip_if = Option::is_none)]
75-
pub request_owner_balance: Option<AccountOwner>,
74+
pub request_owner_balance: AccountOwner,
7675
/// Query the current committees.
7776
#[debug(skip_if = Not::not)]
7877
pub request_committees: bool,
@@ -102,7 +101,7 @@ impl ChainInfoQuery {
102101
chain_id,
103102
test_next_block_height: None,
104103
request_committees: false,
105-
request_owner_balance: None,
104+
request_owner_balance: AccountOwner::Chain,
106105
request_pending_message_bundles: false,
107106
request_sent_certificate_hashes_in_range: None,
108107
request_received_log_excluding_first_n: None,
@@ -123,7 +122,7 @@ impl ChainInfoQuery {
123122
}
124123

125124
pub fn with_owner_balance(mut self, owner: AccountOwner) -> Self {
126-
self.request_owner_balance = Some(owner);
125+
self.request_owner_balance = owner;
127126
self
128127
}
129128

linera-core/src/unit_tests/client_tests.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,7 @@ where
195195
Amount::from_tokens(3)
196196
);
197197
assert_eq!(
198-
receiver
199-
.local_balances_with_owner(Some(owner))
200-
.await
201-
.unwrap(),
198+
receiver.local_balances_with_owner(owner).await.unwrap(),
202199
(Amount::ZERO, Some(Amount::from_tokens(3)))
203200
);
204201
assert_eq!(receiver.query_balance().await.unwrap(), Amount::ZERO);
@@ -207,10 +204,7 @@ where
207204
Amount::from_millis(2999)
208205
);
209206
assert_eq!(
210-
receiver
211-
.query_balances_with_owner(Some(owner))
212-
.await
213-
.unwrap(),
207+
receiver.query_balances_with_owner(owner).await.unwrap(),
214208
(Amount::ZERO, Some(Amount::from_millis(2999)))
215209
);
216210

0 commit comments

Comments
 (0)