Sfoglia il codice sorgente

runtime: Implement initial webassembly runtime prototype for smart contracts.

parazyd 4 anni fa
parent
commit
deab6241dd
13 ha cambiato i file con 1224 aggiunte e 38 eliminazioni
  1. 670 27
      Cargo.lock
  2. 25 10
      Cargo.toml
  3. 49 1
      src/error.rs
  4. 3 0
      src/lib.rs
  5. 104 0
      src/runtime/memory.rs
  6. 3 0
      src/runtime/mod.rs
  7. 167 0
      src/runtime/runtime.rs
  8. 38 0
      src/runtime/util.rs
  9. 9 0
      src/sdk/Cargo.toml
  10. 60 0
      src/sdk/src/entrypoint.rs
  11. 64 0
      src/sdk/src/error.rs
  12. 8 0
      src/sdk/src/lib.rs
  13. 24 0
      src/sdk/src/log.rs

+ 670 - 27
Cargo.lock

@@ -18,7 +18,7 @@ version = "0.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
 checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
 dependencies = [
 dependencies = [
- "gimli",
+ "gimli 0.26.1",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -42,12 +42,6 @@ dependencies = [
  "const-random",
  "const-random",
 ]
 ]
 
 
-[[package]]
-name = "ahash"
-version = "0.4.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
-
 [[package]]
 [[package]]
 name = "ahash"
 name = "ahash"
 version = "0.7.6"
 version = "0.7.6"
@@ -385,7 +379,7 @@ dependencies = [
  "cfg-if 1.0.0",
  "cfg-if 1.0.0",
  "libc",
  "libc",
  "miniz_oxide 0.4.4",
  "miniz_oxide 0.4.4",
- "object",
+ "object 0.27.1",
  "rustc-demangle",
  "rustc-demangle",
 ]
 ]
 
 
@@ -633,19 +627,19 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "borsh"
 name = "borsh"
-version = "0.9.1"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18dda7dc709193c0d86a1a51050a926dc3df1cf262ec46a23a25dba421ea1924"
+checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa"
 dependencies = [
 dependencies = [
  "borsh-derive",
  "borsh-derive",
- "hashbrown 0.9.1",
+ "hashbrown 0.11.2",
 ]
 ]
 
 
 [[package]]
 [[package]]
 name = "borsh-derive"
 name = "borsh-derive"
