1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
//! The types of individual account updates that form a snapp transaction.
use crate::account;
use crate::call_data;
use crate::condition;
use crate::event;
use crate::pickles;
use crate::primitives::*;
use crate::sequence_event;
use crate::token_id;
/// The `SetOrKeep<T>` type is an enum type parameterised by a type `T`, and determines whether a
/// party update affects a particular field of the account state.
#[derive(Copy, Clone)]
pub enum SetOrKeep<T> {
/// Update the account state with a new value.
Set(T),
/// Keep the existing value.
Keep,
}
impl<T> SetOrKeep<T> {
/// Helper function to transform the value inside a [`SetOrKeep::Set`] to a value of a
/// different type, using the given function.
pub fn map<U>(x: SetOrKeep<T>, f: impl FnOnce(T) -> U) -> SetOrKeep<U> {
match x {
SetOrKeep::Set(x) => SetOrKeep::Set(f(x)),
SetOrKeep::Keep => SetOrKeep::Keep,
}
}
}
/// Updates to apply to the account when applying a party.
pub struct PartyUpdate<'a> {
/// Update for each of the elements of the general-purpose storage in the account.
pub app_state: [SetOrKeep<Fp>; 8],
/// Update to delegate staking of the account's balance to.
pub delegate: SetOrKeep<CompressedPublicKey>,
/// Update to the verification key for the snapp associated with this account.
pub verification_key: SetOrKeep<Option<pickles::VerificationKey>>,
/// Update to the permissions for the account.
/// This sets all permissions simultaneously; any update must provide the desired permissions
/// for all permission kinds.
pub permissions: SetOrKeep<account::Permissions>,
/// Update to the URI for access to the code and other resources for this account's snapp smart contract.
pub snapp_uri: SetOrKeep<&'a str>,
/// Update to the symbol for the token managed by this account.
/// If given, the string has a maximum length of 6 characters.
pub token_symbol: SetOrKeep<&'a str>,
/// Update to set the initial timing data for an account.
/// If not given when creating an account, the account is untimed.
pub timing: SetOrKeep<account::TimingInfo>,
/// Update the state hash that the account is recorded as voting for.
pub voting_for: SetOrKeep<StateHash>,
}
// TODO: Move these
/// Declares the 'sign' of a signed number.
pub enum Sign {
Positive,
Negative,
}
/// A signed amount, which records whether it is positive or negative.
pub struct SignedAmount {
/// True if positive, false if negative.
pub sign: Sign,
/// The magnitude of the amount.
pub magnitude: u64,
}
/// Add a [`SignedAmount`] to a `u64`.
///
/// If the `sign` of `y` is `Positive`, this must return a (wrapping) add of `x` and
/// `y.magnitude`.
/// Otherwise, this must
pub fn wrapping_add_signed(x: u64, y: SignedAmount) -> u64 {
match y.sign {
Sign::Positive => x.wrapping_add(y.magnitude),
Sign::Negative => x.wrapping_sub(y.magnitude),
}
}
/// The body of a single account update.
pub struct PartyBody<'a> {
/// The public key of the account that the update applies to.
pub public_key: CompressedPublicKey,
/// The updates to apply to the account.
pub update: PartyUpdate<'a>,
/// The token ID held by the account that this update should apply to.
pub token_id: token_id::TokenID,
/// The change in balance to apply to the account.
/// A `Positive` change increases the balance of the account; a `Negative` change decreases it.
pub balance_change: SignedAmount,
/// Whether to increment the account's nonce when applying this update.
pub increment_nonce: bool,
/// The list of 'events' emitted by the snapp for this account, used to reveal auxiliary
/// information that will not be directly stored within the snapp account. See [`crate::event`]
/// for more details.
///
pub events: &'a event::Events<'a>,
/// The list of 'sequence events' emitted by the snapp for this account.
///
/// These events are accumulated in the order that a block producer selects the transactions,
/// and are made available via a cryptographic commitment stored in the
/// [`sequence_event::SequenceState`] data structure. A 'supervisor' or 'roll-up' rule in the
/// snapp smart contract may use this data to apply updates in a deterministic order when there
/// otherwise might be data races.
pub sequence_events: &'a sequence_event::SequenceEvents<'a>,
/// The opaque 'call data'
pub call_data: call_data::CallData,
/// The 'depth' into the call stack, used to compute the [`crate::call_stack`] for the
/// transaction. This depth must always be > 0 and may only increase by 1, but may decrease by
/// any amount. See [`crate::call_stack`] for more.
pub call_depth: u8,
/// The condition that must be satisfied by the procotol state of the most recent block in
/// order for this update to be accepted.
pub protocol_state_condition: condition::ProtocolStateCondition,
/// The condition that must be satisfied by this account in order for this update to be
/// accepted.
pub account_condition: condition::Account,
/// Whether to use the hash of the full transaction -- including the fee payer -- in the
/// signature. If false, only the non-fee-payer updates are included in the hash, and this
/// party must increment its nonce to prevent replay attacks.
pub use_full_commitment: bool,
}
/// The authorization associated with a particular account update.
pub enum PartyAuthorization {
/// The update is authorized by a proof that verifies against the verification key stored in
/// the account's snapp state.
Proof(pickles::Proof),
/// The update is authorized by a signature.
Signature(Signature),
/// The update does not require authorization.
NoneGiven,
}
pub struct Party<'a> {
pub body: PartyBody<'a>,
pub authorization: PartyAuthorization,
}
pub struct FeePayerBody<'a> {
pub public_key: CompressedPublicKey,
pub update: PartyUpdate<'a>,
pub fee: u64,
pub events: &'a event::Events<'a>,
pub sequence_events: &'a event::Events<'a>,
pub call_data: call_data::CallData,
pub call_depth: u8,
pub protocol_state_condition: condition::ProtocolStateCondition,
pub account_nonce: u32,
}
pub struct FeePayer<'a> {
pub body: FeePayerBody<'a>,
pub signature: Signature,
}