Skip to content

Commit

Permalink
Add an extra data field to Txs that is hashed before signing.
Browse files Browse the repository at this point in the history
  • Loading branch information
murisi committed Feb 20, 2023
1 parent 5a60a9f commit 3d2bd33
Show file tree
Hide file tree
Showing 21 changed files with 163 additions and 88 deletions.
8 changes: 3 additions & 5 deletions apps/src/lib/client/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,13 +196,11 @@ pub async fn submit_init_account(mut ctx: Context, args: args::TxInitAccount) {
}

let tx_code = ctx.read_wasm(TX_INIT_ACCOUNT_WASM);
let data = InitAccount {
public_key,
vp_code,
};
let data = InitAccount { public_key };
let data = data.try_to_vec().expect("Encoding tx data shouldn't fail");

let tx = Tx::new(tx_code, Some(data));
let mut tx = Tx::new(tx_code, Some(data));
tx.extra = Some(vp_code);
let (ctx, initialized_accounts) = process_tx(
ctx,
&args.tx,
Expand Down
1 change: 1 addition & 0 deletions apps/src/lib/node/ledger/shell/process_proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ mod test_process_proposal {
),
timestamp,
inner_tx: tx.inner_tx,
extra: None,
}
} else {
panic!("Test failed");
Expand Down
10 changes: 1 addition & 9 deletions core/src/ledger/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ use crate::types::chain::{ChainId, CHAIN_ID_LENGTH};
use crate::types::internal::TxQueue;
use crate::types::storage::{
BlockHash, BlockHeight, BlockResults, Epoch, Epochs, Header, Key, KeySeg,
TxIndex, BLOCK_HASH_LENGTH,
BLOCK_HASH_LENGTH,
};
use crate::types::time::DateTimeUtc;
use crate::types::token;
Expand Down Expand Up @@ -97,8 +97,6 @@ where
pub next_epoch_min_start_time: DateTimeUtc,
/// The current established address generator
pub address_gen: EstablishedAddressGen,
/// The shielded transaction index
pub tx_index: TxIndex,
/// The currently saved conversion state
pub conversion_state: ConversionState,
/// Wrapper txs to be decrypted in the next block proposal
Expand Down Expand Up @@ -354,7 +352,6 @@ where
address_gen: EstablishedAddressGen::new(
"Privacy is a function of liberty.",
),
tx_index: TxIndex::default(),
conversion_state: ConversionState::default(),
#[cfg(feature = "ferveo-tpke")]
tx_queue: TxQueue::default(),
Expand Down Expand Up @@ -1053,10 +1050,6 @@ where
Ok(self.block.epoch)
}

fn get_tx_index(&self) -> std::result::Result<TxIndex, storage_api::Error> {
Ok(self.tx_index)
}

