mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-06 23:33:10 +00:00
refactor encoding/decoding for public transactions without serde
This commit is contained in:
parent
a5d0c27d6b
commit
bab1112251
@ -34,7 +34,7 @@ pub fn produce_dummy_empty_transaction() -> nssa::PublicTransaction {
|
||||
let program_id = nssa::program::Program::authenticated_transfer_program().id();
|
||||
let addresses = vec![];
|
||||
let nonces = vec![];
|
||||
let instruction_data = 0;
|
||||
let instruction_data: u128 = 0;
|
||||
let message =
|
||||
nssa::public_transaction::Message::try_new(program_id, addresses, nonces, instruction_data).unwrap();
|
||||
let private_key = nssa::PrivateKey::try_new([1; 32]).unwrap();
|
||||
|
||||
@ -9,7 +9,6 @@ risc0-zkvm = "2.3.1"
|
||||
nssa-core = { path = "core" }
|
||||
program-methods = { path = "program_methods" }
|
||||
serde = "1.0.219"
|
||||
serde_cbor = "0.11.2"
|
||||
sha2 = "0.10.9"
|
||||
secp256k1 = "0.31.1"
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use std::io::{Cursor, Read};
|
||||
|
||||
use nssa_core::{
|
||||
account::Nonce,
|
||||
program::{InstructionData, ProgramId},
|
||||
@ -5,6 +7,8 @@ use nssa_core::{
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{Address, error::NssaError, program::Program};
|
||||
const MESSAGE_ENCODING_PREFIX_LEN: usize = 19;
|
||||
const MESSAGE_ENCODING_PREFIX: &[u8; MESSAGE_ENCODING_PREFIX_LEN] = b"NSSA/v0.1/TxMessage";
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct Message {
|
||||
@ -34,8 +38,6 @@ impl Message {
|
||||
/// TAG || <program_id> (bytes LE) * 8 || addresses_len (4 bytes LE) || addresses (32 bytes * N) || nonces_len (4 bytes LE) || nonces (16 bytes * M) || instruction_data_len || instruction_data (4 bytes * K)
|
||||
/// Integers and words are encoded in little-endian byte order, and fields appear in the above order.
|
||||
pub(crate) fn message_to_bytes(&self) -> Vec<u8> {
|
||||
const MESSAGE_ENCODING_PREFIX: &[u8; 19] = b"NSSA/v0.1/TxMessage";
|
||||
|
||||
let mut bytes = MESSAGE_ENCODING_PREFIX.to_vec();
|
||||
// program_id: [u32; 8]
|
||||
for word in &self.program_id {
|
||||
@ -64,4 +66,52 @@ impl Message {
|
||||
|
||||
bytes
|
||||
}
|
||||
|
||||
pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Self {
|
||||
let prefix = {
|
||||
let mut this = [0u8; MESSAGE_ENCODING_PREFIX_LEN];
|
||||
cursor.read_exact(&mut this).unwrap();
|
||||
this
|
||||
};
|
||||
assert_eq!(&prefix, MESSAGE_ENCODING_PREFIX);
|
||||
let program_id: ProgramId = {
|
||||
let mut this = [0u32; 8];
|
||||
for i in 0..8 {
|
||||
this[i] = u32_from_cursor(cursor);
|
||||
}
|
||||
this
|
||||
};
|
||||
let addresses_len = u32_from_cursor(cursor);
|
||||
let mut addresses = Vec::with_capacity(addresses_len as usize);
|
||||
for _ in 0..addresses_len {
|
||||
let mut value = [0u8; 32];
|
||||
cursor.read_exact(&mut value).unwrap();
|
||||
addresses.push(Address::new(value))
|
||||
}
|
||||
let nonces_len = u32_from_cursor(cursor);
|
||||
let mut nonces = Vec::with_capacity(nonces_len as usize);
|
||||
for _ in 0..nonces_len {
|
||||
let mut buf = [0u8; 16];
|
||||
cursor.read_exact(&mut buf).unwrap();
|
||||
nonces.push(u128::from_le_bytes(buf))
|
||||
}
|
||||
let instruction_data_len = u32_from_cursor(cursor);
|
||||
let mut instruction_data = Vec::with_capacity(instruction_data_len as usize);
|
||||
for _ in 0..instruction_data_len {
|
||||
let word = u32_from_cursor(cursor);
|
||||
instruction_data.push(word)
|
||||
}
|
||||
Self {
|
||||
program_id,
|
||||
addresses,
|
||||
nonces,
|
||||
instruction_data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn u32_from_cursor(cursor: &mut Cursor<&[u8]>) -> u32 {
|
||||
let mut word_buf = [0u8; 4];
|
||||
cursor.read_exact(&mut word_buf).unwrap();
|
||||
u32::from_le_bytes(word_buf)
|
||||
}
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
io::Cursor,
|
||||
};
|
||||
|
||||
use nssa_core::{
|
||||
account::{Account, AccountWithMetadata},
|
||||
program::validate_execution,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, digest::FixedOutput};
|
||||
|
||||
use crate::{V01State, address::Address, error::NssaError};
|
||||
@ -15,7 +17,7 @@ mod witness_set;
|
||||
pub use message::Message;
|
||||
pub use witness_set::WitnessSet;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct PublicTransaction {
|
||||
message: Message,
|
||||
witness_set: WitnessSet,
|
||||
@ -45,8 +47,24 @@ impl PublicTransaction {
|
||||
}
|
||||
}
|
||||
|
||||
fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut bytes = self.message.message_to_bytes();
|
||||
bytes.extend_from_slice(&self.witness_set.to_bytes());
|
||||
bytes
|
||||
}
|
||||
|
||||
fn from_bytes(bytes: &[u8]) -> Self {
|
||||
let mut cursor = Cursor::new(bytes);
|
||||
let message = Message::from_cursor(&mut cursor);
|
||||
let witness_set = WitnessSet::from_cursor(&mut cursor);
|
||||
Self {
|
||||
message,
|
||||
witness_set,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hash(&self) -> [u8; 32] {
|
||||
let bytes = serde_cbor::to_vec(&self).unwrap();
|
||||
let bytes = self.to_bytes();
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
hasher.update(&bytes);
|
||||
hasher.finalize_fixed().into()
|
||||
@ -116,3 +134,36 @@ impl PublicTransaction {
|
||||
Ok(message.addresses.iter().cloned().zip(post_states).collect())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{
|
||||
Address, PrivateKey, PublicTransaction, PublicKey,
|
||||
program::Program,
|
||||
public_transaction::{Message, WitnessSet},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let key1 = PrivateKey::try_new([1; 32]).unwrap();
|
||||
let key2 = PrivateKey::try_new([2; 32]).unwrap();
|
||||
let addr1 = Address::from_public_key(&PublicKey::new(&key1));
|
||||
let addr2 = Address::from_public_key(&PublicKey::new(&key2));
|
||||
let nonces = vec![5, 99];
|
||||
let instruction = 1337;
|
||||
let message = Message::try_new(
|
||||
Program::authenticated_transfer_program().id(),
|
||||
vec![addr1, addr2],
|
||||
nonces,
|
||||
instruction,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let witness_set = WitnessSet::for_message(&message, &[&key1, &key2]);
|
||||
let tx = PublicTransaction::new(message, witness_set);
|
||||
|
||||
let bytes = tx.to_bytes();
|
||||
let recov_tx = PublicTransaction::from_bytes(&bytes);
|
||||
assert_eq!(tx, recov_tx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
use std::io::{Cursor, Read};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{PrivateKey, PublicKey, Signature, public_transaction::Message};
|
||||
use crate::{PrivateKey, PublicKey, Signature, error::NssaError, public_transaction::Message};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct WitnessSet {
|
||||
pub(crate) signatures_and_public_keys: Vec<(Signature, PublicKey)>,
|
||||
}
|
||||
@ -32,4 +34,33 @@ impl WitnessSet {
|
||||
pub fn iter_signatures(&self) -> impl Iterator<Item = &(Signature, PublicKey)> {
|
||||
self.signatures_and_public_keys.iter()
|
||||
}
|
||||
|
||||
pub(crate) fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut bytes = Vec::new();
|
||||
let size = self.signatures_and_public_keys.len() as u32;
|
||||
bytes.extend_from_slice(&size.to_le_bytes());
|
||||
for (signature, public_key) in &self.signatures_and_public_keys {
|
||||
bytes.extend_from_slice(&signature.value);
|
||||
bytes.extend_from_slice(&public_key.0);
|
||||
}
|
||||
bytes
|
||||
}
|
||||
|
||||
// TODO: remove unwraps and return Result
|
||||
pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Self {
|
||||
let num_signatures: u32 = {
|
||||
let mut buf = [0u8; 4];
|
||||
cursor.read_exact(&mut buf).unwrap();
|
||||
u32::from_le_bytes(buf)
|
||||
};
|
||||
let mut signatures_and_public_keys = Vec::with_capacity(num_signatures as usize);
|
||||
for i in 0..num_signatures {
|
||||
let signature = Signature::from_cursor(cursor);
|
||||
let public_key = PublicKey::from_cursor(cursor);
|
||||
signatures_and_public_keys.push((signature, public_key))
|
||||
}
|
||||
Self {
|
||||
signatures_and_public_keys,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
use std::io::{Cursor, Read};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::PrivateKey;
|
||||
|
||||
|
||||
// TODO: Dummy impl. Replace by actual public key.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct PublicKey(pub(crate) [u8; 32]);
|
||||
|
||||
impl PublicKey {
|
||||
@ -19,3 +20,12 @@ impl PublicKey {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl PublicKey {
|
||||
// TODO: remove unwraps and return Result
|
||||
pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Self {
|
||||
let mut value = [0u8; 32];
|
||||
cursor.read_exact(&mut value).unwrap();
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::io::{Cursor, Read};
|
||||
|
||||
use crate::{PrivateKey, PublicKey, error::NssaError, public_transaction::Message};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Signature {
|
||||
value: [u8; 64],
|
||||
pub(crate) value: [u8; 64],
|
||||
}
|
||||
|
||||
impl Signature {
|
||||
@ -27,30 +27,11 @@ impl Signature {
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Signature {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
// Serialize as a slice
|
||||
serializer.serialize_bytes(&self.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Signature {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let bytes: &[u8] = Deserialize::deserialize(deserializer)?;
|
||||
if bytes.len() != 64 {
|
||||
return Err(serde::de::Error::invalid_length(
|
||||
bytes.len(),
|
||||
&"expected 64 bytes",
|
||||
));
|
||||
}
|
||||
impl Signature {
|
||||
// TODO: remove unwraps and return Result
|
||||
pub(crate) fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Self {
|
||||
let mut value = [0u8; 64];
|
||||
value.copy_from_slice(bytes);
|
||||
Ok(Signature { value })
|
||||
cursor.read_exact(&mut value).unwrap();
|
||||
Self { value }
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,10 +102,13 @@ impl SequencerCore {
|
||||
.mempool
|
||||
.pop_size(self.sequencer_config.max_num_tx_in_block);
|
||||
|
||||
let valid_transactions = transactions
|
||||
println!("##");
|
||||
println!("{:?}", transactions.len());
|
||||
let valid_transactions: Vec<_> = transactions
|
||||
.into_iter()
|
||||
.filter_map(|tx| self.execute_check_transaction_on_state(tx).ok())
|
||||
.collect();
|
||||
println!("{:?}", valid_transactions.len());
|
||||
|
||||
let prev_block_hash = self
|
||||
.store
|
||||
@ -157,15 +160,13 @@ mod tests {
|
||||
|
||||
fn setup_sequencer_config() -> SequencerConfig {
|
||||
let acc1_addr = vec![
|
||||
// 13, 150, 223, 204, 65, 64, 25, 56, 12, 157, 222, 12, 211, 220, 229, 170, 201, 15, 181,
|
||||
// 68, 59, 248, 113, 16, 135, 65, 174, 175, 222, 85, 42, 215,
|
||||
1; 32
|
||||
27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213, 170, 186, 5, 101, 215, 30, 24,
|
||||
52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, 143,
|
||||
];
|
||||
|
||||
let acc2_addr = vec![
|
||||
// 151, 72, 112, 233, 190, 141, 10, 192, 138, 168, 59, 63, 199, 167, 166, 134, 41, 29,
|
||||
// 135, 50, 80, 138, 186, 152, 179, 96, 128, 243, 156, 44, 243, 100,
|
||||
2; 32
|
||||
77, 75, 108, 209, 54, 16, 50, 202, 155, 210, 174, 185, 217, 0, 170, 77, 69, 217, 234,
|
||||
216, 10, 201, 66, 51, 116, 196, 81, 167, 37, 77, 7, 102,
|
||||
];
|
||||
|
||||
let initial_acc1 = AccountInitialData {
|
||||
@ -236,13 +237,13 @@ mod tests {
|
||||
#[test]
|
||||
fn test_start_different_intial_accounts_balances() {
|
||||
let acc1_addr = vec![
|
||||
13, 150, 223, 204, 65, 64, 25, 56, 12, 157, 222, 12, 211, 220, 229, 170, 201, 15, 181,
|
||||
68, 59, 248, 113, 16, 135, 65, 174, 175, 222, 42, 42, 42,
|
||||
27, 132, 197, 86, 123, 18, 100, 64, 153, 93, 62, 213, 170, 186, 5, 101, 215, 30, 24,
|
||||
52, 96, 72, 25, 255, 156, 23, 245, 233, 213, 221, 7, 143,
|
||||
];
|
||||
|
||||
let acc2_addr = vec![
|
||||
151, 72, 112, 233, 190, 141, 10, 192, 138, 168, 59, 63, 199, 167, 166, 134, 41, 29,
|
||||
135, 50, 80, 138, 186, 152, 179, 96, 128, 243, 156, 42, 42, 42,
|
||||
77, 75, 108, 209, 54, 16, 50, 202, 155, 210, 174, 185, 217, 0, 170, 77, 69, 217, 234,
|
||||
216, 10, 201, 66, 51, 116, 196, 81, 167, 37, 77, 7, 102,
|
||||
];
|
||||
|
||||
let initial_acc1 = AccountInitialData {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user