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,
}