fn get_native_token(
&self,
) -> std::result::Result<Address, storage_api::Error> {
Expand Down Expand Up @@ -1142,7 +1135,6 @@ pub mod testing {
address_gen: EstablishedAddressGen::new(
"Test address generator seed",
),
tx_index: TxIndex::default(),
conversion_state: ConversionState::default(),
#[cfg(feature = "ferveo-tpke")]
tx_queue: TxQueue::default(),
Expand Down
5 changes: 1 addition & 4 deletions core/src/ledger/storage_api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use borsh::{BorshDeserialize, BorshSerialize};
pub use error::{CustomError, Error, OptionExt, Result, ResultExt};

use crate::types::address::Address;
use crate::types::storage::{self, BlockHash, BlockHeight, Epoch, TxIndex};
use crate::types::storage::{self, BlockHash, BlockHeight, Epoch};

/// Common storage read interface
///
Expand Down Expand Up @@ -85,9 +85,6 @@ pub trait StorageRead {
/// current transaction is being applied.
fn get_block_epoch(&self) -> Result<Epoch>;

/// Get the transaction index.
fn get_tx_index(&self) -> Result<TxIndex>;

/// Get the native token address
fn get_native_token(&self) -> Result<Address>;
}
Expand Down
7 changes: 7 additions & 0 deletions core/src/ledger/tx_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::ledger::storage_api::{self, StorageRead, StorageWrite};
use crate::types::address::Address;
use crate::types::ibc::IbcEvent;
use crate::types::storage;
use crate::types::storage::TxIndex;
use crate::types::time::Rfc3339String;

/// Transaction host functions
Expand Down Expand Up @@ -60,4 +61,10 @@ pub trait TxEnv: StorageRead + StorageWrite {

/// Get time of the current block header as rfc 3339 string
fn get_block_time(&self) -> Result<Rfc3339String, storage_api::Error>;

/// Get the transaction index
fn get_tx_index(&self) -> Result<TxIndex, storage_api::Error>;

/// Get the transaction extra data
fn get_tx_extra(&self) -> Result<Vec<u8>, storage_api::Error>;
}
1 change: 1 addition & 0 deletions core/src/proto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ mod tests {
data: Some("arbitrary data".as_bytes().to_owned()),
timestamp: Some(std::time::SystemTime::now().into()),
inner_tx: Some(inner_tx),
extra: None,
};
let mut tx_bytes = vec![];
tx.encode(&mut tx_bytes).unwrap();
Expand Down
8 changes: 8 additions & 0 deletions core/src/proto/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ pub struct Tx {
pub code: Vec<u8>,
pub data: Option<Vec<u8>>,
pub timestamp: DateTimeUtc,
pub extra: Option<Vec<u8>>,
/// the encrypted inner transaction if data contains a WrapperTx
#[cfg(feature = "ferveo-tpke")]
pub inner_tx: Option<EncryptedTx>,
Expand All @@ -172,6 +173,7 @@ impl TryFrom<&[u8]> for Tx {
Ok(Tx {
code: tx.code,
data: tx.data,
extra: tx.extra,
timestamp,
inner_tx,
})
Expand All @@ -188,6 +190,7 @@ impl From<Tx> for types::Tx {
types::Tx {
code: tx.code,
data: tx.data,
extra: tx.extra,
timestamp,
inner_tx,
}
Expand Down Expand Up @@ -287,6 +290,7 @@ impl Tx {
data,
timestamp: DateTimeUtc::now(),
inner_tx: None,
extra: None,
}
}

Expand All @@ -305,6 +309,7 @@ impl Tx {
let mut bytes = vec![];
types::Tx {
code: hash_tx(&self.code).0.to_vec(),
extra: self.extra.as_ref().map(|x| hash_tx(x).0.to_vec()),
data: self.data.clone(),
timestamp,
inner_tx: None,
Expand Down Expand Up @@ -332,6 +337,7 @@ impl Tx {
Tx {
code: self.code,
data: Some(signed),
extra: self.extra,
timestamp: self.timestamp,
inner_tx: self.inner_tx,
}
Expand All @@ -351,6 +357,7 @@ impl Tx {
let data = signed_tx_data.data;
let tx = Tx {
code: self.code.clone(),
extra: self.extra.clone(),
data,
timestamp: self.timestamp,
inner_tx: self.inner_tx.clone(),
Expand Down Expand Up @@ -478,6 +485,7 @@ mod tests {
data: Some(data),
timestamp: None,
inner_tx: None,
extra: None,
};
let mut bytes = vec![];
types_tx.encode(&mut bytes).expect("encoding failed");
Expand Down
4 changes: 2 additions & 2 deletions core/src/types/transaction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,6 @@ pub struct InitAccount {
/// for signature verification of transactions for the newly created
/// account.
pub public_key: common::PublicKey,
/// The VP code
pub vp_code: Vec<u8>,
}

/// A tx data type to initialize a new validator account.
Expand Down Expand Up @@ -297,13 +295,15 @@ pub mod tx_types {
data: Some(data.clone()),
timestamp: tx.timestamp,
inner_tx: tx.inner_tx.clone(),
extra: tx.extra.clone(),
}
.partial_hash();
match TxType::try_from(Tx {
code: tx.code,
data: Some(data),
timestamp: tx.timestamp,
inner_tx: tx.inner_tx,
extra: tx.extra,
})
.map_err(|err| TxError::Deserialization(err.to_string()))?
{
Expand Down
3 changes: 2 additions & 1 deletion proto/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ message Tx {
// TODO this optional is useless because it's default on proto3
optional bytes data = 2;
google.protobuf.Timestamp timestamp = 3;
optional bytes inner_tx = 4;
optional bytes extra = 4;
optional bytes inner_tx = 5;
}

message Dkg { string data = 1; }
Expand Down
8 changes: 0 additions & 8 deletions shared/src/ledger/native_vp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,6 @@ where
self.ctx.get_block_epoch()
}

fn get_tx_index(&self) -> Result<TxIndex, storage_api::Error> {
self.ctx.get_tx_index().into_storage_result()
}

fn get_native_token(&self) -> Result<Address, storage_api::Error> {
self.ctx.get_native_token()
}
Expand Down Expand Up @@ -322,10 +318,6 @@ where
self.ctx.get_block_epoch()
}

fn get_tx_index(&self) -> Result<TxIndex, storage_api::Error> {
self.ctx.get_tx_index().into_storage_result()
}

fn get_native_token(&self) -> Result<Address, storage_api::Error> {
Ok(self.ctx.storage.native_token.clone())
}
Expand Down
5 changes: 1 addition & 4 deletions shared/src/ledger/protocol/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,12 @@ where
gas_meter
.add_compiling_fee(tx.code.len())
.map_err(Error::GasError)?;
let empty = vec![];
let tx_data = tx.data.as_ref().unwrap_or(&empty);
wasm::run::tx(
storage,
write_log,
gas_meter,
tx_index,
&tx.code,
tx_data,
tx,
vp_wasm_cache,
tx_wasm_cache,
)
Expand Down
52 changes: 49 additions & 3 deletions shared/src/vm/host_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ where
pub iterators: MutHostRef<'a, &'a PrefixIterators<'a, DB>>,
/// Transaction gas meter.
pub gas_meter: MutHostRef<'a, &'a BlockGasMeter>,
/// The transaction code is used for signature verification
pub tx: HostRef<'a, &'a Tx>,
/// The transaction index is used to identify a shielded transaction's
/// parent
pub tx_index: HostRef<'a, &'a TxIndex>,
Expand Down Expand Up @@ -131,6 +133,7 @@ where
write_log: &mut WriteLog,
iterators: &mut PrefixIterators<'a, DB>,
gas_meter: &mut BlockGasMeter,
tx: &Tx,
tx_index: &TxIndex,
verifiers: &mut BTreeSet<Address>,
result_buffer: &mut Option<Vec<u8>>,
Expand All @@ -141,6 +144,7 @@ where
let write_log = unsafe { MutHostRef::new(write_log) };
let iterators = unsafe { MutHostRef::new(iterators) };
let gas_meter = unsafe { MutHostRef::new(gas_meter) };
let tx = unsafe { HostRef::new(tx) };
let tx_index = unsafe { HostRef::new(tx_index) };
let verifiers = unsafe { MutHostRef::new(verifiers) };
let result_buffer = unsafe { MutHostRef::new(result_buffer) };
Expand All @@ -153,6 +157,7 @@ where
write_log,
iterators,
gas_meter,
tx,
tx_index,
verifiers,
result_buffer,
Expand Down Expand Up @@ -195,6 +200,7 @@ where
write_log: self.write_log.clone(),
iterators: self.iterators.clone(),
gas_meter: self.gas_meter.clone(),
tx: self.tx.clone(),
tx_index: self.tx_index.clone(),
verifiers: self.verifiers.clone(),
result_buffer: self.result_buffer.clone(),
Expand Down Expand Up @@ -1481,9 +1487,9 @@ where
Ok(height.0)
}

/// Getting the block height function exposed to the wasm VM Tx
/// environment. The height is that of the block to which the current
/// transaction is being applied.
/// Getting the transaction index function exposed to the wasm VM Tx
/// environment. The index is that of the transaction being applied
/// in the current block.
pub fn tx_get_tx_index<MEM, DB, H, CA>(
env: &TxVmEnv<MEM, DB, H, CA>,
) -> TxResult<u32>
Expand All @@ -1498,6 +1504,44 @@ where
Ok(tx_index.0)
}

/// Getting the transaction extra data function exposed to the wasm VM Tx
/// environment. The extra data is that of the transaction being applied.
pub fn tx_get_tx_extra<MEM, DB, H, CA>(
env: &TxVmEnv<MEM, DB, H, CA>,
result_ptr: u64,
) -> TxResult<()>
where
MEM: VmMemory,
DB: storage::DB + for<'iter> storage::DBIter<'iter>,
H: StorageHasher,
CA: WasmCacheAccess,
{
let tx = unsafe { env.ctx.tx.get() };
tx_add_gas(env, crate::vm::host_env::gas::MIN_STORAGE_GAS)?;
let gas = env
.memory
.write_bytes(result_ptr, tx.extra.as_ref().unwrap_or(&vec![]))
.map_err(|e| TxRuntimeError::MemoryError(Box::new(e)))?;
tx_add_gas(env, gas)
}

/// Getting the transaction extra data length function exposed to the wasm
/// VM Tx environment. The extra data length is that of the transaction
/// being applied.
pub fn tx_get_tx_extra_len<MEM, DB, H, CA>(
env: &TxVmEnv<MEM, DB, H, CA>,
) -> TxResult<u64>
where
MEM: VmMemory,
DB: storage::DB + for<'iter> storage::DBIter<'iter>,
H: StorageHasher,
CA: WasmCacheAccess,
{
let tx = unsafe { env.ctx.tx.get() };
tx_add_gas(env, crate::vm::host_env::gas::MIN_STORAGE_GAS)?;
Ok(tx.extra.as_ref().map(|x| Vec::len(x) as u64).unwrap_or(0))
}

/// Getting the block height function exposed to the wasm VM VP
/// environment. The height is that of the block to which the current
/// transaction is being applied.
Expand Down Expand Up @@ -1953,6 +1997,7 @@ pub mod testing {
iterators: &mut PrefixIterators<'static, DB>,
verifiers: &mut BTreeSet<Address>,
gas_meter: &mut BlockGasMeter,
tx: &Tx,
tx_index: &TxIndex,
result_buffer: &mut Option<Vec<u8>>,
#[cfg(feature = "wasm-runtime")] vp_wasm_cache: &mut VpCache<CA>,
Expand All @@ -1969,6 +2014,7 @@ pub mod testing {
write_log,
iterators,
gas_meter,
tx,
tx_index,
verifiers,
result_buffer,
Expand Down
2 changes: 2 additions & 0 deletions shared/src/vm/wasm/host_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ where
"namada_tx_emit_ibc_event" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_emit_ibc_event),
"namada_tx_get_chain_id" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_chain_id),
"namada_tx_get_tx_index" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_tx_index),
"namada_tx_get_tx_extra" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_tx_extra),
"namada_tx_get_tx_extra_len" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_tx_extra_len),
"namada_tx_get_block_height" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_block_height),
"namada_tx_get_block_time" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_block_time),
"namada_tx_get_block_hash" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_block_hash),
Expand Down
Loading

0 comments on commit 3d2bd33

Please sign in to comment.