-version = "0.9.1"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "684155372435f578c0fa1acd13ebbb182cc19d6b38b64ae7901da4393217d264"
+checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775"
 dependencies = [
 dependencies = [
  "borsh-derive-internal",
  "borsh-derive-internal",
  "borsh-schema-derive-internal",
  "borsh-schema-derive-internal",
@@ -656,9 +650,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "borsh-derive-internal"
 name = "borsh-derive-internal"
-version = "0.9.1"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2102f62f8b6d3edeab871830782285b64cc1830168094db05c8e458f209bc5c3"
+checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065"
 dependencies = [
 dependencies = [
  "proc-macro2 1.0.36",
  "proc-macro2 1.0.36",
  "quote 1.0.14",
  "quote 1.0.14",
@@ -667,9 +661,9 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "borsh-schema-derive-internal"
 name = "borsh-schema-derive-internal"
-version = "0.9.1"
+version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "196c978c4c9b0b142d446ef3240690bf5a8a33497074a113ff9a337ccb750483"
+checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0"
 dependencies = [
 dependencies = [
  "proc-macro2 1.0.36",
  "proc-macro2 1.0.36",
  "quote 1.0.14",
  "quote 1.0.14",
@@ -710,6 +704,27 @@ dependencies = [
  "serde",
  "serde",
 ]
 ]
 
 
+[[package]]
+name = "bytecheck"
+version = "0.6.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "314889ea31cda264cb7c3d6e6e5c9415a987ecb0e72c17c00d36fbb881d34abe"
+dependencies = [
+ "bytecheck_derive",
+ "ptr_meta",
+]
+
+[[package]]
+name = "bytecheck_derive"
+version = "0.6.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4a2b3b92c135dae665a6f760205b89187638e83bed17ef3e44e83c712cf30600"
+dependencies = [
+ "proc-macro2 1.0.36",
+ "quote 1.0.14",
+ "syn 1.0.85",
+]
+
 [[package]]
 [[package]]
 name = "bytemuck"
 name = "bytemuck"
 version = "1.7.3"
 version = "1.7.3"
@@ -1083,6 +1098,66 @@ dependencies = [
  "libc",
  "libc",
 ]
 ]
 
 
+[[package]]
+name = "cranelift-bforest"
+version = "0.76.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e6bea67967505247f54fa2c85cf4f6e0e31c4e5692c9b70e4ae58e339067333"
+dependencies = [
+ "cranelift-entity",
+]
+
+[[package]]
+name = "cranelift-codegen"
+version = "0.76.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48194035d2752bdd5bdae429e3ab88676e95f52a2b1355a5d4e809f9e39b1d74"
+dependencies = [
+ "cranelift-bforest",
+ "cranelift-codegen-meta",
+ "cranelift-codegen-shared",
+ "cranelift-entity",
+ "gimli 0.25.0",
+ "log",
+ "regalloc",
+ "smallvec",
+ "target-lexicon",
+]
+
+[[package]]
+name = "cranelift-codegen-meta"
+version = "0.76.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "976efb22fcab4f2cd6bd4e9913764616a54d895c1a23530128d04e03633c555f"
+dependencies = [
+ "cranelift-codegen-shared",
+ "cranelift-entity",
+]
+
+[[package]]
+name = "cranelift-codegen-shared"
+version = "0.76.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dabb5fe66e04d4652e434195b45ae65b5c8172d520247b8f66d8df42b2b45dc"
+
+[[package]]
+name = "cranelift-entity"
+version = "0.76.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3329733e4d4b8e91c809efcaa4faee80bf66f20164e3dd16d707346bd3494799"
+
+[[package]]
+name = "cranelift-frontend"
+version = "0.76.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "279afcc0d3e651b773f94837c3d581177b348c8d69e928104b2e9fccb226f921"
+dependencies = [
+ "cranelift-codegen",
+ "log",
+ "smallvec",
+ "target-lexicon",
+]
+
 [[package]]
 [[package]]
 name = "crc"
 name = "crc"
 version = "2.1.0"
 version = "2.1.0"
@@ -1395,6 +1470,7 @@ dependencies = [
  "clap 3.1.6",
  "clap 3.1.6",
  "crypto_api_chachapoly",
  "crypto_api_chachapoly",
  "dirs 4.0.0",
  "dirs 4.0.0",
+ "drk-sdk",
  "fast-socks5",
  "fast-socks5",
  "futures",
  "futures",
  "group",
  "group",
@@ -1426,6 +1502,9 @@ dependencies = [
  "toml",
  "toml",
  "tungstenite",
  "tungstenite",
  "url",
  "url",
+ "wasmer",
+ "wasmer-compiler-singlepass",
+ "wasmer-middlewares",
  "zeromq",
  "zeromq",
 ]
 ]
 
 
@@ -1456,8 +1535,18 @@ version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858"
 checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858"
 dependencies = [
 dependencies = [
- "darling_core",
- "darling_macro",
+ "darling_core 0.10.2",
+ "darling_macro 0.10.2",
+]
+
+[[package]]
+name = "darling"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4"
+dependencies = [
+ "darling_core 0.13.1",
+ "darling_macro 0.13.1",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -1474,13 +1563,38 @@ dependencies = [
  "syn 1.0.85",
  "syn 1.0.85",
 ]
 ]
 
 
+[[package]]
+name = "darling_core"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2 1.0.36",
+ "quote 1.0.14",
+ "strsim 0.10.0",
+ "syn 1.0.85",
+]
+
 [[package]]
 [[package]]
 name = "darling_macro"
 name = "darling_macro"
 version = "0.10.2"
 version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
 checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
 dependencies = [
 dependencies = [
- "darling_core",
+ "darling_core 0.10.2",
+ "quote 1.0.14",
+ "syn 1.0.85",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b"
+dependencies = [
+ "darling_core 0.13.1",
  "quote 1.0.14",
  "quote 1.0.14",
  "syn 1.0.85",
  "syn 1.0.85",
 ]
 ]
@@ -1532,7 +1646,7 @@ version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0"
 checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0"
 dependencies = [
 dependencies = [
- "darling",
+ "darling 0.10.2",
  "derive_builder_core",
  "derive_builder_core",
  "proc-macro2 1.0.36",
  "proc-macro2 1.0.36",
  "quote 1.0.14",
  "quote 1.0.14",
@@ -1545,7 +1659,7 @@ version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef"
 checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef"
 dependencies = [
 dependencies = [
- "darling",
+ "darling 0.10.2",
  "proc-macro2 1.0.36",
  "proc-macro2 1.0.36",
  "quote 1.0.14",
  "quote 1.0.14",
  "syn 1.0.85",
  "syn 1.0.85",
@@ -1710,6 +1824,15 @@ dependencies = [
  "url",
  "url",
 ]
 ]
 
 
+[[package]]
+name = "drk-sdk"
+version = "0.3.0"
+dependencies = [
+ "borsh",
+ "thiserror",
+ "wee_alloc",
+]
+
 [[package]]
 [[package]]
 name = "dwrote"
 name = "dwrote"
 version = "0.11.0"
 version = "0.11.0"
@@ -1722,6 +1845,32 @@ dependencies = [
  "wio",
  "wio",
 ]
 ]
 
 
+[[package]]
+name = "dynasm"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47b1801e630bd336d0bbbdbf814de6cc749c9a400c7e3d995e6adfd455d0c83c"
+dependencies = [
+ "bitflags",
+ "byteorder",
+ "lazy_static",
+ "proc-macro-error",
+ "proc-macro2 1.0.36",
+ "quote 1.0.14",
+ "syn 1.0.85",
+]
+
+[[package]]
+name = "dynasmrt"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d428afc93ad288f6dffc1fa5f4a78201ad2eec33c5a522e51c181009eb09061"
+dependencies = [
+ "byteorder",
+ "dynasm",
+ "memmap2",
+]
+
 [[package]]
 [[package]]
 name = "easy-parallel"
 name = "easy-parallel"
 version = "3.2.0"
 version = "3.2.0"
@@ -1801,6 +1950,26 @@ dependencies = [
  "cfg-if 1.0.0",
  "cfg-if 1.0.0",
 ]
 ]
 
 
+[[package]]
+name = "enum-iterator"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6"
+dependencies = [
+ "enum-iterator-derive",
+]
+
+[[package]]
+name = "enum-iterator-derive"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159"
+dependencies = [
+ "proc-macro2 1.0.36",
+ "quote 1.0.14",
+ "syn 1.0.85",
+]
+
 [[package]]
 [[package]]
 name = "enum-primitive-derive"
 name = "enum-primitive-derive"
 version = "0.2.2"
 version = "0.2.2"
@@ -1812,6 +1981,27 @@ dependencies = [
  "syn 1.0.85",
  "syn 1.0.85",
 ]
 ]
 
 
+[[package]]
+name = "enumset"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6216d2c19a6fb5f29d1ada1dc7bc4367a8cbf0fa4af5cf12e07b5bbdde6b5b2c"
+dependencies = [
+ "enumset_derive",
+]
+
+[[package]]
+name = "enumset_derive"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6451128aa6655d880755345d085494cf7561a6bee7c8dc821e5d77e6d267ecd4"
+dependencies = [
+ "darling 0.13.1",
+ "proc-macro2 1.0.36",
+ "quote 1.0.14",
+ "syn 1.0.85",
+]
+
 [[package]]
 [[package]]
 name = "env_logger"
 name = "env_logger"
 version = "0.9.0"
 version = "0.9.0"
@@ -1884,6 +2074,12 @@ dependencies = [
  "synstructure",
  "synstructure",
 ]
 ]
 
 
+[[package]]
+name = "fallible-iterator"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
+
 [[package]]
 [[package]]
 name = "fast-socks5"
 name = "fast-socks5"
 version = "0.4.3"
 version = "0.4.3"
@@ -2271,6 +2467,17 @@ dependencies = [
  "weezl",
  "weezl",
 ]
 ]
 
 
+[[package]]
+name = "gimli"
+version = "0.25.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7"
+dependencies = [
+ "fallible-iterator",
+ "indexmap",
+ "stable_deref_trait",
+]
+
 [[package]]
 [[package]]
 name = "gimli"
 name = "gimli"
 version = "0.26.1"
 version = "0.26.1"
@@ -2380,18 +2587,18 @@ dependencies = [
 
 
 [[package]]
 [[package]]
 name = "hashbrown"
 name = "hashbrown"
-version = "0.9.1"
+version = "0.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
+checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
 dependencies = [
 dependencies = [
- "ahash 0.4.7",
+ "ahash 0.7.6",
 ]
 ]
 
 
 [[package]]
 [[package]]
 name = "hashbrown"
 name = "hashbrown"
-version = "0.11.2"
+version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+checksum = "8c21d40587b92fa6a6c6e3c1bdbf87d75511db5672f9c93175574b3a00df1758"
 dependencies = [
 dependencies = [
  "ahash 0.7.6",
  "ahash 0.7.6",
 ]
 ]
@@ -2614,6 +2821,7 @@ checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
 dependencies = [
 dependencies = [
  "autocfg 1.0.1",
  "autocfg 1.0.1",
  "hashbrown 0.11.2",
  "hashbrown 0.11.2",
+ "serde",
 ]
 ]
 
 
 [[package]]
 [[package]]
@@ -2760,6 +2968,12 @@ version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
 checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
 
 
+[[package]]
+name = "leb128"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
+
 [[package]]
 [[package]]
 name = "libc"
 name = "libc"
 version = "0.2.112"
 version = "0.2.112"
@@ -2871,6 +3085,36 @@ dependencies = [
  "value-bag",
  "value-bag",
 ]
 ]
 
 
+[[package]]
+name = "loupe"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b6a72dfa44fe15b5e76b94307eeb2ff995a8c5b283b55008940c02e0c5b634d"
+dependencies = [
+ "indexmap",
+ "loupe-derive",
+ "rustversion",
+]
+
+[[package]]
+name = "loupe-derive"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0fbfc88337168279f2e9ae06e157cfed4efd3316e14dc96ed074d4f2e6c5952"
+dependencies = [
+ "quote 1.0.14",
+ "syn 1.0.85",
+]
+
+[[package]]
+name = "mach"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 [[package]]
 name = "matches"
 name = "matches"
 version = "0.1.9"
 version = "0.1.9"
@@ -2916,6 +3160,12 @@ dependencies = [
  "autocfg 1.0.1",
  "autocfg 1.0.1",
 ]
 ]
 
 
+[[package]]
+name = "memory_units"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3"
+
 [[package]]
 [[package]]
 name = "mime"
 name = "mime"
 version = "0.3.16"
 version = "0.3.16"
@@ -2979,6 +3229,12 @@ dependencies = [
  "winapi 0.3.9",
  "winapi 0.3.9",
 ]
 ]
 
 
+[[package]]
+name = "more-asserts"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389"
+
 [[package]]
 [[package]]
 name = "native-tls"
 name = "native-tls"
 version = "0.2.8"
 version = "0.2.8"
@@ -3147,6 +3403,18 @@ dependencies = [
  "memchr",
  "memchr",
 ]
 ]
 
 
