Conversation
795c626 to
d66cb15
Compare
d66cb15 to
85f269f
Compare
bart-linera
left a comment
There was a problem hiding this comment.
I'm not sure I agree with the premise. It seems like a chain as a transfer target doesn't really belong as a variant of AccountOwner. If we want to be more explicit, I'd just make a type like enum TransferTarget { AccountOwner(AccountOwner), Chain } and replace Option<AccountOwner> with it. Then AccountOwner would play the role of identifying someone owning tokens that can authenticate transfers, and TransferTarget would represent, well, a target of a transfer.
I'm just not sure if that helps with solving the problem this was intended to solve, but I guess new potential variants of "addresses" could then be new variants of TransferTarget?
| AccountOwner::Chain => { | ||
| unreachable!("Chains cannot be used to authenticate") | ||
| } |
There was a problem hiding this comment.
Those unreachable!s suggest to me that we might be conflating two different things here: who can authenticate a transaction, and where tokens can be transferred to. Maybe those should be represented by separate types? (Not necessarily something for this PR.)
There was a problem hiding this comment.
AccountOwner::Chain is both a destination (the chain balance) and an ownership model (any block producer + temporarily message fees).
There was a problem hiding this comment.
Here the issue is that unreachable! is inaccurate and the error message is kinda misleading. It should be something like
panic!("Using chain balance is not authorized")
There was a problem hiding this comment.
Done in Replace unreachables with panics.
I think the ultimate solution would be to simply remove that variant entirely and either hardcode that every chain has an account with some hardcoded address ( |
bart-linera
left a comment
There was a problem hiding this comment.
After some discussion with Mateusz, it seems that a kind of separation between authenticating parties and owners already exists, and what drew my attention seems to have been implementation details of some example applications - so this change seems to be okay to me now 👍
| application_id: UserApplicationId<A>, | ||
| application_id: ApplicationId<A>, |
There was a problem hiding this comment.
This (and below) seems to be a part of a different change?
| authenticated_application_id == Some(owner), | ||
| ExecutionError::UnauthenticatedClaimOwner | ||
| ), | ||
| AccountOwner::Chain => unreachable!(), |
There was a problem hiding this comment.
Maybe it would make sense to handle this case? If a chain owner can transfer from an AccountOwner::Chain, then maybe it makes sense to let them claim from an AccountOwner::Chain, too? (if that's even possible to be implemented)
There was a problem hiding this comment.
Sounds reasonable to mirror logic of transfer here. I didn't decide to do it b/c I would change the logic - i.e. the source here wasn't wrapped with Option.
There was a problem hiding this comment.
Let's not do it in this PR, but I agree it sounds reasonable.
| @@ -144,6 +144,9 @@ impl NativeFungibleTokenContract { | |||
| ); | |||
| } | |||
| AccountOwner::Application(_) => panic!("Applications not supported yet"), | |||
There was a problem hiding this comment.
We should fix that (not here but soon)
| match self { | ||
| AccountOwner::User(owner) => write!(f, "User:{}", owner)?, | ||
| AccountOwner::Application(app_id) => write!(f, "Application:{}", app_id)?, | ||
| AccountOwner::Chain => write!(f, "Chain")?, |
There was a problem hiding this comment.
I look forward to removing these tags
There was a problem hiding this comment.
The ::Chain variant might not be so easy to remove b/c there are flow paths where the Chain is still a valid identifier. Right now I can see two ways to get rid of it:
- Do not let chain own a balance.
- Turn
::Chainvariant into a special case of address ([u8; 32]).
The first one isn't just a refactor (internal change) as it requires making some high-level design decisions around opening new chains etc.
I think the second option is the easier one and we should try to do it. We could hash a string like "Linera Chain Address" (note it cannot simply be [0u8; 32] b/c in Ed25519 a private key for all zeros public key is well-known).
There was a problem hiding this comment.
note it cannot simply be [0u8; 32] b/c in Ed25519 a private key for all zeros public key is well-known)
Addresses are not public keys but hash values, so [0u8; 32] would work. I proposed 0x0 (Reserved(0)) in the internal doc.
| context.authenticated_signer, | ||
| None, | ||
| owner.map(AccountOwner::User), | ||
| owner.map(AccountOwner::User).unwrap_or(AccountOwner::Chain), |
There was a problem hiding this comment.
We should instead modify SystemOperation to use SystemOperation::Transfer { owner: Owner .. } and resolve the default value way earlier.
There was a problem hiding this comment.
unwrap_or(AccountOwner::Chain) is a little bit of a red flag. After this PR, I would imagine that only CLI options may default to a chain account.
There was a problem hiding this comment.
I agree it looks dangerous. So I tracked the places where I use AccountOwner::Chain as the default - there are two (actually three but there are two instances where I use ::Chain as source when constructing a SystemMessage::Credit so that's one for the purpose of this discussion):
- In
send_refundwe previously were usingNoneassourceand now we useAccountOwner::Chain. - In
system.rs#execute_operationwe previously were usingNoneassourcefor the transfer and now we default to::Chain.
In both those cases None resolved to the "chain" already:
There's no regression here.
Also, see #3573 where I replace Transfer::source: Option<Owner> with AccountOwner and get rid of some of these unwrap_or(AccountOwner::Chain).
There was a problem hiding this comment.
Thanks for checking. Indeed the source of a refund's Credit message is currently a best effort. (It only matters if the refund message itself is rejected.)
linera-execution/src/system.rs
Outdated
| let mut outcome = RawExecutionOutcome { | ||
| authenticated_signer: context.authenticated_signer, | ||
| refund_grant_to: context.refund_grant_to(), | ||
| refund_grant_to: Some(context.refund_grant_to()), |
There was a problem hiding this comment.
No. We should not force refunds.
There was a problem hiding this comment.
Ah, you're right. We actually had two Options previously here - the outer one (return type) and inner one (Some(Account { owner: None })) and previously Some(None) would not refund at all.
There was a problem hiding this comment.
99f977e to
9a67aed
Compare
9a67aed to
b6110b9
Compare
| chain.execution_state.system.balances.get(&owner).await?; | ||
| } | ||
| AccountOwner::Chain => { | ||
| info.requested_owner_balance = Some(*chain.execution_state.system.balance.get()); |
There was a problem hiding this comment.
Here or very soon we should remove SystemExecutionStateView::balance by the way
There was a problem hiding this comment.
I took a quick stab at removing the chains' balances entirely and it wasn't very difficult. I can propose something in a separate PR.
| context.authenticated_signer, | ||
| None, | ||
| owner.map(AccountOwner::User), | ||
| owner.map(AccountOwner::User).unwrap_or(AccountOwner::Chain), |
There was a problem hiding this comment.
Thanks for checking. Indeed the source of a refund's Credit message is currently a best effort. (It only matters if the refund message itself is rejected.)
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
ChainintoAccountOwnerenum to identify cases where transactions (mostly token transfers) are targeting or using chain's account balance. Previously that case was handled with the usage ofOption<AccountOwner>. This made refactoring more difficult.Test Plan
CI should catch regressions.
Release Plan
Links