Эх сурвалжийг харах

Add Constructor Support for Solang Solidity Contracts on Soroban (#1674)

Tarek Elsayed 11 сар өмнө
parent
commit
de4fc3476e

+ 5 - 5
.github/workflows/release.yml

@@ -15,7 +15,7 @@ jobs:
       uses: actions/checkout@v4
       with:
         submodules: recursive
-    - uses: dtolnay/rust-toolchain@1.75.0
+    - uses: dtolnay/rust-toolchain@1.81.0
     - name: Build
       run: cargo build --verbose --release
     - name: Run tests
@@ -41,7 +41,7 @@ jobs:
       run: |
         sudo apt-get update
         sudo apt-get install -y gcc g++ make
-    - uses: dtolnay/rust-toolchain@1.75.0
+    - uses: dtolnay/rust-toolchain@1.81.0
     - name: Get LLVM
       run: curl -sSL --output llvm16.0-linux-arm64.tar.xz https://github.com/hyperledger-solang/solang-llvm/releases/download/llvm16-0/llvm16.0-linux-arm64.tar.xz
     - name: Extract LLVM
@@ -74,7 +74,7 @@ jobs:
       run: unzip c:\llvm.zip -d c:/
     - name: Add LLVM to Path
       run: echo "c:\llvm16.0\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8
-    - uses: dtolnay/rust-toolchain@1.75.0
+    - uses: dtolnay/rust-toolchain@1.81.0
       with:
         components: clippy
     - name: Build
@@ -97,7 +97,7 @@ jobs:
       uses: actions/checkout@v4
       with:
         submodules: recursive
-    - uses: dtolnay/rust-toolchain@1.75.0
+    - uses: dtolnay/rust-toolchain@1.81.0
     - name: Get LLVM
       run: curl -sSL --output llvm16.0-mac-arm.tar.xz https://github.com/hyperledger-solang/solang-llvm/releases/download/llvm16-0/llvm16.0-mac-arm.tar.xz
     - name: Extract LLVM
@@ -124,7 +124,7 @@ jobs:
       uses: actions/checkout@v4
       with:
         submodules: recursive
-    - uses: dtolnay/rust-toolchain@1.75.0
+    - uses: dtolnay/rust-toolchain@1.81.0
     - name: Get LLVM
       run: wget -q -O llvm16.0-mac-intel.tar.xz https://github.com/hyperledger-solang/solang-llvm/releases/download/llvm16-0/llvm16.0-mac-intel.tar.xz
     - name: Extract LLVM

+ 10 - 10
.github/workflows/test.yml

@@ -63,7 +63,7 @@ jobs:
     - name: Install Rust
       uses: dtolnay/rust-toolchain@master
       with:
-        toolchain: 1.75.0
+        toolchain: 1.81.0
         components: |
           llvm-tools
           clippy
@@ -120,7 +120,7 @@ jobs:
       run: |
         sudo apt-get update
         sudo apt-get install -y gcc g++ make
-    - uses: dtolnay/rust-toolchain@1.75.0
+    - uses: dtolnay/rust-toolchain@1.81.0
     - name: Get LLVM
       run: curl -sSL --output llvm16.0-linux-arm64.tar.xz https://github.com/hyperledger-solang/solang-llvm/releases/download/llvm16-0/llvm16.0-linux-arm64.tar.xz
     - name: Extract LLVM
@@ -153,7 +153,7 @@ jobs:
     # Use C:\ as D:\ might run out of space
     - name: "Use C: for rust temporary files"
       run: echo "CARGO_TARGET_DIR=C:\target" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
-    - uses: dtolnay/rust-toolchain@1.75.0
+    - uses: dtolnay/rust-toolchain@1.81.0
       with:
         components: clippy
     # We run clippy on Linux in the lint job above, but this does not check #[cfg(windows)] items
@@ -179,7 +179,7 @@ jobs:
       uses: actions/checkout@v4
       with:
         submodules: recursive
-    - uses: dtolnay/rust-toolchain@1.75.0
+    - uses: dtolnay/rust-toolchain@1.81.0
     - name: Get LLVM
       run: curl -sSL --output llvm16.0-mac-arm.tar.xz https://github.com/hyperledger-solang/solang-llvm/releases/download/llvm16-0/llvm16.0-mac-arm.tar.xz
     - name: Extract LLVM
@@ -205,7 +205,7 @@ jobs:
       uses: actions/checkout@v4
       with:
         submodules: recursive
-    - uses: dtolnay/rust-toolchain@1.75.0
+    - uses: dtolnay/rust-toolchain@1.81.0
     - name: Get LLVM
       run: wget -q -O llvm16.0-mac-intel.tar.xz https://github.com/hyperledger-solang/solang-llvm/releases/download/llvm16-0/llvm16.0-mac-intel.tar.xz
     - name: Extract LLVM
@@ -267,7 +267,7 @@ jobs:
     - uses: actions/setup-node@v4
       with:
         node-version: '16'
-    - uses: dtolnay/rust-toolchain@1.75.0
+    - uses: dtolnay/rust-toolchain@1.81.0
     - name: Setup yarn
       run: npm install -g yarn
     - uses: actions/download-artifact@v4.1.8
@@ -318,7 +318,7 @@ jobs:
     - uses: actions/setup-node@v4
       with:
         node-version: '16'
-    - uses: dtolnay/rust-toolchain@1.75.0
+    - uses: dtolnay/rust-toolchain@1.81.0
     - uses: actions/download-artifact@v4.1.8
       with:
         name: solang-linux-x86-64
@@ -329,7 +329,7 @@ jobs:
         echo "$(pwd)/bin" >> $GITHUB_PATH
     
     - name: Install Soroban
-      run: cargo install --locked soroban-cli --version 21.0.0-rc.1
+      run: cargo install --locked soroban-cli --version 22.0.0
     - name: Add cargo install location to PATH
       run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
     - run: npm install
@@ -360,7 +360,7 @@ jobs:
     - uses: actions/setup-node@v4
       with:
         node-version: '16'
-    - uses: dtolnay/rust-toolchain@1.75.0
+    - uses: dtolnay/rust-toolchain@1.81.0
     - uses: actions/download-artifact@v4.1.8
       with:
         name: solang-linux-x86-64
@@ -537,7 +537,7 @@ jobs:
       - name: Install Rust
         uses: dtolnay/rust-toolchain@master
         with:
-          toolchain: 1.75.0
+          toolchain: 1.81.0
           components: llvm-tools
       - name: Install cargo-llvm-cov
         uses: taiki-e/install-action@cargo-llvm-cov

+ 2 - 2
Cargo.toml

@@ -8,7 +8,7 @@ license = "Apache-2.0"
 build = "build.rs"
 description = "Solang Solidity Compiler"
 keywords = [ "solidity", "compiler", "solana", "polkadot", "substrate" ]
-rust-version = "1.75.0"
+rust-version = "1.81.0"
 edition = "2021"
 exclude = [ "/.*", "/docs",  "/examples", "/solana-library", "/tests", "/integration", "/vscode", "/testdata" ]
 
@@ -71,7 +71,7 @@ forge-fmt = { path = "fmt", optional = true }
 # We don't use ethers-core directly, but need the correct version for the
 # build to work.
 ethers-core = { version = "2.0.10", optional = true }
-soroban-sdk = { version = "20.0.0-rc2", features = ["testutils"], optional = true }
+soroban-sdk = { version = "22.0.0-rc.3.2", features = ["testutils"], optional = true }
 
 [dev-dependencies]
 num-derive = "0.4"

+ 1 - 1
Dockerfile

@@ -4,7 +4,7 @@ COPY . src
 WORKDIR /src/stdlib/
 RUN make
 
-RUN rustup default 1.75.0
+RUN rustup default 1.81.0
 
 WORKDIR /src
 RUN cargo build --release

+ 1 - 1
docs/installing.rst

@@ -89,7 +89,7 @@ Option 5: Build Solang from source
 
 In order to build Solang from source, you will need:
 
-* Rust version 1.75.0 or higher
+* Rust version 1.81.0 or higher
 * A C++ compiler with support for C++17
 * A build of LLVM based on the Solana LLVM tree. There are a few LLVM patches required that are not upstream yet.
 

+ 0 - 4
integration/soroban/counter.spec.js

@@ -30,10 +30,6 @@ describe('Counter', () => {
 
     // load contract
     contract = new StellarSdk.Contract(contractAddr);
-
-    // initialize the contract
-    await call_contract_function("init", server, keypair, contract);
-
   });
 
   it('get correct initial counter', async () => {

+ 25 - 13
src/emit/soroban/mod.rs

@@ -8,18 +8,23 @@ use crate::codegen::{
 
 use crate::emit::cfg::emit_cfg;
 use crate::{emit::Binary, sema::ast};
+use funty::Fundamental;
 use inkwell::{
     context::Context,
     module::{Linkage, Module},
 };
 use soroban_sdk::xdr::{
-    DepthLimitedWrite, ScEnvMetaEntry, ScSpecEntry, ScSpecFunctionInputV0, ScSpecFunctionV0,
-    ScSpecTypeDef, StringM, WriteXdr,
+    Limited, Limits, ScEnvMetaEntry, ScEnvMetaEntryInterfaceVersion, ScSpecEntry,
+    ScSpecFunctionInputV0, ScSpecFunctionV0, ScSpecTypeDef, StringM, WriteXdr,
 };
 use std::ffi::CString;
 use std::sync;
 
-const SOROBAN_ENV_INTERFACE_VERSION: u64 = 90194313216;
+const SOROBAN_ENV_INTERFACE_VERSION: ScEnvMetaEntryInterfaceVersion =
+    ScEnvMetaEntryInterfaceVersion {
+        protocol: 22,
+        pre_release: 0,
+    };
 pub const PUT_CONTRACT_DATA: &str = "l._";
 pub const GET_CONTRACT_DATA: &str = "l.1";
 pub const LOG_FROM_LINEAR_MEMORY: &str = "x._";
@@ -129,9 +134,15 @@ impl SorobanTarget {
     }
 
     fn emit_env_meta_entries<'a>(context: &'a Context, binary: &mut Binary<'a>, opt: &'a Options) {
-        let mut meta = DepthLimitedWrite::new(Vec::new(), 10);
-        let soroban_env_interface_version =
-            opt.soroban_version.unwrap_or(SOROBAN_ENV_INTERFACE_VERSION);
+        let mut meta = Limited::new(Vec::new(), Limits::none());
+        let soroban_env_interface_version = opt.soroban_version;
+        let soroban_env_interface_version = match soroban_env_interface_version {
+            Some(version) => ScEnvMetaEntryInterfaceVersion {
+                protocol: version.as_u32(),
+                pre_release: 0,
+            },
+            None => SOROBAN_ENV_INTERFACE_VERSION,
+        };
         ScEnvMetaEntry::ScEnvMetaKindInterfaceVersion(soroban_env_interface_version)
             .write_xdr(&mut meta)
             .expect("writing env meta interface version to xdr");
@@ -146,7 +157,7 @@ impl SorobanTarget {
     ) {
         if cfg.public && !cfg.is_placeholder() {
             // TODO: Emit custom type spec entries
-            let mut spec = DepthLimitedWrite::new(Vec::new(), 10);
+            let mut spec = Limited::new(Vec::new(), Limits::none());
             ScSpecEntry::FunctionV0(ScSpecFunctionV0 {
                 name: name
                     .try_into()
@@ -252,13 +263,13 @@ impl SorobanTarget {
     }
 
     fn emit_initializer(binary: &mut Binary, _ns: &ast::Namespace) {
-        let mut cfg = ControlFlowGraph::new("init".to_string(), ASTFunction::None);
+        let mut cfg = ControlFlowGraph::new("__constructor".to_string(), ASTFunction::None);
 
         cfg.public = true;
         let void_param = ast::Parameter::new_default(ast::Type::Void);
         cfg.returns = sync::Arc::new(vec![void_param]);
 
-        Self::emit_function_spec_entry(binary.context, &cfg, "init".to_string(), binary);
+        Self::emit_function_spec_entry(binary.context, &cfg, "__constructor".to_string(), binary);
 
         let function_name = CString::new(STORAGE_INITIALIZER).unwrap();
         let mut storage_initializers = binary
@@ -271,10 +282,11 @@ impl SorobanTarget {
         assert!(storage_initializers.next().is_none());
 
         let void_type = binary.context.i64_type().fn_type(&[], false);
-        let init = binary
-            .module
-            .add_function("init", void_type, Some(Linkage::External));
-        let entry = binary.context.append_basic_block(init, "entry");
+        let constructor =
+            binary
+                .module
+                .add_function("__constructor", void_type, Some(Linkage::External));
+        let entry = binary.context.append_basic_block(constructor, "entry");
 
         binary.builder.position_at_end(entry);
         binary

+ 4 - 1
tests/soroban.rs

@@ -32,7 +32,7 @@ pub fn build_solidity(src: &str) -> SorobanEnv {
             log_prints: true,
             #[cfg(feature = "wasm_opt")]
             wasm_opt: Some(contract_build::OptimizationPasses::Z),
-            soroban_version: Some(85899345977),
+            soroban_version: None,
             ..Default::default()
         },
         std::vec!["unknown".to_string()],
@@ -59,6 +59,9 @@ impl SorobanEnv {
     }
 
     pub fn register_contract(&mut self, contract_wasm: Vec<u8>) -> Address {
+        // For now, we keep using `register_contract_wasm`. To use `register`, we have to figure
+        // out first what to pass for `constructor_args`
+        #[allow(deprecated)]
         let addr = self
             .env
             .register_contract_wasm(None, contract_wasm.as_slice());

+ 0 - 6
tests/soroban_testcases/print.rs

@@ -18,8 +18,6 @@ fn log_runtime_error() {
 
     let addr = src.contracts.last().unwrap();
 
-    let _res = src.invoke_contract(addr, "init", vec![]);
-
     src.invoke_contract(addr, "decrement", vec![]);
 
     let logs = src.invoke_contract_expect_error(addr, "decrement", vec![]);
@@ -40,8 +38,6 @@ fn print() {
 
     let addr = src.contracts.last().unwrap();
 
-    let _res = src.invoke_contract(addr, "init", vec![]);
-
     src.invoke_contract(addr, "print", vec![]);
 
     let logs = src.env.logs().all();
@@ -65,8 +61,6 @@ fn print_then_runtime_error() {
 
     let addr = src.contracts.last().unwrap();
 
-    let _res = src.invoke_contract(addr, "init", vec![]);
-
     src.invoke_contract(addr, "decrement", vec![]);
 
     let logs = src.invoke_contract_expect_error(addr, "decrement", vec![]);

+ 0 - 2
tests/soroban_testcases/storage.rs

@@ -23,8 +23,6 @@ fn counter() {
 
     let addr = src.contracts.last().unwrap();
 
-    let _res = src.invoke_contract(addr, "init", vec![]);
-
     let res = src.invoke_contract(addr, "count", vec![]);
     let expected: Val = 10_u64.into_val(&src.env);
     assert!(expected.shallow_eq(&res));