Skip to content

Commit

Permalink
execution-core: Support unsigned moonlight transactions
Browse files Browse the repository at this point in the history
Resolves: #2304
  • Loading branch information
moCello committed Sep 9, 2024
1 parent bb0b836 commit 868b5fc
Showing 1 changed file with 59 additions and 1 deletion.
60 changes: 59 additions & 1 deletion execution-core/src/transfer/moonlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,22 @@ impl Transaction {
Ok(Self { payload, signature })
}

/// Create a transaction by signing a previously generated payload with a
/// given secret-key.
///
/// Note that this transaction will be invalid if the secret-key used for
/// signing doesn't form a valid key-pair with the public-key of the
/// `from_account`.
pub fn new_from_payload(
from_sk: &AccountSecretKey,
payload: Payload,
) -> Self {
let digest = payload.signature_message();
let signature = from_sk.sign(&digest);

Self { payload, signature }
}

/// The proof of the transaction.
#[must_use]
pub fn signature(&self) -> &AccountSignature {
Expand Down Expand Up @@ -267,7 +283,7 @@ impl Transaction {
/// The payload for a moonlight transaction.
#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
#[archive_attr(derive(CheckBytes))]
struct Payload {
pub struct Payload {
/// ID of the chain for this transaction to execute on.
pub chain_id: u8,
/// Key of the sender of this transaction.
Expand All @@ -293,6 +309,48 @@ struct Payload {
}

impl Payload {
/// Create a new unsigned transaction-payload.
/// This can be used to generate a transaction payload without the
/// secret-key of the sender.
///
/// To generate a valid transaction, the sender will need to sign the
/// transaction at a later point, using [`Transaction::new_from_payload`]
/// with the secret-key that forms a valid key-pair with the public-key
/// of the `from_account`.
///
/// # Errors
/// The creation of a transaction is not possible and will error if:
/// - the memo, if given, is too large
pub fn new_unsigned(
from_account: AccountPublicKey,
deposit: u64,
gas_limit: u64,
gas_price: u64,
nonce: u64,
chain_id: u8,
data: Option<impl Into<TransactionData>>,
) -> Result<Self, Error> {
let data = data.map(Into::into);

if let Some(TransactionData::Memo(memo)) = data.as_ref() {
if memo.len() > MAX_MEMO_SIZE {
return Err(Error::MemoTooLarge(memo.len()));
}
}

Ok(Self {
chain_id,
from_account,
to_account: None,
value: 0,
deposit,
gas_limit,
gas_price,
nonce,
data,
})
}

/// Serialize the payload into a byte buffer.
#[must_use]
pub fn to_var_bytes(&self) -> Vec<u8> {
Expand Down

0 comments on commit 868b5fc

Please sign in to comment.