+[[package]]
+name = "object"
+version = "0.28.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40bec70ba014595f99f7aa110b84331ffe1ee9aece7fe6f387cc7e3ecda4d456"
+dependencies = [
+ "crc32fast",
+ "hashbrown 0.11.2",
+ "indexmap",
+ "memchr",
+]
+
 [[package]]
 [[package]]
 name = "once_cell"
 name = "once_cell"
 version = "1.9.0"
 version = "1.9.0"
@@ -3545,6 +3813,26 @@ dependencies = [
  "tempfile",
  "tempfile",
 ]
 ]
 
 
+[[package]]
+name = "ptr_meta"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"
+dependencies = [
+ "ptr_meta_derive",
+]
+
+[[package]]
+name = "ptr_meta_derive"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
+dependencies = [
+ "proc-macro2 1.0.36",
+ "quote 1.0.14",
+ "syn 1.0.85",
+]
+
 [[package]]
 [[package]]
 name = "qstring"
 name = "qstring"
 version = "0.7.2"
 version = "0.7.2"
@@ -3861,6 +4149,17 @@ dependencies = [
  "redox_syscall 0.2.10",
  "redox_syscall 0.2.10",
 ]
 ]
 
 
+[[package]]
+name = "regalloc"
+version = "0.0.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "571f7f397d61c4755285cd37853fe8e03271c243424a907415909379659381c5"
+dependencies = [
+ "log",
+ "rustc-hash",
+ "smallvec",
+]
+
 [[package]]
 [[package]]
 name = "regex"
 name = "regex"
 version = "1.5.4"
 version = "1.5.4"
@@ -3884,6 +4183,18 @@ version = "0.6.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
 checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
 
 
+[[package]]
+name = "region"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e"
+dependencies = [
+ "bitflags",
+ "libc",
+ "mach",
+ "winapi 0.3.9",
+]
+
 [[package]]
 [[package]]
 name = "remove_dir_all"
 name = "remove_dir_all"
 version = "0.5.3"
 version = "0.5.3"
@@ -3893,6 +4204,15 @@ dependencies = [
  "winapi 0.3.9",
  "winapi 0.3.9",
 ]
 ]
 
 
+[[package]]
+name = "rend"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79af64b4b6362ffba04eef3a4e10829718a4896dac19daa741851c86781edf95"
+dependencies = [
+ "bytecheck",
+]
+
 [[package]]
 [[package]]
 name = "reqwest"
 name = "reqwest"
 version = "0.11.9"
 version = "0.11.9"
@@ -3946,6 +4266,31 @@ dependencies = [
  "winapi 0.3.9",
  "winapi 0.3.9",
 ]
 ]
 
 
+[[package]]
+name = "rkyv"
+version = "0.7.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5230ae2981a885590b0dc84e0b24c0ed23ad24f7adc0eb824b26cafa961f7c36"
+dependencies = [
+ "bytecheck",
+ "hashbrown 0.12.0",
+ "ptr_meta",
+ "rend",
+ "rkyv_derive",
+ "seahash",
+]
+
+[[package]]
+name = "rkyv_derive"
+version = "0.7.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fc752d5925dbcb324522f3a4c93193d17f107b2e11810913aa3ad352fa01480"
+dependencies = [
+ "proc-macro2 1.0.36",
+ "quote 1.0.14",
+ "syn 1.0.85",
+]
+
 [[package]]
 [[package]]
 name = "rocksdb"
 name = "rocksdb"
 version = "0.17.0"
 version = "0.17.0"
@@ -4110,6 +4455,12 @@ dependencies = [
  "untrusted",
  "untrusted",
 ]
 ]
 
 
+[[package]]
+name = "seahash"
+version = "4.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
+
 [[package]]
 [[package]]
 name = "secp256k1"
 name = "secp256k1"
 version = "0.20.3"
 version = "0.20.3"
@@ -5273,6 +5624,12 @@ dependencies = [
  "xattr",
  "xattr",
 ]
 ]
 
 
+[[package]]
+name = "target-lexicon"
+version = "0.12.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d7fa7e55043acb85fca6b3c01485a2eeb6b69c5d21002e273c79e465f43b7ac1"
+
 [[package]]
 [[package]]
 name = "taucli"
 name = "taucli"
 version = "0.1.0"
 version = "0.1.0"
@@ -5538,10 +5895,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"
 checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"
 dependencies = [
 dependencies = [
  "cfg-if 1.0.0",
  "cfg-if 1.0.0",
+ "log",
  "pin-project-lite",
  "pin-project-lite",
+ "tracing-attributes",
  "tracing-core",
  "tracing-core",
 ]
 ]
 
 
