Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: new PublishTemplate instruction #1208

Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions dan_layer/consensus/src/consensus_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ pub struct ConsensusConstants {
/// The value that fees are divided by to determine the amount of fees to burn. 0 means no fees are burned.
pub fee_exhaust_divisor: u64,
pub epochs_per_era: Epoch,
/// Maximum size in bytes for a template WASM binary.
pub template_binary_max_size_bytes: usize,
}

impl ConsensusConstants {
Expand All @@ -63,6 +65,7 @@ impl ConsensusConstants {
max_block_size: 500,
fee_exhaust_divisor: 20, // 5%
epochs_per_era: Epoch(10),
template_binary_max_size_bytes: 1000 * 1000 * 2, // 2 MB
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion dan_layer/consensus_tests/src/support/harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,7 @@ impl TestBuilder {
max_block_size: 500,
fee_exhaust_divisor: 20,
epochs_per_era: Epoch(10),
template_binary_max_size_bytes: 1000 * 1000 * 2,
},
},
}
Expand Down Expand Up @@ -616,7 +617,7 @@ impl TestBuilder {
}
true
})
.map(|(address, shard_group, shard_addr, _, _, _)| {
.map(|(address, shard_group, shard_addr, _, _, _)| {
let sql_address = sql_address.replace("{}", &address.0);
let (sk, pk) = helpers::derive_keypair_from_address(&address);

Expand Down
1 change: 1 addition & 0 deletions dan_layer/engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ tari_template_builtin = { workspace = true }
tari_template_lib = { workspace = true }
tari_utilities = { workspace = true }
tari_transaction = { workspace = true }
tari_consensus = { workspace = true }
Copy link
Member

@sdbondi sdbondi Dec 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consensus and execution must remain decoupled.

I see you're using consensus constants to dictate the maximum permitted size of a template.

I suggest creating a TransactionProcessorConfig struct that you pass into the processor that we can configure using consensus constants in the validator/indexer's bootstrap.rs. The network can also go into that config as well as any future config.

pub struct TransactionProcessorConfig {
   pub network: Network,
  pub template_binary_max_size_bytes: usize
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay, totally makes sense, let me update

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just pushed


anyhow = { workspace = true }
blake2 = { workspace = true }
Expand Down
6 changes: 5 additions & 1 deletion dan_layer/engine/src/transaction/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
use tari_engine_types::indexed_value::IndexedValueError;
use tari_template_lib::models::TemplateAddress;

use crate::{runtime::RuntimeError, wasm::WasmExecutionError};
use crate::{runtime::RuntimeError, template::TemplateLoaderError, wasm::WasmExecutionError};

#[derive(Debug, thiserror::Error)]
pub enum TransactionError {
Expand All @@ -45,4 +45,8 @@ pub enum TransactionError {
FunctionNotFound { name: String },
#[error("Invariant error: {details}")]
InvariantError { details: String },
#[error("Load template error: {0}")]
LoadTemplate(#[from] TemplateLoaderError),
#[error("WASM binary too big! {0} bytes are greater than allowed maximum {1} bytes.")]
WasmBinaryTooBig(usize, usize),
}
40 changes: 35 additions & 5 deletions dan_layer/engine/src/transaction/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use log::*;
use tari_bor::to_value;
use tari_common::configuration::Network;
use tari_common_types::types::PublicKey;
use tari_consensus::consensus_constants::ConsensusConstants;
use tari_dan_common_types::{services::template_provider::TemplateProvider, Epoch};
use tari_engine_types::{
commit_result::{ExecuteResult, FinalizeResult, RejectReason, TransactionResult},
Expand All @@ -42,7 +43,7 @@ use tari_template_builtin::ACCOUNT_TEMPLATE_ADDRESS;
use tari_template_lib::{
arg,
args,
args::{Arg, WorkspaceAction},
args::{Arg, LogLevel, WorkspaceAction},
auth::OwnerRule,
crypto::RistrettoPublicKeyBytes,
invoke_args,
Expand All @@ -66,7 +67,7 @@ use crate::{
template::LoadedTemplate,
traits::Invokable,
transaction::TransactionError,
wasm::WasmProcess,
wasm::{WasmModule, WasmProcess},
};

const LOG_TARGET: &str = "tari::dan::engine::instruction_processor";
Expand Down Expand Up @@ -149,7 +150,10 @@ impl<TTemplateProvider: TemplateProvider<Template = LoadedTemplate> + 'static> T

let (fee_instructions, instructions) = transaction.into_instructions();

let fee_exec_results = Self::process_instructions(&template_provider, &runtime, fee_instructions);
let consensus_constants = ConsensusConstants::from(self.network);

let fee_exec_results =
Self::process_instructions(&consensus_constants, &template_provider, &runtime, fee_instructions);

let fee_exec_result = match fee_exec_results {
Ok(execution_results) => {
Expand Down Expand Up @@ -177,7 +181,8 @@ impl<TTemplateProvider: TemplateProvider<Template = LoadedTemplate> + 'static> T
},
};

let instruction_result = Self::process_instructions(&*template_provider, &runtime, instructions);
let instruction_result =
Self::process_instructions(&consensus_constants, &*template_provider, &runtime, instructions);

match instruction_result {
Ok(execution_results) => {
Expand Down Expand Up @@ -217,13 +222,14 @@ impl<TTemplateProvider: TemplateProvider<Template = LoadedTemplate> + 'static> T
}

fn process_instructions(
consensus_constants: &ConsensusConstants,
template_provider: &TTemplateProvider,
runtime: &Runtime,
instructions: Vec<Instruction>,
) -> Result<Vec<InstructionResult>, TransactionError> {
let result: Result<_, _> = instructions
.into_iter()
.map(|instruction| Self::process_instruction(template_provider, runtime, instruction))
.map(|instruction| Self::process_instruction(consensus_constants, template_provider, runtime, instruction))
.collect();

// check that the finalized state is valid
Expand All @@ -235,6 +241,7 @@ impl<TTemplateProvider: TemplateProvider<Template = LoadedTemplate> + 'static> T
}

fn process_instruction(
consensus_constants: &ConsensusConstants,
template_provider: &TTemplateProvider,
runtime: &Runtime,
instruction: Instruction,
Expand Down Expand Up @@ -303,6 +310,7 @@ impl<TTemplateProvider: TemplateProvider<Template = LoadedTemplate> + 'static> T
)?;
Ok(InstructionResult::empty())
},
Instruction::PublishTemplate { binary } => Self::publish_template(consensus_constants, runtime, binary),
}
}

Expand All @@ -320,6 +328,28 @@ impl<TTemplateProvider: TemplateProvider<Template = LoadedTemplate> + 'static> T
Ok(())
}

/// Load, validate template binary and adds to the cache of TemplateProvider.
pub fn publish_template(
consensus_constants: &ConsensusConstants,
runtime: &Runtime,
binary: Vec<u8>,
) -> Result<InstructionResult, TransactionError> {
if binary.len() > consensus_constants.template_binary_max_size_bytes {
return Err(TransactionError::WasmBinaryTooBig(
binary.len(),
consensus_constants.template_binary_max_size_bytes,
));
}
let template = WasmModule::load_template_from_code(binary.as_slice())?;
// TODO: delete debug log when implemented
runtime.interface().emit_log(
LogLevel::Debug,
format!("Template name: \"{}\"", template.template_name()),
)?;
// TODO: implement
Ok(InstructionResult::empty())
}

pub fn create_account(
template_provider: &TTemplateProvider,
runtime: &Runtime,
Expand Down
6 changes: 6 additions & 0 deletions dan_layer/engine_types/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ pub enum Instruction {
resource_address: ResourceAddress,
min_amount: Amount,
},
PublishTemplate {
binary: Vec<u8>,
},
}

impl Display for Instruction {
Expand Down Expand Up @@ -149,6 +152,9 @@ impl Display for Instruction {
key, resource_address, min_amount
)
},
Instruction::PublishTemplate { .. } => {
write!(f, "PublishTemplate")
},
}
}
}
4 changes: 4 additions & 0 deletions dan_layer/p2p/proto/transaction.proto
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ message Instruction {
DROP_ALL_PROOFS_IN_WORKSPACE = 6;
CREATE_ACCOUNT = 7;
ASSERT_BUCKET_CONTAINS = 8;
PUBLISH_TEMPLATE = 9;
}
InstructionType instruction_type = 1;

Expand Down Expand Up @@ -79,6 +80,9 @@ message Instruction {
// AssertBucketContains
bytes resource_address = 21;
int64 min_amount = 22;

// PublishTemplate
bytes template_binary = 23;
}


Expand Down
13 changes: 13 additions & 0 deletions dan_layer/p2p/src/conversions/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,13 @@ impl TryFrom<proto::transaction::Transaction> for Transaction {
.into_iter()
.map(TryInto::try_into)
.collect::<Result<_, _>>()?;

let filled_inputs = request
.filled_inputs
.into_iter()
.map(TryInto::try_into)
.collect::<Result<_, _>>()?;

let transaction = Transaction::new(
request
.transaction
Expand Down Expand Up @@ -130,16 +132,19 @@ impl TryFrom<proto::transaction::UnsignedTransaction> for UnsignedTransaction {
.into_iter()
.map(TryInto::try_into)
.collect::<Result<Vec<_>, _>>()?;

let fee_instructions = request
.fee_instructions
.into_iter()
.map(TryInto::try_into)
.collect::<Result<Vec<_>, _>>()?;

let inputs = request
.inputs
.into_iter()
.map(TryInto::try_into)
.collect::<Result<_, _>>()?;

let min_epoch = request.min_epoch.map(|epoch| Epoch(epoch.epoch));
let max_epoch = request.max_epoch.map(|epoch| Epoch(epoch.epoch));
Ok(Self {
Expand Down Expand Up @@ -187,6 +192,7 @@ impl TryFrom<proto::transaction::Instruction> for Instruction {
.collect::<Result<_, _>>()?;
let instruction_type =
InstructionType::try_from(request.instruction_type).map_err(|e| anyhow!("invalid instruction_type {e}"))?;

let instruction = match instruction_type {
InstructionType::CreateAccount => Instruction::CreateAccount {
public_key_address: PublicKey::from_canonical_bytes(&request.create_account_public_key)
Expand Down Expand Up @@ -253,6 +259,9 @@ impl TryFrom<proto::transaction::Instruction> for Instruction {
min_amount: Amount::new(request.min_amount),
}
},
InstructionType::PublishTemplate => Instruction::PublishTemplate {
binary: request.template_binary,
},
};

Ok(instruction)
Expand Down Expand Up @@ -334,6 +343,10 @@ impl From<Instruction> for proto::transaction::Instruction {
result.resource_address = resource_address.as_bytes().to_vec();
result.min_amount = min_amount.0
},
Instruction::PublishTemplate { binary } => {
result.instruction_type = InstructionType::PublishTemplate as i32;
result.template_binary = binary;
},
}
result
}
Expand Down
7 changes: 7 additions & 0 deletions dan_layer/transaction/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,13 @@ impl TransactionBuilder {
})
}

/// Publishing a WASM template.
pub fn publish_template<T: AsRef<[u8]>>(self, binary: T) -> Self {
self.add_instruction(Instruction::PublishTemplate {
binary: binary.as_ref().to_vec(),
})
}

pub fn claim_burn(self, claim: ConfidentialClaim) -> Self {
self.add_instruction(Instruction::ClaimBurn { claim: Box::new(claim) })
}
Expand Down
Loading