Skip to content

Commit

Permalink
Merge pull request #752 from SethDusek/optimizations
Browse files Browse the repository at this point in the history
Optimizations
  • Loading branch information
SethDusek authored Jul 6, 2024
2 parents 519ec21 + c7fa9f3 commit f0b4136
Show file tree
Hide file tree
Showing 132 changed files with 1,764 additions and 1,500 deletions.
6 changes: 3 additions & 3 deletions bindings/ergo-lib-wasm/src/ast/js_conv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pub(crate) fn constant_from_js(val: &JsValue) -> Result<Constant, ConvError> {
Ok(Constant {
tpe: SType::SColl(SType::SByte.into()),
v: Literal::Coll(CollKind::NativeColl(NativeColl::CollByte(
bytes.to_vec().as_vec_i8(),
bytes.to_vec().as_vec_i8().into(),
))),
})
} else if let Ok(arr) = val.clone().dyn_into::<Array>() {
Expand Down Expand Up @@ -164,10 +164,10 @@ pub(crate) fn constant_to_js(c: Constant) -> Result<JsValue, ConvError> {
}
Literal::Coll(CollKind::WrappedColl { elem_tpe, items }) => {
let arr = Array::new();
for item in items {
for item in items.iter() {
arr.push(&constant_to_js(Constant {
tpe: elem_tpe.clone(),
v: item,
v: item.clone(),
})?);
}
arr.into()
Expand Down
3 changes: 3 additions & 0 deletions bindings/ergo-lib-wasm/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::json::UnsignedTransactionJsonEip12;
use ergo_lib::chain;
use ergo_lib::chain::transaction::{distinct_token_ids, TxIoVec};
use ergo_lib::ergotree_ir::serialization::SigmaSerializable;
use ergo_lib::wallet::signing::make_context;
use gloo_utils::format::JsValueSerdeExt;
use js_sys::Uint8Array;
use std::convert::{TryFrom, TryInto};
Expand Down Expand Up @@ -425,8 +426,10 @@ pub fn verify_tx_input_proof(
)
.map_err(to_js)?;
let state_context_inner = state_context.clone().into();
let mut context = make_context(&state_context_inner, &tx_context, input_idx).map_err(to_js)?;
Ok(ergo_lib::chain::transaction::verify_tx_input_proof(
&tx_context,
&mut context,
&state_context_inner,
input_idx,
&tx_context.spending_tx.bytes_to_sign().map_err(to_js)?,
Expand Down
6 changes: 3 additions & 3 deletions ergo-lib/src/chain/json/context_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ mod tests {
],
"creationHeight" : 693475,
"additionalRegisters" : {
},
"transactionId" : "c8520befd345ff40fcf244b44ffe8cea29c8b116b174cfaf4f2a521604d531a4",
"index" : 0
Expand All @@ -116,7 +116,7 @@ mod tests {
],
"creationHeight" : 693475,
"additionalRegisters" : {
},
"transactionId" : "c8520befd345ff40fcf244b44ffe8cea29c8b116b174cfaf4f2a521604d531a4",
"index" : 1
Expand All @@ -129,7 +129,7 @@ mod tests {
],
"creationHeight" : 693475,
"additionalRegisters" : {
},
"transactionId" : "c8520befd345ff40fcf244b44ffe8cea29c8b116b174cfaf4f2a521604d531a4",
"index" : 2
Expand Down
14 changes: 7 additions & 7 deletions ergo-lib/src/chain/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub mod unsigned;

use bounded_vec::BoundedVec;
use ergo_chain_types::blake2b256_hash;
use ergotree_interpreter::eval::context::Context;
pub use ergotree_interpreter::eval::context::TxIoVec;
use ergotree_interpreter::eval::env::Env;
use ergotree_interpreter::eval::extract_sigma_boolean;
Expand Down Expand Up @@ -37,7 +38,7 @@ use ergotree_ir::serialization::SigmaSerializationError;
use ergotree_ir::serialization::SigmaSerializeResult;
pub use input::*;

use crate::wallet::signing::make_context;
use crate::wallet::signing::update_context;
use crate::wallet::signing::TransactionContext;
use crate::wallet::tx_context::TransactionContextError;

Expand All @@ -50,7 +51,6 @@ use indexmap::IndexSet;
use std::convert::TryFrom;
use std::convert::TryInto;
use std::iter::FromIterator;
use std::rc::Rc;

use super::ergo_state_context::ErgoStateContext;

Expand Down Expand Up @@ -342,12 +342,14 @@ pub enum TransactionError {
}

/// Verify transaction input's proof
pub fn verify_tx_input_proof(
tx_context: &TransactionContext<Transaction>,
pub fn verify_tx_input_proof<'ctx>(
tx_context: &'ctx TransactionContext<Transaction>,
ctx: &mut Context<'ctx>,
state_context: &ErgoStateContext,
input_idx: usize,
bytes_to_sign: &[u8],
) -> Result<VerificationResult, TxValidationError> {
update_context(ctx, tx_context, input_idx)?;
let input = tx_context
.spending_tx
.inputs
Expand All @@ -356,10 +358,9 @@ pub fn verify_tx_input_proof(
let input_box = tx_context
.get_input_box(&input.box_id)
.ok_or(TransactionContextError::InputBoxNotFound(input_idx))?;
let ctx = Rc::new(make_context(state_context, tx_context, input_idx)?);
let verifier = TestVerifier;
// Try spending in storage rent, if any condition is not satisfied fallback to normal script validation
match try_spend_storage_rent(input, &input_box, state_context, &ctx) {
match try_spend_storage_rent(input, input_box, state_context, ctx) {
Some(()) => Ok(VerificationResult {
result: true,
cost: 0,
Expand All @@ -371,7 +372,6 @@ pub fn verify_tx_input_proof(
None => verifier
.verify(
&input_box.ergo_tree,
&Env::empty(),
ctx,
input.spending_proof.proof.clone(),
bytes_to_sign,
Expand Down
51 changes: 22 additions & 29 deletions ergo-lib/src/chain/transaction/ergo_transaction.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
//! Exposes common properties for signed and unsigned transactions
use ergotree_interpreter::{
eval::context::TxIoVec,
sigma_protocol::{
prover::ContextExtension,
verifier::{VerificationResult, VerifierError},
},
use ergotree_interpreter::sigma_protocol::{
prover::ContextExtension,
verifier::{VerificationResult, VerifierError},
};
use ergotree_ir::{
chain::{
Expand Down Expand Up @@ -87,11 +84,11 @@ pub enum TxValidationError {
/// Exposes common properties for signed and unsigned transactions
pub trait ErgoTransaction {
/// input boxes ids
fn inputs_ids(&self) -> TxIoVec<BoxId>;
fn inputs_ids(&self) -> impl ExactSizeIterator<Item = BoxId>;
/// data input boxes
fn data_inputs(&self) -> Option<TxIoVec<DataInput>>;
fn data_inputs(&self) -> Option<&[DataInput]>;
/// output boxes
fn outputs(&self) -> TxIoVec<ErgoBox>;
fn outputs(&self) -> &[ErgoBox];
/// ContextExtension for the given input index
fn context_extension(&self, input_index: usize) -> Option<ContextExtension>;

Expand All @@ -108,30 +105,26 @@ pub trait ErgoTransaction {
.ok_or(TxValidationError::OutputSumOverflow)?;

// Check if there are no double-spends in input (one BoxId being spent more than once)
let unique_count = inputs.iter().unique().count();
if unique_count != inputs.len() {
return Err(TxValidationError::DoubleSpend(unique_count, inputs.len()));
let len = inputs.len();
let unique_count = inputs.unique().count();
if unique_count != len {
return Err(TxValidationError::DoubleSpend(unique_count, len));
}
Ok(())
}
}

impl ErgoTransaction for UnsignedTransaction {
fn inputs_ids(&self) -> TxIoVec<BoxId> {
self.inputs.clone().mapped(|input| input.box_id)
fn inputs_ids(&self) -> impl ExactSizeIterator<Item = BoxId> {
self.inputs.iter().map(|input| input.box_id)
}

fn data_inputs(&self) -> Option<TxIoVec<DataInput>> {
self.data_inputs.clone()
fn data_inputs(&self) -> Option<&[DataInput]> {
self.data_inputs.as_ref().map(|di| di.as_slice())
}

fn outputs(&self) -> TxIoVec<ErgoBox> {
#[allow(clippy::unwrap_used)] // box serialization cannot fail?
self.output_candidates
.clone()
.enumerated()
.try_mapped(|(idx, b)| ErgoBox::from_box_candidate(&b, self.id(), idx as u16))
.unwrap()
fn outputs(&self) -> &[ErgoBox] {
self.outputs.as_slice()
}

fn context_extension(&self, input_index: usize) -> Option<ContextExtension> {
Expand All @@ -142,16 +135,16 @@ impl ErgoTransaction for UnsignedTransaction {
}

impl ErgoTransaction for Transaction {
fn inputs_ids(&self) -> TxIoVec<BoxId> {
self.inputs.clone().mapped(|input| input.box_id)
fn inputs_ids(&self) -> impl ExactSizeIterator<Item = BoxId> {
self.inputs.iter().map(|input| input.box_id)
}

fn data_inputs(&self) -> Option<TxIoVec<DataInput>> {
self.data_inputs.clone()
fn data_inputs(&self) -> Option<&[DataInput]> {
self.data_inputs.as_ref().map(|di| di.as_slice())
}

fn outputs(&self) -> TxIoVec<ErgoBox> {
self.outputs.clone()
fn outputs(&self) -> &[ErgoBox] {
self.outputs.as_slice()
}

fn context_extension(&self, input_index: usize) -> Option<ContextExtension> {
Expand Down
9 changes: 4 additions & 5 deletions ergo-lib/src/chain/transaction/reduced.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
//! Represent `reduced` transaction, i.e. unsigned transaction where each unsigned input
//! is augmented with ReducedInput which contains a script reduction result.

use std::rc::Rc;

use ergotree_interpreter::eval::env::Env;
use ergotree_interpreter::eval::reduce_to_crypto;
use ergotree_interpreter::sigma_protocol::prover::ContextExtension;
use ergotree_interpreter::sigma_protocol::prover::ProverError;
Expand All @@ -18,6 +15,7 @@ use crate::chain::ergo_state_context::ErgoStateContext;
use crate::chain::transaction::Transaction;
use crate::chain::transaction::UnsignedInput;
use crate::wallet::signing::make_context;
use crate::wallet::signing::update_context;
use crate::wallet::signing::TransactionContext;
use crate::wallet::signing::TxSigningError;
use crate::wallet::tx_context::TransactionContextError;
Expand Down Expand Up @@ -70,21 +68,22 @@ pub fn reduce_tx(
state_context: &ErgoStateContext,
) -> Result<ReducedTransaction, TxSigningError> {
let tx = &tx_context.spending_tx;
let mut ctx = make_context(state_context, &tx_context, 0)?;
let reduced_inputs = tx
.inputs
.clone()
.enumerated()
.try_mapped::<_, _, TxSigningError>(|(idx, input)| {
update_context(&mut ctx, &tx_context, idx)?;
let input_box = tx_context
.get_input_box(&input.box_id)
.ok_or(TransactionContextError::InputBoxNotFound(idx))?;
let ctx = Rc::new(make_context(state_context, &tx_context, idx)?);
let expr = input_box
.ergo_tree
.proposition()
.map_err(ProverError::ErgoTreeError)
.map_err(|e| TxSigningError::ProverError(e, idx))?;
let reduction_result = reduce_to_crypto(&expr, &Env::empty(), ctx)
let reduction_result = reduce_to_crypto(&expr, &ctx)
.map_err(ProverError::EvalError)
.map_err(|e| TxSigningError::ProverError(e, idx))?;
Ok(ReducedInput {
Expand Down
20 changes: 20 additions & 0 deletions ergo-lib/src/chain/transaction/unsigned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use super::{distinct_token_ids, TransactionError};
use bounded_vec::BoundedVec;
use ergo_chain_types::blake2b256_hash;

use ergotree_ir::chain::ergo_box::ErgoBox;
use ergotree_ir::chain::ergo_box::ErgoBoxCandidate;
use ergotree_ir::chain::token::TokenId;
use ergotree_ir::chain::tx_id::TxId;
Expand Down Expand Up @@ -36,6 +37,7 @@ pub struct UnsignedTransaction {
pub data_inputs: Option<TxIoVec<DataInput>>,
/// box candidates to be created by this transaction
pub output_candidates: TxIoVec<ErgoBoxCandidate>,
pub(crate) outputs: TxIoVec<ErgoBox>,
}

impl UnsignedTransaction {
Expand Down Expand Up @@ -63,15 +65,33 @@ impl UnsignedTransaction {
data_inputs: Option<TxIoVec<DataInput>>,
output_candidates: TxIoVec<ErgoBoxCandidate>,
) -> Result<UnsignedTransaction, SigmaSerializationError> {
#[allow(clippy::unwrap_used)] // box serialization cannot fail
let outputs = output_candidates
.iter()
.enumerate()
.map(|(idx, b)| ErgoBox::from_box_candidate(b, TxId::zero(), idx as u16).unwrap())
.collect::<Vec<_>>()
.try_into()
.unwrap();

let tx_to_sign = UnsignedTransaction {
tx_id: TxId::zero(),
inputs,
data_inputs,
output_candidates,
outputs,
};
let tx_id = tx_to_sign.calc_tx_id()?;

let outputs = tx_to_sign
.output_candidates
.clone()
.enumerated()
.try_mapped_ref(|(idx, bc)| ErgoBox::from_box_candidate(bc, tx_id, *idx as u16))?;

Ok(UnsignedTransaction {
tx_id,
outputs,
..tx_to_sign
})
}
Expand Down
4 changes: 4 additions & 0 deletions ergo-lib/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use crate::wallet::multi_sig::{

use self::ext_secret_key::ExtSecretKey;
use self::ext_secret_key::ExtSecretKeyError;
use self::signing::make_context;
use self::signing::sign_message;
use self::signing::sign_reduced_transaction;
use self::signing::sign_tx_input;
Expand Down Expand Up @@ -164,10 +165,13 @@ impl Wallet {
) -> Result<Input, WalletError> {
let tx = tx_context.spending_tx.clone();
let message_to_sign = tx.bytes_to_sign().map_err(TxSigningError::from)?;
let mut context =
make_context(state_context, &tx_context, input_idx).map_err(TxSigningError::from)?;
Ok(sign_tx_input(
self.prover.as_ref(),
&tx_context,
state_context,
&mut context,
tx_hints,
input_idx,
message_to_sign.as_slice(),
Expand Down
Loading

0 comments on commit f0b4136

Please sign in to comment.