+[[package]]
+name = "tracing-attributes"
+version = "0.1.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b"
+dependencies = [
+ "proc-macro2 1.0.36",
+ "quote 1.0.14",
+ "syn 1.0.85",
+]
+
 [[package]]
 [[package]]
 name = "tracing-core"
 name = "tracing-core"
 version = "0.1.21"
 version = "0.1.21"
@@ -5865,6 +6235,256 @@ version = "0.2.78"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
 checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
 
 
+[[package]]
+name = "wasmer"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfc7dff846db3f38f8ed0be4a009fdfeb729cf1f94a2c7fb6ff2fec01cefa110"
+dependencies = [
+ "cfg-if 1.0.0",
+ "indexmap",
+ "js-sys",
+ "loupe",
+ "more-asserts",
+ "target-lexicon",
+ "thiserror",
+ "wasm-bindgen",
+ "wasmer-compiler",
+ "wasmer-compiler-cranelift",
+ "wasmer-derive",
+ "wasmer-engine",
+ "wasmer-engine-dylib",
+ "wasmer-engine-universal",
+ "wasmer-types",
+ "wasmer-vm",
+ "wat",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "wasmer-compiler"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c91abf22b16dad3826ec0d0e3ec0a8304262a6c7a14e16528c536131b80e63d"
+dependencies = [
+ "enumset",
+ "loupe",
+ "rkyv",
+ "serde",
+ "serde_bytes",
+ "smallvec",
+ "target-lexicon",
+ "thiserror",
+ "wasmer-types",
+ "wasmer-vm",
+ "wasmparser",
+]
+
+[[package]]
+name = "wasmer-compiler-cranelift"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7624a1f496b163139a7e0b442426cad805bec70486900287506f9d15a29323ab"
+dependencies = [
+ "cranelift-codegen",
+ "cranelift-entity",
+ "cranelift-frontend",
+ "gimli 0.25.0",
+ "loupe",
+ "more-asserts",
+ "rayon",
+ "smallvec",
+ "target-lexicon",
+ "tracing",
+ "wasmer-compiler",
+ "wasmer-types",
+ "wasmer-vm",
+]
+
+[[package]]
+name = "wasmer-compiler-singlepass"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b63c1538ffb4b0e09edaebfcac35c34141d5944c52f77d137cbe0b634bd40fa"
+dependencies = [
+ "byteorder",
+ "dynasm",
+ "dynasmrt",
+ "lazy_static",
+ "loupe",
+ "more-asserts",
+ "rayon",
+ "smallvec",
+ "wasmer-compiler",
+ "wasmer-types",
+ "wasmer-vm",
+]
+
+[[package]]
+name = "wasmer-derive"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "933b23b5cee0f58aa6c17c6de7e1f3007279357e0d555f22e24d6b395cfe7f89"
+dependencies = [
+ "proc-macro-error",
+ "proc-macro2 1.0.36",
+ "quote 1.0.14",
+ "syn 1.0.85",
+]
+
+[[package]]
+name = "wasmer-engine"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41db0ac4df90610cda8320cfd5abf90c6ec90e298b6fe5a09a81dff718b55640"
+dependencies = [
+ "backtrace",
+ "enumset",
+ "lazy_static",
+ "loupe",
+ "memmap2",
+ "more-asserts",
+ "rustc-demangle",
+ "serde",
+ "serde_bytes",
+ "target-lexicon",
+ "thiserror",
+ "wasmer-compiler",
+ "wasmer-types",
+ "wasmer-vm",
+]
+
+[[package]]
+name = "wasmer-engine-dylib"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "591683f3356ac31cc88aaecaf77ac2cc9f456014348b01af46c164f44f531162"
+dependencies = [
+ "cfg-if 1.0.0",
+ "enum-iterator",
+ "enumset",
+ "leb128",
+ "libloading",
+ "loupe",
+ "object 0.28.3",
+ "rkyv",
+ "serde",
+ "tempfile",
+ "tracing",
+ "wasmer-compiler",
+ "wasmer-engine",
+ "wasmer-object",
+ "wasmer-types",
+ "wasmer-vm",
+ "which",
+]
+
+[[package]]
+name = "wasmer-engine-universal"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dccfde103e9b87427099a6de344b7c791574f307d035c8c7dbbc00974c1af0c1"
+dependencies = [
+ "cfg-if 1.0.0",
+ "enum-iterator",
+ "enumset",
+ "leb128",
+ "loupe",
+ "region",
+ "rkyv",
+ "wasmer-compiler",
+ "wasmer-engine",
+ "wasmer-types",
+ "wasmer-vm",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "wasmer-middlewares"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be816528dd62f037ae935977b643bb4237e10be9e32826e2f3eb1f911eaccc97"
+dependencies = [
+ "loupe",
+ "wasmer",
+ "wasmer-types",
+ "wasmer-vm",
+]
+
+[[package]]
+name = "wasmer-object"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d0c4005592998bd840f2289102ef9c67b6138338ed78e1fc0809586aa229040"
+dependencies = [
+ "object 0.28.3",
+ "thiserror",
+ "wasmer-compiler",
+ "wasmer-types",
+]
+
+[[package]]
+name = "wasmer-types"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4deb854f178265a76b59823c41547d259c65da3687b606b0b9c12d80ab950e3e"
+dependencies = [
+ "indexmap",
+ "loupe",
+ "rkyv",
+ "serde",
+ "thiserror",
+]
+
+[[package]]
+name = "wasmer-vm"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5dbc5c989cb14a102433927e630473da52f83d82c469acd5cfa8fc7efacc1e70"
+dependencies = [
+ "backtrace",
+ "cc",
+ "cfg-if 1.0.0",
+ "enum-iterator",
+ "indexmap",
+ "libc",
+ "loupe",
+ "memoffset 0.6.5",
+ "more-asserts",
+ "region",
+ "rkyv",
+ "serde",
+ "thiserror",
+ "wasmer-types",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "wasmparser"
+version = "0.78.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52144d4c78e5cf8b055ceab8e5fa22814ce4315d6002ad32cfd914f37c12fd65"
+
+[[package]]
+name = "wast"
+version = "39.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e9bbbd53432b267421186feee3e52436531fa69a7cfee9403f5204352df3dd05"
+dependencies = [
+ "leb128",
+ "memchr",
+ "unicode-width",
+]
+
+[[package]]
+name = "wat"
+version = "1.0.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab98ed25494f97c69f28758617f27c3e92e5336040b5c3a14634f2dd3fe61830"
+dependencies = [
+ "wast",
+]
+
 [[package]]
 [[package]]
 name = "web-sys"
 name = "web-sys"
 version = "0.3.55"
 version = "0.3.55"
@@ -5913,6 +6533,18 @@ dependencies = [
  "webpki 0.22.0",
  "webpki 0.22.0",
 ]
 ]
 
 
+[[package]]
+name = "wee_alloc"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e"
+dependencies = [
+ "cfg-if 0.1.10",
+ "libc",
+ "memory_units",
+ "winapi 0.3.9",
+]
+
 [[package]]
 [[package]]
 name = "weezl"
 name = "weezl"
 version = "0.1.5"
 version = "0.1.5"
@@ -5928,6 +6560,17 @@ dependencies = [
  "cc",
  "cc",
 ]
 ]
 
 
+[[package]]
+name = "which"
+version = "4.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a5a7e487e921cf220206864a94a89b6c6905bfc19f1057fa26a4cb360e5c1d2"
+dependencies = [
+ "either",
+ "lazy_static",
+ "libc",
+]
+
 [[package]]
 [[package]]
 name = "winapi"
 name = "winapi"
 version = "0.2.8"
 version = "0.2.8"

+ 25 - 10
Cargo.toml

@@ -25,6 +25,8 @@ members = [
     "bin/taud",
     "bin/taud",
     "bin/tau-cli",
     "bin/tau-cli",
     "bin/vanityaddr",
     "bin/vanityaddr",
+
+    "src/sdk",
 ]
 ]
 
 
 [dependencies]
 [dependencies]
