Skip to content

Commit 117a58c

Browse files
Merge pull request #904 from multiversx/development
Development into main
2 parents 31f6ee3 + 895e2f6 commit 117a58c

File tree

6 files changed

+50
-147
lines changed

6 files changed

+50
-147
lines changed

docs/developers/reproducible-contract-builds.md

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ You will also learn how to reproduce a contract build, given its source code and
1111
> **Reproducible builds**, also known as **deterministic compilation**, is a process of compiling software which ensures the resulting binary code can be reproduced. Source code compiled using deterministic compilation will always output the same binary [[Wikipedia]](https://en.wikipedia.org/wiki/Reproducible_builds).
1212
1313
:::important
14-
As of September 2022, the Rust toolchain does not support reproducible builds out-of-the-box, thus we recommend smart contract developers to follow this tutorial in order to achieve deterministic compilation.
14+
As of May 2024, the Rust toolchain does not support reproducible builds out-of-the-box, thus we recommend smart contract developers to follow this tutorial in order to achieve deterministic compilation.
1515
:::
1616

1717
[comment]: # (mx-context-auto)
@@ -22,12 +22,12 @@ Before diving into contract build reproducibility, let's grasp the concept of `c
2222

2323
When a smart contract is deployed, the network stores the bytecode, and also computes its `blake2b` checksum (using a digest length of 256 bits). This is called the `codehash`.
2424

25-
Assume that we are interested into the following contract, deployed on _devnet_: [erd1qqqqqqqqqqqqqpgqahertgz4020wegswus8m7f2ak8a6d0gv396qw3t2zy](https://devnet-explorer.multiversx.com/accounts/erd1qqqqqqqqqqqqqpgqahertgz4020wegswus8m7f2ak8a6d0gv396qw3t2zy). It's source code is published on [GitHub](https://github.com/multiversx/mx-reproducible-contract-build-example-sc).
25+
Assume that we are interested into the following contract (a simple on-chain **adder**), deployed on _devnet_: [erd1qqqqqqqqqqqqqpgqws44xjx2t056nn79fn29q0rjwfrd3m43396ql35kxy](https://devnet-explorer.multiversx.com/accounts/erd1qqqqqqqqqqqqqpgqws44xjx2t056nn79fn29q0rjwfrd3m43396ql35kxy). It's source code is published on [GitHub](https://github.com/multiversx/mx-contracts-rs).
2626

2727
We can fetch the _codehash_ of the contract from the API:
2828

2929
```bash
30-
curl -s https://devnet-api.multiversx.com/accounts/erd1qqqqqqqqqqqqqpgqahertgz4020wegswus8m7f2ak8a6d0gv396qw3t2zy \
30+
curl -s https://devnet-api.multiversx.com/accounts/erd1qqqqqqqqqqqqqpgqws44xjx2t056nn79fn29q0rjwfrd3m43396ql35kxy \
3131
| jq -r -j .codeHash \
3232
| base64 -d \
3333
| xxd -p \
@@ -37,7 +37,7 @@ curl -s https://devnet-api.multiversx.com/accounts/erd1qqqqqqqqqqqqqpgqahertgz40
3737
The output is:
3838

3939
```
40-
58c6e78f40bd6ccc30d8a01f952b34a13ebfdad796a2526678be17c5d7820174
40+
384b680df7a95ebceca02ffb3e760a2fc288dea1b802685ef15df22ae88ba15b
4141
```
4242

4343
If the `WASM` file is directly available, we can also use the utility `b2sum` to locally compute the _codehash_:
@@ -49,7 +49,7 @@ b2sum -l 256 adder.wasm
4949
The output would be the same:
5050

5151
```
52-
58c6e78f40bd6ccc30d8a01f952b34a13ebfdad796a2526678be17c5d7820174
52+
384b680df7a95ebceca02ffb3e760a2fc288dea1b802685ef15df22ae88ba15b
5353
```
5454

5555
All in all, in order to verify the bytecode equality of two given builds of a contract we can simply compare the _codehash_ property.
@@ -58,37 +58,30 @@ All in all, in order to verify the bytecode equality of two given builds of a co
5858

5959
## Supporting reproducible builds
6060

61-
As of October 2022, the recommended approach to support reproducible builds for your smart contract is to use a build script relying on a specially-designed, [publicly-available, tagged Docker image](https://hub.docker.com/r/multiversx/sdk-rust-contract-builder/tags), that includes tagged, explicit versions of the build tools (_Rust_, _wasm-opt_ etc.).
61+
As of May 2024, the recommended approach to support reproducible builds for your smart contract is to use a build script relying on a specially-designed, [publicly-available, tagged Docker image](https://hub.docker.com/r/multiversx/sdk-rust-contract-builder/tags), that includes tagged, explicit versions of the build tools (_Rust_, _wasm-opt_ etc.).
6262

6363
This approach is recommended in order to counteract eventual pieces of non-determinism related to `cargo`'s (essential component of the Rust toolchain) sensibility on the environment.
6464

6565
:::important
66-
If the code source of your smart contract is hosted on GitHub, then it's a good practice to define a GitHub Workflow similar to [this one](https://github.com/multiversx/mx-reproducible-contract-build-example-sc/blob/main/.github/workflows/on_release_build_contracts.yml), which performs the deployment (production-ready) build within the _release_ procedure.
66+
If the code source of your smart contract is hosted on GitHub, then it's a good practice to define a GitHub Workflow similar to [release.yml](https://github.com/multiversx/mx-contracts-rs/blob/main/.github/workflows/release.yml), which performs the deployment (production-ready) build within the _release_ procedure. Additionally, define a dry-run reproducible build on all your branches. See this workflow as an example: [on_pull_request_build_contracts.yml](https://github.com/multiversx/mx-contracts-rs/blob/main/.github/workflows/on_pull_request_build_contracts.yml).
6767
:::
6868

6969
[comment]: # (mx-context-auto)
7070

7171
### Choose an image tag
7272

73-
The first step for supporting reproducible builds is to decide on a specific Docker image tag to use. Check the **frozen** tags listed at [multiversx/sdk-rust-contract-builder](https://hub.docker.com/r/multiversx/sdk-rust-contract-builder/tags), and inspect their labels - especially the labels `rust` and `wasm-opt-binaryen`:
74-
75-
```
76-
LABEL rust=nightly-2022-08-23
77-
LABEL wasm-opt-binaryen=version_105
78-
```
79-
8073
For a new smart contract that isn't released yet (deployed on the network), it's recommended to pick the tag with the **largest index number**, which tipically includes recent versions of `rust` and other necessary dependencies.
8174

8275
However, for minor releases or patches, it's wise to stick to the previously chosen image tag, for the same (nuanced) reasons you would not embrace an update of your development tools in the middle of fixing a critical bug (in any development context).
8376

84-
The chosen, _frozen_ image tag should accompany the versioned source code (e.g. via _release notes_), in order to inform others on how to reproduce a specific build (of a specific source code version). In this context, _frozen_ image tag refers to a Docker image tag that will never get any updates after its initial publishing.
77+
The chosen, _frozen_ image tag **should accompany the versioned source code (e.g. via _release notes_), in order to inform others on how to reproduce a specific build** (of a specific source code version). In this context, a _frozen_ image tag refers to a Docker image tag that will never get any updates after its initial publishing.
8578

8679
:::tip
8780
It's perfectly normal to switch to a newer image tag on each (major) release of your contract. Just make sure you spread this information - i.e. using _release notes_.
8881
:::
8982

9083
:::caution
91-
Never pick the tag called `latest` for production-ready builds.
84+
Never pick the tag called `latest` or `next` for production-ready builds.
9285
:::
9386

9487
[comment]: # (mx-context-auto)
@@ -101,14 +94,14 @@ In this section, you'll learn how to run a reproducible build, or, to put it dif
10194

10295
### Fetch the source code
10396

104-
Let's clone the [example source code](https://github.com/multiversx/mx-reproducible-contract-build-example-sc) locally, and switch to [a certain version](https://github.com/multiversx/mx-reproducible-contract-build-example-sc/releases/tag/v0.2.0) that we'd like to build:
97+
Let's clone [mx-contracts-rs](https://github.com/multiversx/mx-contracts-rs) locally, and switch to [a certain version](https://github.com/multiversx/mx-contracts-rs/releases/tag/v0.45.4) that we'd like to build:
10598

10699
```bash
107100
mkdir -p ~/contracts && cd ~/contracts
108-
git clone https://github.com/multiversx/mx-reproducible-contract-build-example-sc.git --branch=v0.2.0 --depth=1
101+
git clone https://github.com/multiversx/mx-contracts-rs.git --branch=v0.45.4 --depth=1
109102
```
110103

111-
By inspecting the release notes, we see that [`v0.2.0`](https://github.com/multiversx/mx-reproducible-contract-build-example-sc/releases/tag/v0.2.0) was built using the `image:tag = multiversx/sdk-rust-contract-builder:v4.1.0`.
104+
By inspecting the release notes, we see that [`v0.45.4`](https://github.com/multiversx/mx-contracts-rs/releases/tag/v0.45.4) was built using the `image:tag = multiversx/sdk-rust-contract-builder:v5.4.1`.
112105

113106
[comment]: # (mx-context-auto)
114107

@@ -127,7 +120,7 @@ wget https://raw.githubusercontent.com/multiversx/mx-sdk-build-contract/main/bui
127120
Export the following variables:
128121

129122
```bash
130-
export PROJECT=~/contracts/reproducible-contract-build-example
123+
export PROJECT=~/contracts/mx-contracts-rs
131124
export BUILD_OUTPUT=~/contracts/output-from-docker
132125
# Below, the image tag is just an example:
133126
export IMAGE=multiversx/sdk-rust-contract-builder:v1.2.3
@@ -163,12 +156,12 @@ These being said, let's summarize the steps above into a single bash snippet:
163156
```bash
164157
wget https://raw.githubusercontent.com/multiversx/mx-sdk-build-contract/main/build_with_docker.py
165158

166-
export PROJECT=~/contracts/reproducible-contract-build-example
159+
export PROJECT=~/contracts/mx-contracts-rs
167160
export BUILD_OUTPUT=~/contracts/output-from-docker
168161
# Below, the image tag is just an example:
169162
export IMAGE=multiversx/sdk-rust-contract-builder:v1.2.3
170163

171-
python3 ./build_contract_rust_with_docker.py --image=${IMAGE} \
164+
python3 ./build_with_docker.py --image=${IMAGE} \
172165
--project=${PROJECT} \
173166
--output=${BUILD_OUTPUT}
174167
```
@@ -187,24 +180,24 @@ First, make sure you have the:
187180
Then, use the `reproducible-build` command (below, the image tag is just an example):
188181

189182
```
190-
mxpy contract reproducible-build --docker-image="multiversx/sdk-rust-contract-builder:v4.1.3"
183+
mxpy contract reproducible-build --docker-image="multiversx/sdk-rust-contract-builder:v1.2.3"
191184
```
192185

193186
This will build all the smart contracts inside the current working directory. If you want to build the smart contracts inside another directory, you can specify an input directory:
194187

195188
```
196-
mxpy contract reproducible-build ~/contracts/reproducible-contract-build-example --docker-image="multiversx/sdk-rust-contract-builder:v4.1.3"
189+
mxpy contract reproducible-build ~/contracts/mx-contracts-rs --docker-image="multiversx/sdk-rust-contract-builder:v1.2.3"
197190
```
198191

199-
Upon a successful build, an output folder named `output-docker` will be generated containing:
192+
Upon a successful build, an output folder named `output-docker` will be generated. It contains one subfolder for each contract, each holding the following files:
200193

201194
- `contract.wasm`: the actual bytecode of the smart contract, to be deployed on the network;
202195
- `contract.abi.json`: the ABI of the smart contract (a listing of endpoints and types definitions), to be used when developing dApps or simply interacting with the contract (e.g. using _sdk-js_);
203196
- `contract.codehash.txt`: the computed `codehash` of the contract.
204197
- **`contract-1.2.3.source.json`** : packaged (bundled) source code.
205198

206199
:::tip
207-
You can run a local test using this [example-sc](https://github.com/multiversx/mx-reproducible-contract-build-example-sc).
200+
You can run a local test using [these example contracts](https://github.com/multiversx/mx-contracts-rs).
208201
:::
209202

210203
[comment]: # (mx-context-auto)
@@ -216,10 +209,10 @@ Once the build is ready, you can check the codehash of the generated `*.wasm`, b
216209
For our example, that should be:
217210

218211
```
219-
adder.codehash.txt: 58c6e78f40bd6ccc30d8a01f952b34a13ebfdad796a2526678be17c5d7820174
212+
adder.codehash.txt: 384b680df7a95ebceca02ffb3e760a2fc288dea1b802685ef15df22ae88ba15b
220213
```
221214

222-
We can see that it matches the previously fetched (or computed) codehash. That is, the contract deployed at [erd1qqqqqqqqqqqqqpgqahertgz4020wegswus8m7f2ak8a6d0gv396qw3t2zy](https://devnet-explorer.multiversx.com/accounts/erd1qqqqqqqqqqqqqpgqahertgz4020wegswus8m7f2ak8a6d0gv396qw3t2zy) is guaranteed to have been built from the same source code version as the one that we've checked out.
215+
We can see that it matches the previously fetched (or computed) codehash. That is, the contract deployed at [erd1qqqqqqqqqqqqqpgqws44xjx2t056nn79fn29q0rjwfrd3m43396ql35kxy](https://devnet-explorer.multiversx.com/accounts/erd1qqqqqqqqqqqqqpgqws44xjx2t056nn79fn29q0rjwfrd3m43396ql35kxy) is guaranteed to have been built from the same source code version as the one that we've checked out.
223216

224217
**Congratulations!** You've achieved a reproducible contract build 🎉
225218

docs/sdk-and-tools/sdk-js/extending-sdk-js.md

Lines changed: 7 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ pagination_prev: sdk-and-tools/sdk-js/sdk-js
88

99
This tutorial will guide you through the process of extending and tailoring certain modules from sdk-js.
1010

11+
:::important
12+
Documentation in this section is preliminary and subject to change.
13+
:::
14+
1115
[comment]: # (mx-context-auto)
1216

1317
## Extending the Network Providers
@@ -16,74 +20,9 @@ The default classes from `@multiversx/sdk-network-providers` should **only be us
1620

1721
[comment]: # (mx-context-auto)
1822

19-
### Performing HTTP requests from scratch
20-
21-
One can broadcast transactions and GET resources from the MultiversX API (or Gateway) by performing simple HTTP requests using the `axios` utility. Below are a few examples:
22-
23-
Broadcasting a transaction:
24-
25-
```
26-
import axios, { AxiosResponse } from "axios";
27-
28-
let tx = new Transaction({ /* provide the fields */ });
29-
// ... sign the transaction using a dApp / signing provider
30-
let data = tx.toSendable();
31-
let url = "https://devnet-api.multiversx.com/transactions";
32-
let response: AxiosResponse = await axios.post(url, data, {
33-
headers: {
34-
"Content-Type": "application/json",
35-
}
36-
});
37-
let txHash = response.data.txHash;
38-
```
39-
40-
Fetching a transaction:
41-
42-
```
43-
let url = `https://devnet-api.multiversx.com/transactions/${txHash}`;
44-
let response = await axios.get(url);
45-
let transactionOnNetwork = TransactionOnNetwork.fromApiHttpResponse(txHash, response.data);
46-
```
47-
48-
Querying a smart contract (with parsing the results):
49-
50-
```
51-
let query = contract.createQuery({
52-
func: new ContractFunction("foobar"),
53-
args: [new AddressValue(addressOfAlice)],
54-
caller: new Address("erd1...")
55-
});
56-
57-
let url = "https://devnet-api.multiversx.com/query";
58-
let data = {
59-
scAddress: query.address.bech32(),
60-
caller: query.caller?.bech32() ? query.caller.bech32() : undefined,
61-
funcName: query.func.toString(),
62-
value: query.value ? query.value.toString() : undefined,
63-
args: query.getEncodedArguments()
64-
};
65-
66-
let response: AxiosResponse = await axios.post(url, data, {
67-
headers: {
68-
"Content-Type": "application/json",
69-
}
70-
});
71-
72-
let queryResponse = {
73-
returnCode: response.data.returnCode,
74-
returnMessage: response.data.returnMessage,
75-
getReturnDataParts: () => response.data.returnData.map((item) => Buffer.from(item || "", "base64"));
76-
};
77-
78-
let endpointDefinition = contract.getEndpoint("foobar");
79-
let { firstValue, secondValue, returnCode } = resultsParser.parseQueryResponse(queryResponse, endpointDefinition);
80-
```
81-
82-
[comment]: # (mx-context-auto)
83-
8423
### Extending a default Network Provider
8524

86-
You can also derive from the default network providers (`ApiNetworkProvider` and `ProxyNetworkProvider`) and overwrite / add additional methods, making use of `doGetGeneric()` and `doPostGeneric()`.
25+
You can derive from the default network providers (`ApiNetworkProvider` and `ProxyNetworkProvider`) and overwrite / add additional methods, making use of `doGetGeneric()` and `doPostGeneric()`. For example:
8726

8827
```
8928
export class MyTailoredNetworkProvider extends ApiNetworkProvider {
@@ -103,36 +42,6 @@ export class MyTailoredNetworkProvider extends ApiNetworkProvider {
10342
If, for some reason, the default transaction completion detection algorithm provided by **sdk-js** does not satisfy your requirements, you may want to use a different strategy for transaction awaiting, such as:
10443

10544
```
106-
await transactionWatcher.awaitAllEvents(transaction, ["mySpecialEventFoo", "mySpecialEventBar"]);
107-
await transactionWatcher.awaitAnyEvents(transaction, ["mySpecialEventFoo", "mySpecialEventBar"]);
45+
await transactionWatcher.awaitAllEvents(txHash, ["mySpecialEventFoo", "mySpecialEventBar"]);
46+
await transactionWatcher.awaitAnyEvents(txHash, ["mySpecialEventFoo", "mySpecialEventBar"]);
10847
```
109-
110-
[comment]: # (mx-context-auto)
111-
112-
## Extending the contract results parser
113-
114-
If, for some reason (e.g. a bug), the default `ResultsParser` provided by **sdk-js** does not satisfy your requirements, you may want to extend it and override the method `createBundleWithCustomHeuristics()`:
115-
116-
```
117-
export class MyTailoredResultsParser extends ResultsParser {
118-
protected createBundleWithCustomHeuristics(transaction: ITransactionOnNetwork, transactionMetadata: TransactionMetadata): UntypedOutcomeBundle | null {
119-
let returnMessage: string = "<< extract the message from the input transaction object >>";
120-
let values: Buffer[] = [
121-
Buffer.from("<< extract 1st result from the input transaction object >>"),
122-
Buffer.from("<< extract 2nd result from the input transaction object >>"),
123-
Buffer.from("<< extract 3rd result from the input transaction object >>"),
124-
// ...
125-
]
126-
127-
return {
128-
returnCode: ReturnCode.Ok,
129-
returnMessage: returnMessage,
130-
values: values
131-
};
132-
}
133-
}
134-
```
135-
136-
:::important
137-
When the default `ResultsParser` misbehaves, please open an issue [on GitHub](https://github.com/multiversx/mx-sdk-js-core/issues), and also provide as much details as possible about the unparsable results (e.g. provide a dump of the transaction object if possible - make sure to remove any sensitive information).
138-
:::

docs/sdk-and-tools/sdk-py/configuring-mxpy.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ In order to view the current configuration, one can issue the command `mxpy conf
1919

2020
```
2121
{
22-
"dependencies.llvm.tag": "v...",
23-
"dependencies.vmtools.tag": "v...",
2422
"dependencies.rust.tag": ""
2523
}
2624
```
@@ -31,6 +29,6 @@ In order to view the current configuration, one can issue the command `mxpy conf
3129

3230
One can alter the current configuration using the command `mxpy config set`. For example, in order to set the **_rust version_** to be used, one would do the following:
3331

34-
```
35-
$ mxpy config set dependencies.rust.tag nightly-2023-12-11
32+
```bash
33+
$ mxpy config set dependencies.rust.tag stable
3634
```

docs/sdk-and-tools/sdk-py/installing-mxpy.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ pipx upgrade multiversx-sdk-cli
7878

7979
Installing **mxpy** using **mxpy-up** is not recommended anymore. We recommend using **pipx** instead.
8080

81-
If you've previously installed **mxpy** using **mxpy-up** and you'd like to switch to **pipx**, make sure to remove the old `mxpy` shortcut and virtual Python environment beforehand:
81+
If you've previously installed **mxpy** using the legacy **mxpy-up**, you should switch to the **pipx** approach. Make sure to remove the old `mxpy` shortcut and virtual Python environment beforehand:
8282

8383
```sh
8484
rm ~/multiversx-sdk/mxpy

0 commit comments

Comments
 (0)