Skip to content

Commit 7002510

Browse files
author
Eduardo Leegwater Simões
authored
Merge pull request #339 from dusk-network/optional-owner-336
piecrust: optional owner in `Session::migrate`
2 parents 648f68d + e6aaba7 commit 7002510

27 files changed

+255
-118
lines changed

piecrust/CHANGELOG.md

+34-20
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Add `ContractDataBuilder::owner` to allow for setting the owner of a contract
13+
on deploy time [#336]
14+
1015
### Changed
1116

17+
- Change `migrate` to take the owner of the contract being replaced if it is
18+
not set by the caller [#336]
19+
- Make `owner` field optional in `ContractData` and `ContractDataBuilder` [#336]
20+
- Change `ContractData` and `ContractDataBuilder` to take a `Vec<u8>` as owner
21+
instead of `[u8; N]` [#336]
1222
- Use empty constructor arguments by default [#316]
1323
- Upgrade `dusk-wasmtime` to version `18`
1424

@@ -32,7 +42,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3242
### Changed
3343

3444
- Change `owner` import to accept the contract ID as argument and return
35-
non-zero upon success
45+
non-zero upon success
3646

3747
## [0.14.1] - 2024-01-11
3848

@@ -72,20 +82,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7282

7383
## Added
7484

75-
- Add `Session::memory_pages` allowing for inclusion proofs of pages [#273]
85+
- Add `Session::memory_pages` allowing for inclusion proofs of pages [#273]
7686

7787
## Changed
7888

79-
- Change state tree to distinguish between 32 and 64 bit smart contracts [#273]
89+
- Change state tree to distinguish between 32 and 64 bit smart contracts [#273]
8090

8191
## [0.12.0] - 2023-11-01
8292

8393
## Added
8494

8595
- Support `memory64` smart contracts [#281]
8696
- Add some `Error` variants:
87-
* `InvalidFunction`
88-
* `InvalidMemory`
97+
* `InvalidFunction`
98+
* `InvalidMemory`
8999
- Add `once_cell` dependency
90100

91101
## Changed
@@ -104,19 +114,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
104114
- Remove 4 page - 256KiB - minimum memory requirement for contracts
105115
- Remove `Clone` derivation for `Error`
106116
- Remove some `Error` variants, along with `From` implementations:
107-
* `CompileError`
108-
* `DeserializeError`
109-
* `ExportError`
110-
* `InstantiationError`
111-
* `InvalidFunctionSignature`
112-
* `MemorySetupError`
113-
* `ParsingError`
114-
* `SerializeError`
115-
* `Trap`
117+
* `CompileError`
118+
* `DeserializeError`
119+
* `ExportError`
120+
* `InstantiationError`
121+
* `InvalidFunctionSignature`
122+
* `MemorySetupError`
123+
* `ParsingError`
124+
* `SerializeError`
125+
* `Trap`
116126

117127
## Fixed
118128

119-
- Fix loading of compiled contracts from state transported from different
129+
- Fix loading of compiled contracts from state transported from different
120130
platforms [#287]
121131

122132
## [0.11.0] - 2023-10-11
@@ -190,8 +200,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
190200

191201
### Changed
192202

193-
- Change commit write behavior to write dirty pages instead of diffs [#253]
194-
- Change memory backend to use `crumbles` instead of `libc` directly [#253]
203+
- Change commit write behavior to write dirty pages instead of diffs [#253]
204+
- Change memory backend to use `crumbles` instead of `libc` directly [#253]
195205

196206
### Removed
197207

@@ -209,13 +219,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
209219

210220
### Changed
211221

212-
- Change imports
222+
- Change imports
213223
- Change diffing algorithm to not delegate growth to `bsdiff`
214224
- Change memory growth algorithm to not require copying to temp file
215225

216226
### Fixed
217227

218-
- Fix behavior of imports on out of bounds pointers [#249]
228+
- Fix behavior of imports on out of bounds pointers [#249]
219229
- Fix SIGBUS caused by improper memory growth
220230

221231
## [0.7.0] - 2023-07-19
@@ -310,7 +320,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
310320

311321
### Changed
312322

313-
- Change `owner` parameter type in `ModuleData::builder` to be `[u8; N]` [#201]
323+
- Change `owner` parameter type in `ModuleData::builder` to be `[u8; N]` [#201]
314324

315325
### Fixed
316326

@@ -362,9 +372,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
362372
- First `piecrust` release
363373

364374
<!-- PULLS -->
375+
365376
[#234]: https://github.com/dusk-network/piecrust/pull/234
366377

367378
<!-- ISSUES -->
379+
380+
[#336]: https://github.com/dusk-network/piecrust/issues/336
368381
[#325]: https://github.com/dusk-network/piecrust/issues/325
369382
[#324]: https://github.com/dusk-network/piecrust/issues/324
370383
[#316]: https://github.com/dusk-network/piecrust/issues/316
@@ -400,6 +413,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
400413
[#93]: https://github.com/dusk-network/piecrust/issues/93
401414

402415
<!-- VERSIONS -->
416+
403417
[Unreleased]: https://github.com/dusk-network/piecrust/compare/piecrust-0.16.0...HEAD
404418
[0.16.0]: https://github.com/dusk-network/piecrust/compare/piecrust-0.15.0...piecrust-0.16.0
405419
[0.15.0]: https://github.com/dusk-network/piecrust/compare/piecrust-0.14.1...piecrust-0.15.0

piecrust/src/contract.rs

+18-14
Original file line numberDiff line numberDiff line change
@@ -13,59 +13,63 @@ use rkyv::{Archive, Deserialize, Serialize};
1313

1414
use crate::error::Error;
1515

16-
pub struct ContractData<'a, A, const N: usize> {
16+
pub struct ContractData<'a, A> {
1717
pub(crate) contract_id: Option<ContractId>,
1818
pub(crate) constructor_arg: Option<&'a A>,
19-
pub(crate) owner: [u8; N],
19+
pub(crate) owner: Option<Vec<u8>>,
2020
}
2121

2222
// `()` is done on purpose, since by default it should be that the constructor
2323
// takes no argument.
24-
impl<'a, const N: usize> ContractData<'a, (), N> {
24+
impl<'a> ContractData<'a, ()> {
2525
/// Build a deploy data structure.
2626
///
2727
/// This function returns a builder that can be used to set optional fields
2828
/// in contract deployment.
29-
pub fn builder(owner: [u8; N]) -> ContractDataBuilder<'a, (), N> {
29+
pub fn builder() -> ContractDataBuilder<'a, ()> {
3030
ContractDataBuilder {
3131
contract_id: None,
3232
constructor_arg: None,
33-
owner,
33+
owner: None,
3434
}
3535
}
3636
}
3737

38-
impl<'a, A, const N: usize> From<ContractDataBuilder<'a, A, N>>
39-
for ContractData<'a, A, N>
40-
{
41-
fn from(builder: ContractDataBuilder<'a, A, N>) -> Self {
38+
impl<'a, A> From<ContractDataBuilder<'a, A>> for ContractData<'a, A> {
39+
fn from(builder: ContractDataBuilder<'a, A>) -> Self {
4240
builder.build()
4341
}
4442
}
4543

46-
pub struct ContractDataBuilder<'a, A, const N: usize> {
44+
pub struct ContractDataBuilder<'a, A> {
4745
contract_id: Option<ContractId>,
48-
owner: [u8; N],
46+
owner: Option<Vec<u8>>,
4947
constructor_arg: Option<&'a A>,
5048
}
5149

52-
impl<'a, A, const N: usize> ContractDataBuilder<'a, A, N> {
50+
impl<'a, A> ContractDataBuilder<'a, A> {
5351
/// Set the deployment contract ID.
5452
pub fn contract_id(mut self, id: ContractId) -> Self {
5553
self.contract_id = Some(id);
5654
self
5755
}
5856

5957
/// Set the constructor argument for deployment.
60-
pub fn constructor_arg<B>(self, arg: &B) -> ContractDataBuilder<B, N> {
58+
pub fn constructor_arg<B>(self, arg: &B) -> ContractDataBuilder<B> {
6159
ContractDataBuilder {
6260
contract_id: self.contract_id,
6361
owner: self.owner,
6462
constructor_arg: Some(arg),
6563
}
6664
}
6765

68-
pub fn build(self) -> ContractData<'a, A, N> {
66+
/// Set the owner of the contract.
67+
pub fn owner(mut self, owner: impl Into<Vec<u8>>) -> Self {
68+
self.owner = Some(owner.into());
69+
self
70+
}
71+
72+
pub fn build(self) -> ContractData<'a, A> {
6973
ContractData {
7074
contract_id: self.contract_id,
7175
constructor_arg: self.constructor_arg,

piecrust/src/lib.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,13 @@
8989
//! const LIMIT: u64 = 1_000_000;
9090
//!
9191
//! let mut session = vm.session(SessionData::builder()).unwrap();
92-
//! let counter_id = session.deploy(contract_bytecode!("counter"), ContractData::builder(OWNER), LIMIT).unwrap();
92+
//! let counter_id = session
93+
//! .deploy(
94+
//! contract_bytecode!("counter"),
95+
//! ContractData::builder().owner(OWNER),
96+
//! LIMIT,
97+
//! )
98+
//! .unwrap();
9399
//!
94100
//! assert_eq!(session.call::<_, i64>(counter_id, "read_value", &(), LIMIT).unwrap().data, 0xfc);
95101
//! session.call::<_, ()>(counter_id, "increment", &(), LIMIT).unwrap();

piecrust/src/session.rs

+37-6
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const MAX_META_SIZE: usize = ARGBUF_LEN;
3434
pub const INIT_METHOD: &str = "init";
3535

3636
unsafe impl Send for Session {}
37+
3738
unsafe impl Sync for Session {}
3839

3940
/// A running mutation to a state.
@@ -208,15 +209,18 @@ impl Session {
208209
///
209210
/// [`ContractId`]: ContractId
210211
/// [`PersistenceError`]: PersistenceError
211-
pub fn deploy<'a, A, D, const N: usize>(
212+
///
213+
/// # Panics
214+
/// If `deploy_data` does not specify an owner, this will panic.
215+
pub fn deploy<'a, A, D>(
212216
&mut self,
213217
bytecode: &[u8],
214218
deploy_data: D,
215219
gas_limit: u64,
216220
) -> Result<ContractId, Error>
217221
where
218222
A: 'a + for<'b> Serialize<StandardBufSerializer<'b>>,
219-
D: Into<ContractData<'a, A, N>>,
223+
D: Into<ContractData<'a, A>>,
220224
{
221225
let mut deploy_data = deploy_data.into();
222226

@@ -247,7 +251,9 @@ impl Session {
247251
contract_id,
248252
bytecode,
249253
constructor_arg,
250-
deploy_data.owner.to_vec(),
254+
deploy_data
255+
.owner
256+
.expect("Owner must be specified when deploying a contract"),
251257
gas_limit,
252258
)?;
253259

@@ -400,11 +406,19 @@ impl Session {
400406
/// given `contract` ID, and the old contract will be removed from the
401407
/// state.
402408
///
409+
/// If the `owner` of a contract is not set, it will be set to the owner of
410+
/// the contract being replaced. If it is set, then it will be used as the
411+
/// new owner.
412+
///
403413
/// # Errors
404414
/// The migration may error during execution for a myriad of reasons. The
405415
/// caller is encouraged to drop the `Session` should an error occur as it
406416
/// will more than likely be left in an inconsistent state.
407-
pub fn migrate<'a, A, D, F, const N: usize>(
417+
///
418+
/// # Panics
419+
/// If the owner of the new contract is not set in `deploy_data`, and the
420+
/// contract being replaced does not exist, this will panic.
421+
pub fn migrate<'a, A, D, F>(
408422
mut self,
409423
contract: ContractId,
410424
bytecode: &[u8],
@@ -414,11 +428,28 @@ impl Session {
414428
) -> Result<Self, Error>
415429
where
416430
A: 'a + for<'b> Serialize<StandardBufSerializer<'b>>,
417-
D: Into<ContractData<'a, A, N>>,
431+
D: Into<ContractData<'a, A>>,
418432
F: FnOnce(ContractId, &mut Session) -> Result<(), Error>,
419433
{
434+
let mut new_contract_data = deploy_data.into();
435+
436+
// If the contract being replaced exists, and the caller did not specify
437+
// an owner, set the owner to the owner of the contract being replaced.
438+
if let Some(old_contract_data) = self
439+
.inner
440+
.contract_session
441+
.contract(contract)
442+
.map_err(|err| PersistenceError(Arc::new(err)))?
443+
{
444+
if new_contract_data.owner.is_none() {
445+
new_contract_data.owner =
446+
Some(old_contract_data.metadata.data().owner.clone());
447+
}
448+
}
449+
420450
let new_contract =
421-
self.deploy(bytecode, deploy_data, deploy_gas_limit)?;
451+
self.deploy(bytecode, new_contract_data, deploy_gas_limit)?;
452+
422453
closure(new_contract, &mut self)?;
423454

424455
self.inner

piecrust/tests/box.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub fn box_set_get() -> Result<(), Error> {
1818

1919
let id = session.deploy(
2020
contract_bytecode!("box"),
21-
ContractData::builder(OWNER),
21+
ContractData::builder().owner(OWNER),
2222
LIMIT,
2323
)?;
2424

@@ -43,7 +43,7 @@ pub fn box_set_get_raw() -> Result<(), Error> {
4343

4444
let id = session.deploy(
4545
contract_bytecode!("box"),
46-
ContractData::builder(OWNER),
46+
ContractData::builder().owner(OWNER),
4747
LIMIT,
4848
)?;
4949

0 commit comments

Comments
 (0)