@@ -34,7 +36,7 @@ thiserror = "1.0.30"
 
 
 # async-runtime
 # async-runtime
 smol = {version = "1.2.5", optional = true}
 smol = {version = "1.2.5", optional = true}
-futures = {version = "0.3.19", optional = true}
+futures = {version = "0.3.21", optional = true}
 async-std = {version = "1.10.0", features = ["attributes"], optional = true}
 async-std = {version = "1.10.0", features = ["attributes"], optional = true}
 async-trait = {version = "0.1.52", optional = true}
 async-trait = {version = "0.1.52", optional = true}
 async-channel = {version = "1.6.1", optional = true}
 async-channel = {version = "1.6.1", optional = true}
@@ -51,15 +53,15 @@ toml = {version = "0.5.8", optional = true}
 bytes = {version = "1.1.0", optional = true}
 bytes = {version = "1.1.0", optional = true}
 bincode = {version = "1.3.3", optional = true}
 bincode = {version = "1.3.3", optional = true}
 num-bigint = {version = "0.4.3", optional = true}
 num-bigint = {version = "0.4.3", optional = true}
-serde_json = {version = "1.0.74", optional = true}
-serde = {version = "1.0.133", features = ["derive"], optional = true}
+serde_json = {version = "1.0.79", optional = true}
+serde = {version = "1.0.136", features = ["derive"], optional = true}
 
 
 # Utilities
 # Utilities
 url = {version = "2.2.2", optional = true}
 url = {version = "2.2.2", optional = true}
 dirs = {version = "4.0.0", optional = true}
 dirs = {version = "4.0.0", optional = true}
 subtle = {version = "2.4.1", optional = true}
 subtle = {version = "2.4.1", optional = true}
 lazy_static = {version = "1.4.0", optional = true}
 lazy_static = {version = "1.4.0", optional = true}
-indexmap = {version = "1.7.0", optional = true}
+indexmap = {version = "1.8.0", optional = true}
 itertools = {version = "0.10.3", optional = true}
 itertools = {version = "0.10.3", optional = true}
 
 
 # Misc
 # Misc
@@ -67,8 +69,8 @@ termion = {version = "1.5.6", optional = true}
 simplelog = {version = "0.11.2", optional = true}
 simplelog = {version = "0.11.2", optional = true}
 
 
 # Websockets
 # Websockets
-tungstenite = {version = "0.16.0", optional = true}
-async-tungstenite = {version = "0.16.1", optional = true}
+tungstenite = {version = "0.17.2", optional = true}
+async-tungstenite = {version = "0.17.1", optional = true}
 
 
 # socks5 
 # socks5 
 fast-socks5 = {git = "https://github.com/ghassmo/fast-socks5", optional = true}
 fast-socks5 = {git = "https://github.com/ghassmo/fast-socks5", optional = true}
@@ -86,9 +88,15 @@ incrementalmerkletree = {version = "0.2.0", optional = true}
 halo2_proofs = {git = "https://github.com/zcash/halo2", branch = "main", features = ["dev-graph", "gadget-traces", "sanity-checks"], optional = true}
 halo2_proofs = {git = "https://github.com/zcash/halo2", branch = "main", features = ["dev-graph", "gadget-traces", "sanity-checks"], optional = true}
 halo2_gadgets = {git = "https://github.com/zcash/halo2", branch = "main", features = ["dev-graph", "test-dependencies"], optional = true}
 halo2_gadgets = {git = "https://github.com/zcash/halo2", branch = "main", features = ["dev-graph", "test-dependencies"], optional = true}
 
 
+# Smart contract runtime
+drk-sdk = {path = "src/sdk", optional = true}
+wasmer = {version = "2.2.1", optional = true}
+wasmer-compiler-singlepass = {version = "2.2.1", optional = true}
+wasmer-middlewares = {version = "2.2.1", optional = true}
+
 # Wallet management
 # Wallet management
-sqlx = {version = "0.5.10", features = ["runtime-async-std-native-tls", "sqlite"], optional = true}
-libsqlite3-sys = {version = "0.23.1", features = ["bundled-sqlcipher"],  optional = true }
+sqlx = {version = "0.5.11", features = ["runtime-async-std-native-tls", "sqlite"], optional = true}
+libsqlite3-sys = {version = "0.24.1", features = ["bundled-sqlcipher"],  optional = true }
 
 
 # Node utilities
 # Node utilities
 signal-hook = {version = "0.3.13", optional = true}
 signal-hook = {version = "0.3.13", optional = true}
@@ -111,7 +119,7 @@ optional = true
 
 
 
 
 [dev-dependencies]
 [dev-dependencies]
