diff --git a/contracts/Cargo.toml b/contracts/Cargo.toml index 9d92df24..ae920537 100644 --- a/contracts/Cargo.toml +++ b/contracts/Cargo.toml @@ -3,11 +3,11 @@ members = [ "box", "c-example", "callcenter", - "constructor", + "initializer", "counter", "debugger", "double_counter", - "empty_constructor", + "empty_initializer", "eventer", "everest", "fallible_counter", diff --git a/contracts/README.md b/contracts/README.md index 736a111f..55a6b367 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -6,7 +6,8 @@ This workspace contains individual contract examples. These examples demonstrate - [Box](box/): A contract for managing a boxed i16 value with set and get operations. - [Callcenter](callcenter/): Inter-contract call example. -- [Constructor](constructor/): Contract with a constructor. +- [Initializer](initializer/): Contract that makes use of the init method. +- [Empty Initializer](empty_initializer/): Contract that makes use of an init method without arguments. - [Counter](counter/): Counter contract that both reads and writes state. - [Crossover](crossover/): Bi-directional inter-contract call example. - [Debugger](debugger/): Example of in-contract debug calls. diff --git a/contracts/empty_constructor/Cargo.toml b/contracts/empty_initializer/Cargo.toml similarity index 91% rename from contracts/empty_constructor/Cargo.toml rename to contracts/empty_initializer/Cargo.toml index 209755a4..814f96bf 100644 --- a/contracts/empty_constructor/Cargo.toml +++ b/contracts/empty_initializer/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "empty_constructor" +name = "empty_initializer" version = "0.1.0" authors = [ "Eduardo Leegwater Simões ", diff --git a/contracts/empty_constructor/src/lib.rs b/contracts/empty_initializer/src/lib.rs similarity index 55% rename from contracts/empty_constructor/src/lib.rs rename to contracts/empty_initializer/src/lib.rs index 4b89053a..224f8e3f 100644 --- a/contracts/empty_constructor/src/lib.rs +++ b/contracts/empty_initializer/src/lib.rs @@ -4,28 +4,31 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -//! Contract that provides and example use of the constructor. +//! Contract that provides an example use of the init method. +//! The init method provides a way to initialize the state of the contract and execute other logic only once at the time of deployment. +//! +//! The init method can be partially compared to the functionality of a constructor in other languages. #![no_std] use piecrust_uplink as uplink; -/// Struct that describes the state of the Constructor contract -pub struct EmptyConstructor { +/// Struct that describes the state of the Init contract +pub struct EmptyInitializer { value: u8, } -impl EmptyConstructor { +impl EmptyInitializer { pub fn init(&mut self) { self.value = 0x10; } } -/// State of the EmptyConstructor contract -static mut STATE: EmptyConstructor = EmptyConstructor { value: 0x00 }; +/// State of the EmptyInitializer contract +static mut STATE: EmptyInitializer = EmptyInitializer { value: 0x00 }; -impl EmptyConstructor { - /// Read the value of the constructor contract state +impl EmptyInitializer { + /// Read the value of the contract state pub fn read_value(&self) -> u8 { self.value } @@ -37,19 +40,19 @@ impl EmptyConstructor { } } -/// Expose `EmptyConstructor::read_value()` to the host +/// Expose `EmptyInitializer::read_value()` to the host #[no_mangle] unsafe fn read_value(arg_len: u32) -> u32 { uplink::wrap_call(arg_len, |_: ()| STATE.read_value()) } -/// Expose `EmptyConstructor::increment()` to the host +/// Expose `EmptyInitializer::increment()` to the host #[no_mangle] unsafe fn increment(arg_len: u32) -> u32 { uplink::wrap_call(arg_len, |_: ()| STATE.increment()) } -/// Expose `EmptyConstructor::init()` to the host +/// Expose `EmptyInitializer::init()` to the host #[no_mangle] unsafe fn init(arg_len: u32) -> u32 { uplink::wrap_call(arg_len, |()| STATE.init()) diff --git a/contracts/constructor/Cargo.toml b/contracts/initializer/Cargo.toml similarity index 92% rename from contracts/constructor/Cargo.toml rename to contracts/initializer/Cargo.toml index 29fbea24..66362c1b 100644 --- a/contracts/constructor/Cargo.toml +++ b/contracts/initializer/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "constructor" +name = "initializer" version = "0.1.0" authors = [ "Milosz Muszynski ", diff --git a/contracts/constructor/src/lib.rs b/contracts/initializer/src/lib.rs similarity index 56% rename from contracts/constructor/src/lib.rs rename to contracts/initializer/src/lib.rs index a41a1816..77308499 100644 --- a/contracts/constructor/src/lib.rs +++ b/contracts/initializer/src/lib.rs @@ -4,28 +4,31 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -//! Contract that provides and example use of the constructor. +//! Contract that provides an example use of the init method. +//! The init method provides a way to initialize the state of the contract and execute other logic only once at the time of deployment. +//! +//! The init method can be partially compared to the functionality of a constructor in other languages. #![no_std] use piecrust_uplink as uplink; -/// Struct that describes the state of the Constructor contract -pub struct Constructor { +/// Struct that describes the state of the Initializer contract +pub struct Initializer { value: u8, } -impl Constructor { +impl Initializer { pub fn init(&mut self, value: u8) { self.value = value; } } -/// State of the Constructor contract -static mut STATE: Constructor = Constructor { value: 0x50 }; +/// State of the Initializer contract +static mut STATE: Initializer = Initializer { value: 0x50 }; -impl Constructor { - /// Read the value of the constructor contract state +impl Initializer { + /// Read the value of the contract state pub fn read_value(&self) -> u8 { self.value } @@ -36,19 +39,19 @@ impl Constructor { } } -/// Expose `Constructor::read_value()` to the host +/// Expose `Initializer::read_value()` to the host #[no_mangle] unsafe fn read_value(arg_len: u32) -> u32 { uplink::wrap_call(arg_len, |_: ()| STATE.read_value()) } -/// Expose `Constructor::increment()` to the host +/// Expose `Initializer::increment()` to the host #[no_mangle] unsafe fn increment(arg_len: u32) -> u32 { uplink::wrap_call(arg_len, |_: ()| STATE.increment()) } -/// Expose `Constructor::init()` to the host +/// Expose `Initializer::init()` to the host #[no_mangle] unsafe fn init(arg_len: u32) -> u32 { uplink::wrap_call(arg_len, |arg: u8| STATE.init(arg)) diff --git a/piecrust/CHANGELOG.md b/piecrust/CHANGELOG.md index 081b0c79..c0e9e080 100644 --- a/piecrust/CHANGELOG.md +++ b/piecrust/CHANGELOG.md @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Change `callee` import to return an integer +- Change `constructor_arg` to `init_arg` +- Change all references to `constructor` either to `init` or `initializer` ## [0.22.0] - 2024-07-03 diff --git a/piecrust/src/contract.rs b/piecrust/src/contract.rs index ab7d4824..2d7c11fe 100644 --- a/piecrust/src/contract.rs +++ b/piecrust/src/contract.rs @@ -15,11 +15,11 @@ use crate::error::Error; pub struct ContractData<'a, A> { pub(crate) contract_id: Option, - pub(crate) constructor_arg: Option<&'a A>, + pub(crate) init_arg: Option<&'a A>, pub(crate) owner: Option>, } -// `()` is done on purpose, since by default it should be that the constructor +// `()` is done on purpose, since by default it should be that the initializer // takes no argument. impl<'a> ContractData<'a, ()> { /// Build a deploy data structure. @@ -29,7 +29,7 @@ impl<'a> ContractData<'a, ()> { pub fn builder() -> ContractDataBuilder<'a, ()> { ContractDataBuilder { contract_id: None, - constructor_arg: None, + init_arg: None, owner: None, } } @@ -44,7 +44,7 @@ impl<'a, A> From> for ContractData<'a, A> { pub struct ContractDataBuilder<'a, A> { contract_id: Option, owner: Option>, - constructor_arg: Option<&'a A>, + init_arg: Option<&'a A>, } impl<'a, A> ContractDataBuilder<'a, A> { @@ -54,15 +54,23 @@ impl<'a, A> ContractDataBuilder<'a, A> { self } - /// Set the constructor argument for deployment. - pub fn constructor_arg(self, arg: &B) -> ContractDataBuilder { + /// Set the initializer argument for deployment. + /// This is the argument that will be passed to the contract's `init` + /// function. + pub fn init_arg(self, arg: &B) -> ContractDataBuilder { ContractDataBuilder { contract_id: self.contract_id, owner: self.owner, - constructor_arg: Some(arg), + init_arg: Some(arg), } } + /// Deprecated: Use `init_arg` instead. + #[deprecated(note = "Use `init_arg` instead of `constructor_arg`")] + pub fn constructor_arg(self, arg: &B) -> ContractDataBuilder { + self.init_arg(arg) + } + /// Set the owner of the contract. pub fn owner(mut self, owner: impl Into>) -> Self { self.owner = Some(owner.into()); @@ -72,7 +80,7 @@ impl<'a, A> ContractDataBuilder<'a, A> { pub fn build(self) -> ContractData<'a, A> { ContractData { contract_id: self.contract_id, - constructor_arg: self.constructor_arg, + init_arg: self.init_arg, owner: self.owner, } } diff --git a/piecrust/src/session.rs b/piecrust/src/session.rs index d05eebb6..bd40ce82 100644 --- a/piecrust/src/session.rs +++ b/piecrust/src/session.rs @@ -226,8 +226,8 @@ impl Session { { let deploy_data = deploy_data.into(); - let mut constructor_arg = None; - if let Some(arg) = deploy_data.constructor_arg { + let mut init_arg = None; + if let Some(arg) = deploy_data.init_arg { let mut sbuf = [0u8; SCRATCH_BUF_BYTES]; let scratch = BufferScratch::new(&mut sbuf); let ser = BufferSerializer::new(&mut self.inner.buffer[..]); @@ -236,13 +236,13 @@ impl Session { ser.serialize_value(arg)?; let pos = ser.pos(); - constructor_arg = Some(self.inner.buffer[0..pos].to_vec()); + init_arg = Some(self.inner.buffer[0..pos].to_vec()); } self.deploy_raw( deploy_data.contract_id, bytecode, - constructor_arg, + init_arg, deploy_data .owner .expect("Owner must be specified when deploying a contract"), @@ -272,7 +272,7 @@ impl Session { &mut self, contract_id: Option, bytecode: &[u8], - constructor_arg: Option>, + init_arg: Option>, owner: Vec, gas_limit: u64, ) -> Result { @@ -280,13 +280,7 @@ impl Session { let hash = blake3::hash(bytecode); ContractId::from_bytes(hash.into()) }); - self.do_deploy( - contract_id, - bytecode, - constructor_arg, - owner, - gas_limit, - )?; + self.do_deploy(contract_id, bytecode, init_arg, owner, gas_limit)?; Ok(contract_id) } @@ -328,10 +322,10 @@ impl Session { self.instance(&contract_id).expect("instance should exist"); if instance.is_function_exported(INIT_METHOD) { - // If no argument was provided, we call the constructor anyway, + // If no argument was provided, we call the init method anyway, // but with an empty argument. The alternative is to panic, but // that assumes that the caller of `deploy` knows that the - // contract has a constructor in the first place, which might + // contract has an init method in the first place, which might // not be the case, such as when ingesting untrusted bytecode. let arg = arg.unwrap_or_default(); self.call_inner(contract_id, INIT_METHOD, arg, gas_limit)?; diff --git a/piecrust/tests/constructor.rs b/piecrust/tests/initializer.rs similarity index 89% rename from piecrust/tests/constructor.rs rename to piecrust/tests/initializer.rs index 7165e860..bb235d04 100644 --- a/piecrust/tests/constructor.rs +++ b/piecrust/tests/initializer.rs @@ -11,16 +11,14 @@ const OWNER: [u8; 32] = [0u8; 32]; const LIMIT: u64 = 1_000_000; #[test] -fn constructor() -> Result<(), Error> { +fn init() -> Result<(), Error> { let vm = VM::ephemeral()?; let mut session = vm.session(SessionData::builder())?; let id = session.deploy( - contract_bytecode!("constructor"), - ContractData::builder() - .owner(OWNER) - .constructor_arg(&0xabu8), + contract_bytecode!("initializer"), + ContractData::builder().owner(OWNER).init_arg(&0xabu8), LIMIT, )?; @@ -75,13 +73,13 @@ fn constructor() -> Result<(), Error> { } #[test] -fn empty_constructor_argument() -> Result<(), Error> { +fn empty_init_argument() -> Result<(), Error> { let vm = VM::ephemeral()?; let mut session = vm.session(SessionData::builder())?; let id = session.deploy( - contract_bytecode!("empty_constructor"), + contract_bytecode!("empty_initializer"), ContractData::builder().owner(OWNER), LIMIT, )?;