-clap = {version = "3.0.7", features = ["derive"]}
+clap = {version = "3.1.6", features = ["derive"]}
 
 
 [features]
 [features]
 async-runtime = [
 async-runtime = [
@@ -196,7 +204,14 @@ crypto = [
 
 
 wallet = [
 wallet = [
     "sqlx",
     "sqlx",
-    "libsqlite3-sys"
+    "libsqlite3-sys",
+]
+
+wasm-runtime = [
+    "drk-sdk",
+    "wasmer",
+    "wasmer-compiler-singlepass",
+    "wasmer-middlewares",
 ]
 ]
 
 
 node = [
 node = [

+ 49 - 1
src/error.rs

@@ -1,6 +1,6 @@
 pub type Result<T> = std::result::Result<T, Error>;
 pub type Result<T> = std::result::Result<T, Error>;
 
 
-#[derive(Debug, Clone, thiserror::Error)]
+#[derive(Clone, Debug, thiserror::Error)]
 pub enum Error {
 pub enum Error {
     #[error("io error: `{0:?}`")]
     #[error("io error: `{0:?}`")]
     Io(std::io::ErrorKind),
     Io(std::io::ErrorKind),
@@ -195,6 +195,26 @@ pub enum Error {
 
 
     #[error("Invalid bincode: {0}")]
     #[error("Invalid bincode: {0}")]
     ZkasDecoderError(&'static str),
     ZkasDecoderError(&'static str),
+
+    #[cfg(feature = "wasm-runtime")]
+    #[error("wasm export error: {0}")]
+    WasmerExportError(String),
+
+    #[cfg(feature = "wasm-runtime")]
+    #[error("wasm runtime error: {0}")]
+    WasmerRuntimeError(String),
+
+    #[cfg(feature = "wasm-runtime")]
+    #[error("wasm instantiation error: {0}")]
+    WasmerInstantiationError(String),
+
+    #[cfg(feature = "wasm-runtime")]
+    #[error("wasm compile error: {0}")]
+    WasmerCompileError(String),
+
+    #[cfg(feature = "wasm-runtime")]
+    #[error("wasm runtime out of memory")]
+    WasmerOomError,
 }
 }
 
 
 #[cfg(feature = "node")]
 #[cfg(feature = "node")]
@@ -298,3 +318,31 @@ impl From<halo2_proofs::plonk::Error> for Error {
         Error::PlonkError(err.to_string())
         Error::PlonkError(err.to_string())
     }
     }
 }
 }
+
+#[cfg(feature = "wasm-runtime")]
+impl From<wasmer::CompileError> for Error {
+    fn from(err: wasmer::CompileError) -> Error {
+        Error::WasmerCompileError(err.to_string())
+    }
+}
+
+#[cfg(feature = "wasm-runtime")]
+impl From<wasmer::ExportError> for Error {
+    fn from(err: wasmer::ExportError) -> Error {
+        Error::WasmerExportError(err.to_string())
+    }
+}
+
+#[cfg(feature = "wasm-runtime")]
+impl From<wasmer::RuntimeError> for Error {
+    fn from(err: wasmer::RuntimeError) -> Error {
+        Error::WasmerRuntimeError(err.to_string())
+    }
+}
+
+#[cfg(feature = "wasm-runtime")]
+impl From<wasmer::InstantiationError> for Error {
+    fn from(err: wasmer::InstantiationError) -> Error {
+        Error::WasmerInstantiationError(err.to_string())
+    }
+}

+ 3 - 0
src/lib.rs

@@ -25,6 +25,9 @@ pub mod system;
 #[cfg(feature = "util")]
 #[cfg(feature = "util")]
 pub mod util;
 pub mod util;
 
 
+#[cfg(feature = "wasm-runtime")]
+pub mod runtime;
+
 #[cfg(feature = "rpc")]
 #[cfg(feature = "rpc")]
 pub mod rpc;
 pub mod rpc;
 
 

+ 104 - 0
src/runtime/memory.rs

@@ -0,0 +1,104 @@
+use wasmer::{Array, Memory, WasmPtr};
+
+use crate::{Error, Result};
+
+pub trait MemoryManipulation {
+    fn write(&self, mem_offset: u32, value_slice: &[u8]) -> Result<()>;
+    fn read(&self, mem_offset: u32, value_len: usize) -> Option<&[u8]>;
+}
+
+impl MemoryManipulation for Memory {
+    fn write(&self, mem_offset: u32, value_slice: &[u8]) -> Result<()> {
+        // Prepare WasmPtr
+        let target_ptr: WasmPtr<u8, Array> = WasmPtr::new(mem_offset);
+
+        // Allocate necessary memory space on guest
+        let guest_value_slice = match target_ptr.deref(self, 0, value_slice.len() as u32) {
+            Some(slice) => slice,
+            None => [].to_vec(),
+        };
+
+        if guest_value_slice.is_empty() {
+            return Err(Error::WasmerOomError)
+        }
+
+        // Copy bytes to guest
+        for i in 0..value_slice.len() {
+            guest_value_slice[i].set(value_slice[i]);
+        }
+
+        Ok(())
+    }
+
+    fn read(&self, mem_offset: u32, value_len: usize) -> Option<&[u8]> {
+        let memory_size = self.size().bytes().0;
+
+        if mem_offset as usize + value_len > memory_size || mem_offset as usize >= memory_size {
+            return None
+        }
+
+        let ptr = unsafe { self.view::<u8>().as_ptr().add(mem_offset as usize) as *const u8 };
+        unsafe { Some(std::slice::from_raw_parts(ptr, value_len)) }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use wasmer::{imports, wat2wasm, Instance, Module, Store};
+
+    fn wasmer_instance() -> Instance {
+        let wasm_bytes = wat2wasm(
+                                br#"
+                                            (module
+                                                          (type $add_one_t (func (param i32) (result i32)))
+                                                                        (func $add_one_f (type $add_one_t) (param $value i32) (result i32)
+                                                                                        local.get $value
+                                                                                                        i32.const 1
+                                                                                                                        i32.add)
+                                                                                                                                      (export "add_one" (func $add_one_f))
+                                                                                                                                                    (memory $memory (export "memory") 17))
+                                                                                                                                                                "#,
+                                                                                                                                                                        )
+                                                                                                                                                                                .unwrap();
+
+        let store = Store::default();
+        let module = Module::new(&store, wasm_bytes).unwrap();
+
+        let import_object = imports! {};
+        Instance::new(&module, &import_object).unwrap()
+    }
+
+    #[test]
+    fn can_write_on_memory() {
+        let wasmer_instance = wasmer_instance();
+
+        let memory = wasmer_instance.exports.get_memory("memory").unwrap();
+        let data = String::from("data_test");
+
+        let mem_addr = 0x2220;
+
+        memory.write(mem_addr as u32, data.as_bytes()).unwrap();
+
+        let ptr = unsafe { memory.view::<u8>().as_ptr().add(mem_addr as usize) as *const u8 };
+        let slice_raw = unsafe { std::slice::from_raw_parts(ptr, data.len()) };
+
+        assert_eq!(data.as_bytes(), slice_raw);
+    }
+
+    #[test]
+    fn can_read_from_memory() {
+        let wasmer_instance = wasmer_instance();
+
+        let memory = wasmer_instance.exports.get_memory("memory").unwrap();
+        let data = String::from("data_test");
+
+        let mem_addr = 0x2220;
+
+        memory.write(mem_addr as u32, data.as_bytes()).unwrap();
+
+        let slice_raw = memory.read(mem_addr as u32, data.as_bytes().len()).unwrap();
+
+        assert_eq!(data.as_bytes(), slice_raw);
+    }
+}

+ 3 - 0
src/runtime/mod.rs

@@ -0,0 +1,3 @@
+pub mod memory;
+pub mod runtime;
+pub mod util;

+ 167 - 0
src/runtime/runtime.rs

@@ -0,0 +1,167 @@
+use std::sync::{Arc, Mutex};
+
+use drk_sdk::entrypoint;
+use log::debug;
+use wasmer::{
+    imports, wasmparser::Operator, CompilerConfig, Function, HostEnvInitError, Instance, LazyInit,
+    Memory, Module, Store, Universal, Value, WasmerEnv,
+};
+use wasmer_compiler_singlepass::Singlepass;
+use wasmer_middlewares::{
+    metering::{get_remaining_points, MeteringPoints},
+    Metering,
+};
+
+use super::{memory::MemoryManipulation, util::drk_log};
+use crate::Result;
+
+/// Function name in our wasm module that allows us to allocate some memory.
+const WASM_MEM_ALLOC: &str = "__drkruntime_mem_alloc";
+/// Name of the wasm linear memory in our guest module
+const MEMORY: &str = "memory";
+/// Hardcoded entrypoint function of a contract
+const ENTRYPOINT: &str = "entrypoint";
+/// Gas limit for a contract
+const GAS_LIMIT: u64 = 200000;
+
+#[derive(Clone)]
+pub struct Env {
+    pub logs: Arc<Mutex<Vec<String>>>,
+    pub memory: LazyInit<Memory>,
+}
+
+impl WasmerEnv for Env {
+    fn init_with_instance(
+        &mut self,
+        instance: &Instance,
+    ) -> std::result::Result<(), HostEnvInitError> {
+        let memory: Memory = instance.exports.get_with_generics_weak(MEMORY)?;
+        self.memory.initialize(memory);
+        Ok(())
+    }
+}
+
+pub struct Runtime {
+    pub(crate) instance: Instance,
+    pub(crate) env: Env,
+}
+
+impl Runtime {
+    /// Create a new wasm runtime instance that contains the given wasm module.
+    pub fn new(wasm_bytes: &[u8]) -> Result<Self> {
+        // This function will be called for each `Operator` encountered during
+        // the wasm module execution. It should return the cost of the operator
+        // that it received as its first argument.
+        let cost_function = |operator: &Operator| -> u64 {
+            match operator {
+                Operator::LocalGet { .. } => 1,
+                Operator::I32Const { .. } => 1,
+                Operator::I32Add { .. } => 2,
+                _ => 0,
+            }
+        };
+
+        // `Metering` needs to be conigured with a limit and a cost function.
+        // For each `Operator`, the metering middleware will call the cost
+        // function and subtract the cost from the remaining points.
+        let metering = Arc::new(Metering::new(GAS_LIMIT, cost_function));
+
+        // Define the compiler and middleware, engine, and store
+        let mut compiler = Singlepass::new();
+        compiler.push_middleware(metering);
+        let store = Store::new(&Universal::new(compiler).engine());
+
+        debug!(target: "wasm-runtime", "Compiling module...");
+        let module = Module::new(&store, wasm_bytes)?;
+
+        debug!(target: "wasm-runtime", "Importing functions...");
+        let env = Env { logs: Arc::new(Mutex::new(vec![])), memory: LazyInit::new() };
+        let import_object = imports! {
+            "env" => {
+                "drk_log_" => Function::new_native_with_env(
+                    &store,
+                    env.clone(),
+                    drk_log,
+                ),
+            }
+        };
+
+        debug!(target: "wasm-runtime", "Instantiating module...");
+        let instance = Instance::new(&module, &import_object)?;
+
+        Ok(Self { instance, env })
+    }
+
+    /// Run the hardcoded [ENTRYPOINT] function with the given payload as input.
+    pub fn run(&mut self, payload: &[u8]) -> Result<()> {
+        // Get module linear memory
+        let memory = self.memory()?;
+
+        // Retrieve ptr to pass data
+        let mem_offset = self.guest_mem_alloc(payload.len())?;
+        memory.write(mem_offset, payload)?;
+
+        debug!(target: "wasm-runtime", "Getting entrypoint function...");
+        let entrypoint = self.instance.exports.get_function(ENTRYPOINT)?;
+
+        debug!(target: "wasm-runtime", "Executing wasm...");
+        let ret = match entrypoint.call(&[Value::I32(mem_offset as i32)]) {
+            Ok(v) => {
+                self.print_logs();
+                debug!(target: "wasm-runtime", "{}", self.gas_info());
+                v
+            }
+            Err(e) => {
+                self.print_logs();
+                debug!(target: "wasm-runtime", "{}", self.gas_info());
+                return Err(e.into())
+            }
+        };
+
+        debug!(target: "wasm-runtime", "wasm executed successfully");
+        debug!(target: "wasm-runtime", "Contract returned: {:?}", ret[0]);
+
+        let retval = match ret[0] {
+            Value::I64(v) => v as u64,
+            _ => unreachable!(),
+        };
+
+        match retval {
+            entrypoint::SUCCESS => Ok(()),
+            // _ => Err(ContractError(retval)),
+            _ => todo!(),
+        }
+    }
+
+    fn print_logs(&self) {
+        let logs = self.env.logs.lock().unwrap();
+        for msg in logs.iter() {
+            debug!(target: "wasm-runtime", "Contract log: {}", msg);
+        }
+    }
+
+    fn gas_info(&self) -> String {
+        let remaining_points = get_remaining_points(&self.instance);
+
+        match remaining_points {
+            MeteringPoints::Remaining(rem) => {
+                format!("Gas used: {}/{}", GAS_LIMIT - rem, GAS_LIMIT)
+            }
+            MeteringPoints::Exhausted => {
+                format!("Gas fully exhausted: {}/{}", GAS_LIMIT + 1, GAS_LIMIT)
+            }
+        }
+    }
+
+    /// Allocate some memory space on a wasm linear memory to allow direct rw.
+    fn guest_mem_alloc(&self, size: usize) -> Result<u32> {
+        let mem_alloc = self.instance.exports.get_function(WASM_MEM_ALLOC)?;
+        let res_target_ptr = mem_alloc.call(&[Value::I32(size as i32)])?.to_vec();
+        Ok(res_target_ptr[0].unwrap_i32() as u32)
+    }
+
+    /// Retrieve linear memory from a wasm module and return its reference.
+    fn memory(&self) -> Result<&Memory> {
+        Ok(self.instance.exports.get_memory(MEMORY)?)
+    }
+}

+ 38 - 0
src/runtime/util.rs

@@ -0,0 +1,38 @@
+use log::{error, warn};
+
+use super::{memory::MemoryManipulation, runtime::Env};
+
+/// Serialize contract payload to format accepted by the runtime entrypoint.
+/// We keep the same payload as a slice of bytes, and prepend it with a
+/// little-endian u64 to tell the payload's length.
+pub fn serialize_payload(payload: &[u8]) -> Vec<u8> {
+    let mut out = vec![];
+
+    let len = payload.len() as u64;
+    out.extend_from_slice(&len.to_le_bytes());
+    out.extend_from_slice(payload);
+
+    out
+}
+
+/// Host function for logging strings.
+/// This is injected into the runtime with wasmer's `imports!` macro.
+pub(crate) fn drk_log(env: &Env, ptr: u32, len: u32) {
+    if let Some(bytes) = env.memory.get_ref().unwrap().read(ptr, len as usize) {
+        // Piece the string together
+        let msg = match String::from_utf8(bytes.to_vec()) {
+            Ok(v) => v,
+            Err(e) => {
+                warn!(target: "wasm-runtime", "Invalid UTF-8 string: {:?}", e);
+                return
+            }
+        };
+
+        let mut logs = env.logs.lock().unwrap();
+        logs.push(msg);
+        std::mem::drop(logs);
+        return
+    }
+
+    error!(target: "wasm-runtime", "Failed to read any bytes from VM memory");
+}

+ 9 - 0
src/sdk/Cargo.toml

@@ -0,0 +1,9 @@
+[package]
+name = "drk-sdk"
+version = "0.3.0"
+edition = "2021"
+
+[dependencies]
+borsh = "0.9.3"
+thiserror = "1.0.30"
+wee_alloc = "0.4.5"

+ 60 - 0
src/sdk/src/entrypoint.rs

@@ -0,0 +1,60 @@
+use std::{mem::size_of, slice::from_raw_parts};
+
+/// Success exit code for a contract
+pub const SUCCESS: u64 = 0;
+
+/// This macro is used to flag the contract entrypoint function.
+/// All contracts must provide such a function and accept a payload.
+///
+/// The payload is a slice of u8 prepended with a little-endian u64
+/// that tells the slice's length.
+#[macro_export]
+macro_rules! entrypoint {
+    ($process_instruction:ident) => {
+        /// # Safety
+        #[no_mangle]
+        pub unsafe extern "C" fn entrypoint(input: *mut u8) -> u64 {
+            let instruction_data = $crate::entrypoint::deserialize(input);
+
+            match $process_instruction(&instruction_data) {
+                Ok(()) => $crate::entrypoint::SUCCESS,
+                Err(e) => e.into(),
+            }
+        }
+    };
+}
+
+/// Deserialize a given payload in `entrypoint`
+/// # Safety
+pub unsafe fn deserialize<'a>(input: *mut u8) -> &'a [u8] {
+    let mut offset: usize = 0;
+
+    let instruction_data_len = *(input.add(offset) as *const u64) as usize;
+    offset += size_of::<u64>();
+
+    let instruction_data = { from_raw_parts(input.add(offset), instruction_data_len) };
+
+    instruction_data
+}
+
+/// Allocate a piece of memory in the wasm VM
+#[no_mangle]
+#[cfg(target_arch = "wasm32")]
+extern "C" fn __drkruntime_mem_alloc(size: usize) -> *mut u8 {
+    let align = std::mem::align_of::<usize>();
+
+    if let Ok(layout) = std::alloc::Layout::from_size_align(size, align) {
+        unsafe {
+            if layout.size() > 0 {
+                let ptr = std::alloc::alloc(layout);
+                if !ptr.is_null() {
+                    return ptr
+                }
+            } else {
+                return align as *mut u8
+            }
+        }
+    }
+
+    std::process::abort();
+}

+ 64 - 0
src/sdk/src/error.rs

@@ -0,0 +1,64 @@
+use borsh::maybestd::io::Error as BorshIoError;
+use std::result::Result as ResultGeneric;
+
+pub type ContractResult = ResultGeneric<(), ContractError>;
+
+#[derive(Debug, thiserror::Error)]
+pub enum ContractError {
+    /// Allows on-chain programs to implement contract-specific error types and
+    /// see them returned by the runtime. A contract-specific error may be any
+    /// type that is represented as or serialized to an u32 integer.
+    #[error("Custom contract error: {0:#x}")]
+    Custom(u32),
+
+    #[error("Internal error")]
+    Internal,
+
+    #[error("IO error: {0}")]
+    BorshIoError(String),
+}
+
+/// Builtin return values occupy the upper 32 bits
+const BUILTIN_BIT_SHIFT: usize = 32;
+macro_rules! to_builtin {
+    ($error:expr) => {
+        ($error as u64) << BUILTIN_BIT_SHIFT
+    };
+}
+
+pub const CUSTOM_ZERO: u64 = to_builtin!(1);
+pub const INTERNAL_ERROR: u64 = to_builtin!(2);
+pub const BORSH_IO_ERROR: u64 = to_builtin!(3);
+
+impl From<ContractError> for u64 {
+    fn from(err: ContractError) -> Self {
+        match err {
+            ContractError::Internal => INTERNAL_ERROR,
+            ContractError::BorshIoError(_) => BORSH_IO_ERROR,
+            ContractError::Custom(error) => {
+                if error == 0 {
+                    CUSTOM_ZERO
+                } else {
+                    error as u64
+                }
+            }
+        }
+    }
+}
+
+impl From<u64> for ContractError {
+    fn from(error: u64) -> Self {
+        match error {
+            CUSTOM_ZERO => Self::Custom(0),
+            INTERNAL_ERROR => Self::Internal,
+            BORSH_IO_ERROR => Self::BorshIoError("Unknown".to_string()),
+            _ => Self::Custom(error as u32),
+        }
+    }
+}
+
+impl From<BorshIoError> for ContractError {
+    fn from(error: BorshIoError) -> Self {
+        Self::BorshIoError(format!("{}", error))
+    }
+}

+ 8 - 0
src/sdk/src/lib.rs

@@ -0,0 +1,8 @@
+pub mod entrypoint;
+pub mod error;
+pub mod log;
+
+// Set up global allocator by default
+#[cfg(target_arch = "wasm32")]
+#[global_allocator]
+static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;

+ 24 - 0
src/sdk/src/log.rs

@@ -0,0 +1,24 @@
+/// Print a message to the log
+#[macro_export]
+macro_rules! msg {
+    ($msg:expr) => {
+        $crate::log::drk_log($msg)
+    };
+    ($($arg:tt)*) => ($crate::log::drk_log(&format!($($arg)*)));
+}
+
+#[inline]
+pub fn drk_log(message: &str) {
+    #[cfg(target_arch = "wasm32")]
+    unsafe {
+        drk_log_(message.as_ptr(), message.len());
+    }
+
+    #[cfg(not(target_arch = "wasm32"))]
+    println!("{}", message);
+}
+
+#[cfg(target_arch = "wasm32")]
+extern "C" {
+    fn drk_log_(ptr: *const u8, len: usize);
+}