├── AUTHORS ├── NEWS ├── README ├── ChangeLog ├── metering ├── .gitignore ├── cmd │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── inject_metering │ └── Cargo.toml ├── Cargo.toml └── Cargo.lock ├── pedersen ├── .gitignore ├── commitments │ └── Cargo.toml └── Cargo.toml ├── wasm_libs ├── .gitignore └── install_gmp.sh ├── wasm_ed25519 ├── .gitignore └── Makefile ├── cpp_contracts ├── .gitignore ├── sdk │ ├── syscall.h │ ├── macros.h │ ├── types.h │ ├── general_storage.h │ ├── delete.h │ ├── flag.h │ ├── contracts.h │ ├── concepts.h │ ├── witness.h │ ├── constexpr.h │ ├── shared.h │ ├── auth_singlekey.h │ ├── semaphore.h │ ├── log.h │ ├── asset.h │ ├── calldata.h │ ├── replay_cache.h │ ├── auth_singlekey_wasmed25519.h │ ├── rpc.h │ ├── raw_memory.h │ ├── crypto.h │ ├── nonnegative_int64.h │ └── hashset.h ├── genesis │ ├── addresses.h │ ├── deploy.cc │ └── deploy.h ├── test_hashset.cc ├── test_gas_limit.cc ├── test_nn_int64.cc ├── test_redirect_call.cc ├── test_rpc.cc ├── test_sdk.cc ├── test_log.cc ├── payment_experiment │ ├── payment.cc │ └── payment_wasmsig.cc └── erc721.h ├── autogen.sh ├── wasi ├── .gitignore ├── linux_install.sh ├── mac_install.sh ├── SETUP.md └── wasi_install.sh ├── dedup.sh ├── main ├── simple.cc ├── basic.cc └── test.cc ├── rocksdb_install.md ├── pedersen_ffi ├── pedersen.h └── pedersen.cc ├── disable_hyperthreading.sh ├── contract_db ├── runnable_script.h ├── contract_utils.h ├── uncommitted_contracts.h ├── contract_utils.cc └── uncommitted_contracts.cc ├── notes ├── use-cases.txt └── replay-mechanisms.txt ├── .gitignore ├── .gitmodules ├── config ├── print_configs.h ├── static_constants.h └── print_configs.cc ├── utils ├── defer.h ├── make_calldata.h ├── load_wasm.h ├── atomic_singleton.h ├── atomic_uint128.h └── recycling_allocator.h ├── object ├── comparators.h ├── object_defaults.h ├── comparators.cc ├── make_delta.h ├── object_defaults.cc └── make_delta.cc ├── rpc_server ├── mock_external_call.h ├── echo_server.h ├── server_runner.h └── server_runner.cc ├── state_db ├── optional_value_wrapper.h ├── modified_keys_list.h ├── modified_keys_list.cc ├── state_db_v2.h └── typed_modification_index.h ├── persistence ├── rocksdb_wrapper.h ├── rocksdb_wrapper.cc ├── rocksdb_iface.h ├── accumulate_kvs_iface.h └── async_rdb_bulkload.h ├── proto └── external_call.proto ├── xdr ├── rpc.x ├── block.x ├── types.x ├── transaction.x └── storage.x ├── transaction_context ├── error.h ├── method_invocation.h ├── transaction_results.h ├── method_invocation.cc └── transaction_results.cc ├── vm ├── genesis.h ├── genesis.cc ├── groundhog_vm.h ├── base_vm.h └── vm.h ├── storage_proxy ├── storage_proxy_value.h ├── transaction_rewind.h └── storage_proxy.h ├── test_utils ├── deploy_and_commit_contractdb.h ├── deploy_and_commit_contractdb.cc └── utils.h ├── .github └── workflows │ └── cpp.yml ├── common └── syscall_nos.h ├── rpc ├── rpc_address_db.h └── rpc_address_db.cc ├── threadlocal ├── uid.h ├── cancellable_rpc.h ├── threadlocal_context.cc ├── gc.h └── rate_limiter.h ├── ansible └── aws_install_packages.yaml ├── debug ├── debug_utils.h └── debug_macros.h ├── mempool ├── mempool.h └── mempool.cc ├── crypto ├── crypto_utils.h └── hash.h ├── phase └── phases.h ├── metering_ffi ├── metered_contract.h └── metered_contract.cc ├── hash_set ├── atomic_set.h └── utils.h ├── block_assembly ├── limits.cc └── limits.h ├── tx_block ├── tests │ └── test_unique_txset.cc └── unique_tx_set.h ├── sisyphus_vm └── vm.h └── experiments └── payment_experiment.h /AUTHORS: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /metering/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | -------------------------------------------------------------------------------- /pedersen/.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | -------------------------------------------------------------------------------- /wasm_libs/.gitignore: -------------------------------------------------------------------------------- 1 | libs/* 2 | -------------------------------------------------------------------------------- /wasm_ed25519/.gitignore: -------------------------------------------------------------------------------- 1 | libed25519.a 2 | -------------------------------------------------------------------------------- /cpp_contracts/.gitignore: -------------------------------------------------------------------------------- 1 | *.wasm 2 | *.wat 3 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec autoreconf -i -Wno-portability 3 | -------------------------------------------------------------------------------- /wasi/.gitignore: -------------------------------------------------------------------------------- 1 | wasi-sdk/* 2 | wasi-sysroot/* 3 | *.gz 4 | lib/* 5 | -------------------------------------------------------------------------------- /dedup.sh: -------------------------------------------------------------------------------- 1 | 2 | IFS= read -r line 3 | 4 | strarray=($line) 5 | 6 | for i in ${strarray[@]} 7 | do 8 | echo $i 9 | done -------------------------------------------------------------------------------- /main/simple.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | int main(int argc, char** argv) 5 | { 6 | std::printf("foo\n"); 7 | } 8 | -------------------------------------------------------------------------------- /main/basic.cc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #include 5 | 6 | int main(int argc, const char** argv) 7 | { 8 | std::printf("run a program!"); 9 | } 10 | -------------------------------------------------------------------------------- /main/test.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char** argv) 4 | { 5 | int result = Catch::Session().run(argc, argv); 6 | return result; 7 | } 8 | -------------------------------------------------------------------------------- /wasi/linux_install.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | curl -LO "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0-linux.tar.gz" 3 | tar -xf wasi-sdk-20.0-linux.tar.gz 4 | mv wasi-sdk-20.0 wasi-sdk 5 | -------------------------------------------------------------------------------- /wasi/mac_install.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | curl -LO "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0-macos.tar.gz" 3 | tar -xf wasi-sdk-20.0-macos.tar.gz 4 | mv wasi-sdk-20.0 wasi-sdk 5 | 6 | -------------------------------------------------------------------------------- /rocksdb_install.md: -------------------------------------------------------------------------------- 1 | RocksDB relies on a bunch of compression libraries. Install those first before building (prior to building rocksdb) 2 | 3 | Install process is 4 | `sudo make shared_lib install-shared` 5 | 6 | 7 | -------------------------------------------------------------------------------- /metering/cmd/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cmd" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | inject_metering = {path = "../inject_metering"} 8 | 9 | [[bin]] 10 | name = "metering_cmd" 11 | path = "src/main.rs" -------------------------------------------------------------------------------- /metering/inject_metering/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "inject_metering" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | wasm-instrument = "0.3.0" 8 | parity-wasm = "0.45.0" 9 | 10 | [lib] 11 | crate-type = ["cdylib", "staticlib", "rlib"] -------------------------------------------------------------------------------- /pedersen_ffi/pedersen.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "xdr/types.h" 4 | 5 | namespace scs 6 | { 7 | 8 | void init_pedersen(); 9 | 10 | 11 | std::array 12 | pedersen_commitment(unsigned __int128 value, Hash const& blinding); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /pedersen/commitments/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "commitments" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | curve25519-dalek = "2" 8 | sha3 = { version = "0.8", default-features = false } 9 | 10 | [lib] 11 | crate-type = ["cdylib", "staticlib", "rlib"] -------------------------------------------------------------------------------- /disable_hyperthreading.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | for cpunum in $(cat /sys/devices/system/cpu/cpu*/topology/thread_siblings_list | cut -s -d, -f2- | tr ',' '\n' | sort -un) 4 | do 5 | #echo /sys/devices/system/cpy/cpu$cpunum/online 6 | echo 0 > /sys/devices/system/cpu/cpu$cpunum/online 7 | done 8 | -------------------------------------------------------------------------------- /wasi/SETUP.md: -------------------------------------------------------------------------------- 1 | To install the version of clang with wasm supported: 2 | 3 | 1. Install a copy of wasi-sdk-* under wasi/ 4 | 5 | 2. Rename that folder to wasi-sdk/ 6 | 7 | In the future, clang might ship with this wasi built in, or 8 | you could adjust Makefile.am to point to a different install location. 9 | 10 | -------------------------------------------------------------------------------- /wasi/wasi_install.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sysroot-20.0.tar.gz 3 | tar -xf wasi-sysroot-20.0.tar.gz 4 | wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/libclang_rt.builtins-wasm32-wasi-20.0.tar.gz 5 | tar -xf libclang_rt.builtins-wasm32-wasi-20.0.tar.gz 6 | -------------------------------------------------------------------------------- /metering/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | 3 | members = [ 4 | "inject_metering", 5 | "cmd", 6 | ] 7 | 8 | [profile.dev] 9 | opt-level = 0 10 | overflow-checks = false 11 | debug = 0 12 | strip = "debuginfo" 13 | 14 | [profile.release] 15 | lto=true 16 | opt-level = 3 17 | overflow-checks = false 18 | debug = 0 19 | strip = "symbols" 20 | debug-assertions = false -------------------------------------------------------------------------------- /pedersen/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | 4 | members = [ 5 | "commitments", 6 | ] 7 | 8 | [profile.dev] 9 | opt-level = 0 10 | overflow-checks = false 11 | debug = 0 12 | strip = "debuginfo" 13 | 14 | [profile.release] 15 | lto=true 16 | opt-level = 3 17 | overflow-checks = false 18 | debug = 0 19 | strip = "symbols" 20 | debug-assertions = false -------------------------------------------------------------------------------- /contract_db/runnable_script.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace scs { 6 | 7 | struct RunnableScriptView 8 | { 9 | const uint8_t* data; 10 | uint32_t len; 11 | 12 | operator bool() { return data != nullptr; } 13 | }; 14 | 15 | constexpr static RunnableScriptView null_script{ .data = nullptr, .len = 0 }; 16 | 17 | } // namespace scs 18 | 19 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/syscall.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "sdk/macros.h" 6 | #include "../common/syscall_nos.h" 7 | 8 | namespace sdk 9 | { 10 | 11 | namespace detail 12 | { 13 | 14 | BUILTIN("syscall") 15 | uint64_t 16 | builtin_syscall( 17 | uint64_t callno, 18 | uint64_t arg0, 19 | uint64_t arg1, 20 | uint64_t arg2, 21 | uint64_t arg3, 22 | uint64_t arg4, 23 | uint64_t arg5); 24 | 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /notes/use-cases.txt: -------------------------------------------------------------------------------- 1 | 2 | * Replay prevention 3 | * Ratchet (e.g., for payment channel) 4 | * Relative timelock (payment channels) 5 | - async calls schedule tx to run automatically N blocks/time 6 | in the future, unless someone objects/disables it 7 | * Atomic swap 8 | * Auctions 9 | * Liquidation events (auctioning collateral) 10 | * Sidechain / SPEEDEX 11 | * Atomic swap 12 | * Mutual exclusion / semaphore 13 | Many people try something, it only happens once (or N times) 14 | * Multipart transactions (Tx1 only happens if Tx2 did) 15 | * Control how much banks can lever their base money 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | aclocal.m4 2 | autom4te.cache/ 3 | missing 4 | configure 5 | install-sh 6 | config.h.in 7 | config.h 8 | Makefile.in 9 | Makefile 10 | config.log 11 | config.status 12 | stamp-h1 13 | *.so 14 | build/ 15 | *.o 16 | doc/ 17 | *.deps 18 | *.dirstamp 19 | depcomp 20 | test_runner.cc 21 | ylwrap 22 | test-driver 23 | ar-lib 24 | compile 25 | 26 | xdr/*.h 27 | 28 | proto/*.pb.cc 29 | proto/*.pb.h 30 | 31 | #binaries 32 | basic 33 | test 34 | blockstm_comparison 35 | sisyphus_payment_sim 36 | 37 | #mac 38 | .DS_STORE 39 | *~ 40 | **/.DS_STORE 41 | 42 | #lldb 43 | *.dSYM/* 44 | 45 | #test wasm 46 | */tests/wat/*.wasm 47 | -------------------------------------------------------------------------------- /wasm_libs/install_gmp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | basedir=$(git rev-parse --show-toplevel) 6 | 7 | export RANLIB="${basedir}/wasi/wasi-sdk/bin/ranlib" 8 | export AR="${basedir}/wasi/wasi-sdk/bin/ar" 9 | 10 | cd ${basedir}/wasm_libs/srcs/gmp-wasm/ 11 | 12 | pwd 13 | 14 | ./configure \ 15 | --prefix=${basedir}/wasm_libs/libs/gmp/ \ 16 | CC="${basedir}/wasi/wasi-sdk/bin/clang --sysroot="${basedir}"/wasi/wasi-sdk/share/wasi-sysroot" \ 17 | --host=wasm32-wasi \ 18 | --enable-alloca=alloca \ 19 | ABI=longlong \ 20 | CFLAGS="-O3" 21 | 22 | make -j 8 23 | 24 | which ranlib 25 | 26 | make install 27 | 28 | 29 | -------------------------------------------------------------------------------- /wasm_ed25519/Makefile: -------------------------------------------------------------------------------- 1 | 2 | .c.o: Makefile 3 | clang -O3 --target=wasm32-unknown-wasi -c $< -o $@ \ 4 | --sysroot=../wasi/wasi-sysroot \ 5 | -nostdlib \ 6 | -fno-exceptions 7 | 8 | libed25519.a: ed25519/src/add_scalar.o ed25519/src/fe.o ed25519/src/ge.o ed25519/src/key_exchange.o ed25519/src/keypair.o ed25519/src/sc.o ed25519/src/sha512.o ed25519/src/sign.o ed25519/src/verify.o 9 | llvm-ar rcs libed25519.a \ 10 | ed25519/src/add_scalar.o \ 11 | ed25519/src/fe.o \ 12 | ed25519/src/ge.o \ 13 | ed25519/src/key_exchange.o \ 14 | ed25519/src/keypair.o \ 15 | ed25519/src/sc.o \ 16 | ed25519/src/sha512.o \ 17 | ed25519/src/sign.o \ 18 | ed25519/src/verify.o 19 | llvm-ranlib libed25519.a 20 | 21 | clean: 22 | rm ed25519/src/*.o 23 | rm libed25519.a 24 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "xdrpp"] 2 | path = lib/xdrpp 3 | url = https://github.com/gramseyer/xdrpp.git 4 | [submodule "merkle_trie_toolkit"] 5 | path = lib/merkle_trie_toolkit 6 | url = https://github.com/gramseyer/merkle_trie_toolkit.git 7 | [submodule "wasm_api"] 8 | path = lib/wasm_api 9 | url = https://github.com/gramseyer/wasm_api.git 10 | [submodule "m4"] 11 | path = m4 12 | url = https://github.com/gramseyer/m4.git 13 | [submodule "lib/utility"] 14 | path = lib/utility 15 | url = https://github.com/gramseyer/utility.git 16 | [submodule "wasm_libs/srcs/gmp-wasm"] 17 | path = wasm_libs/srcs/gmp-wasm 18 | url = https://github.com/gramseyer/gmp-wasm.git 19 | [submodule "wasm_ed25519/ed25519"] 20 | path = wasm_ed25519/ed25519 21 | url = https://github.com/gramseyer/ed25519.git 22 | -------------------------------------------------------------------------------- /config/print_configs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | namespace scs { 20 | 21 | void __attribute__((constructor)) print_configs(); 22 | 23 | } -------------------------------------------------------------------------------- /utils/defer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | namespace scs { 20 | 21 | template 22 | struct defer 23 | { 24 | lambda_t obj; 25 | 26 | ~defer() { obj(); } 27 | }; 28 | 29 | } // namespace scs -------------------------------------------------------------------------------- /metering/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "cmd" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "inject_metering", 10 | ] 11 | 12 | [[package]] 13 | name = "inject_metering" 14 | version = "0.1.0" 15 | dependencies = [ 16 | "parity-wasm", 17 | "wasm-instrument", 18 | ] 19 | 20 | [[package]] 21 | name = "parity-wasm" 22 | version = "0.45.0" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" 25 | 26 | [[package]] 27 | name = "wasm-instrument" 28 | version = "0.3.0" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "aa1dafb3e60065305741e83db35c6c2584bb3725b692b5b66148a38d72ace6cd" 31 | dependencies = [ 32 | "parity-wasm", 33 | ] 34 | -------------------------------------------------------------------------------- /cpp_contracts/genesis/addresses.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/types.h" 20 | #include "sdk/constexpr.h" 21 | 22 | namespace genesis 23 | { 24 | 25 | constexpr static sdk::Address DEPLOY_ADDRESS = sdk::make_static_address(0); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /object/comparators.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | 21 | namespace scs 22 | { 23 | 24 | struct HashSetEntry; 25 | 26 | std::strong_ordering 27 | operator<=>(const HashSetEntry& d1, const HashSetEntry& d2); 28 | 29 | } // namespace scs 30 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/macros.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #define MODULE __attribute((import_module("scs"))) 20 | #define NAME(x) __attribute((import_name(x))) 21 | 22 | #define BUILTIN(x) MODULE NAME(x) 23 | 24 | #define EXPORT(name) void __attribute((export_name(name))) 25 | 26 | -------------------------------------------------------------------------------- /rpc_server/mock_external_call.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "config.h" 20 | 21 | #if USE_RPC 22 | #error "should not include mock if rpcs enabled" 23 | #endif 24 | 25 | namespace scs { 26 | struct ExternalCall 27 | { 28 | struct Service 29 | {}; 30 | }; 31 | } // namespace scs 32 | -------------------------------------------------------------------------------- /state_db/optional_value_wrapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "object/revertable_object.h" 4 | #include "xdr/storage.h" 5 | 6 | #include "mtt/memcached_snapshot_trie/durable_interface.h" 7 | 8 | #include 9 | 10 | namespace scs { 11 | 12 | class OptionalValueWrapper : public RevertableObject 13 | { 14 | using slice_t = trie::DurableValueSlice; 15 | 16 | static StorageObject from_slice(const slice_t& slice) 17 | { 18 | throw std::runtime_error("unimplemented"); 19 | } 20 | 21 | public: 22 | using RevertableObject::RevertableObject; 23 | 24 | OptionalValueWrapper(slice_t const& slice) 25 | : RevertableObject(from_slice(slice)) 26 | {} 27 | 28 | void copy_data(std::vector& buf) const 29 | { 30 | auto const& res = get_committed_object(); 31 | if (res) { 32 | xdr::append_xdr_to_opaque(buf, *res); 33 | } 34 | } 35 | }; 36 | 37 | } // namespace scs 38 | -------------------------------------------------------------------------------- /persistence/rocksdb_wrapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "rocksdb/db.h" 4 | 5 | #include 6 | 7 | namespace scs { 8 | 9 | class RocksdbWrapper 10 | { 11 | const std::string dbdir; 12 | 13 | rocksdb::DB* db = nullptr; 14 | 15 | void open_guard() const 16 | { 17 | if (db == nullptr) { 18 | throw std::runtime_error("db not open"); 19 | } 20 | } 21 | 22 | const rocksdb::ReadOptions read_options; 23 | const rocksdb::WriteOptions write_options; 24 | 25 | public: 26 | RocksdbWrapper(const std::string dbdir) 27 | : dbdir(dbdir + "/") 28 | { 29 | } 30 | 31 | void open(); 32 | void clear_previous(); 33 | ~RocksdbWrapper(); 34 | 35 | void put(rocksdb::Slice const& key_slice, 36 | rocksdb::Slice const& value_slice); 37 | void get(rocksdb::Slice const& key_slice, std::string& value_out); 38 | }; 39 | 40 | } // namespace scs 41 | -------------------------------------------------------------------------------- /object/object_defaults.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "xdr/storage_delta.h" 20 | #include "xdr/storage.h" 21 | 22 | #include 23 | 24 | namespace scs 25 | { 26 | 27 | StorageObject 28 | object_from_delta_class(StorageDeltaClass const& d, std::optional const& prev_object); 29 | 30 | } // namespace scs 31 | -------------------------------------------------------------------------------- /proto/external_call.proto: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | syntax = "proto3"; 18 | 19 | package scs; 20 | 21 | service ExternalCall { 22 | rpc SendCall (GRpcCall) returns (GRpcResult) {}; 23 | } 24 | 25 | // The request message containing the user's name. 26 | message GRpcCall { 27 | bytes call = 1; 28 | } 29 | 30 | message GRpcResult { 31 | bytes result = 1; 32 | } 33 | -------------------------------------------------------------------------------- /xdr/rpc.x: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | %#include "xdr/types.h" 18 | 19 | namespace scs 20 | { 21 | 22 | struct RpcCall 23 | { 24 | Hash target; 25 | opaque calldata<>; 26 | }; 27 | 28 | struct RpcResult 29 | { 30 | opaque result<>; 31 | }; 32 | 33 | program ContractRPC { 34 | version ContractRPCV1 { 35 | RpcResult execute_call(RpcCall) = 1; 36 | } = 1; 37 | } = 0x11111111; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /transaction_context/error.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2024 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | namespace scs 23 | { 24 | 25 | // calls to builtin fns from the sandbox should 26 | // throw HostError 27 | struct HostError : public wasm_api::HostError 28 | { 29 | using wasm_api::HostError::HostError; 30 | }; 31 | 32 | } /* scs */ 33 | -------------------------------------------------------------------------------- /vm/genesis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "xdr/types.h" 20 | #include 21 | 22 | namespace scs 23 | { 24 | 25 | class ContractDB; 26 | 27 | Address make_address(uint64_t a, uint64_t b, uint64_t c, uint64_t d); 28 | 29 | const static Address 30 | DEPLOYER_ADDRESS = make_address(0, 0, 0, 0); 31 | 32 | void 33 | install_genesis_contracts(ContractDB& contract_db); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /contract_db/contract_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | 21 | #include "xdr/types.h" 22 | 23 | namespace scs 24 | { 25 | 26 | Address 27 | compute_contract_deploy_address( 28 | Address const& deployer_address, 29 | Hash const& hash, 30 | uint64_t nonce); 31 | 32 | InvariantKey make_static_key( 33 | uint64_t a, 34 | uint64_t b = 0, 35 | uint64_t c = 0, 36 | uint64_t d = 0); 37 | 38 | } -------------------------------------------------------------------------------- /cpp_contracts/sdk/types.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include 20 | #include 21 | 22 | namespace sdk 23 | { 24 | 25 | typedef std::array Address; 26 | typedef std::array StorageKey; 27 | typedef std::array Hash; 28 | typedef std::array PublicKey; 29 | typedef std::array Signature; 30 | 31 | struct EmptyStruct {}; 32 | 33 | } /* sdk */ 34 | -------------------------------------------------------------------------------- /xdr/block.x: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | %#include "xdr/types.h" 18 | %#include "xdr/transaction.h" 19 | 20 | namespace scs 21 | { 22 | 23 | struct Block 24 | { 25 | TxSetEntry transactions<>; 26 | }; 27 | 28 | struct BlockHeader 29 | { 30 | uint64 block_number; 31 | Hash prev_header_hash; 32 | 33 | Hash tx_set_hash; 34 | Hash modified_keys_hash; 35 | Hash state_db_hash; 36 | Hash contract_db_hash; 37 | }; 38 | 39 | } /* namespace scs */ 40 | -------------------------------------------------------------------------------- /object/comparators.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "object/comparators.h" 18 | 19 | #include "xdr/storage.h" 20 | 21 | namespace scs 22 | { 23 | 24 | std::strong_ordering 25 | operator<=>(const HashSetEntry& d1, const HashSetEntry& d2) 26 | { 27 | auto res = d1.index <=> d2.index; 28 | if (res != std::strong_ordering::equal) 29 | { 30 | return res; 31 | } 32 | 33 | return d1.hash <=> d2.hash; 34 | } 35 | 36 | 37 | } // namespace scs 38 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/general_storage.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/macros.h" 20 | #include "sdk/alloc.h" 21 | #include "sdk/types.h" 22 | #include "sdk/concepts.h" 23 | 24 | #include 25 | #include 26 | 27 | namespace sdk 28 | { 29 | 30 | bool 31 | has_key(const StorageKey& key) 32 | { 33 | return detail::builtin_syscall(SYSCALLS::HAS_KEY, 34 | to_offset(&key), 0, 0, 0, 0, 0) != 0; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /storage_proxy/storage_proxy_value.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "storage_proxy/proxy_applicator.h" 20 | 21 | #include "xdr/storage_delta.h" 22 | 23 | namespace scs 24 | { 25 | 26 | // writes generated by one tx on one key 27 | struct StorageProxyValue 28 | { 29 | ProxyApplicator applicator; 30 | 31 | StorageProxyValue(std::optional const& obj) 32 | : applicator(obj) 33 | {} 34 | }; 35 | 36 | } /* scs */ 37 | -------------------------------------------------------------------------------- /test_utils/deploy_and_commit_contractdb.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "xdr/types.h" 20 | 21 | #include 22 | 23 | namespace scs { 24 | 25 | class ContractDB; 26 | 27 | namespace test { 28 | 29 | void 30 | deploy_and_commit_contractdb(ContractDB& contract_db, 31 | const Address& addr, 32 | std::shared_ptr contract); 33 | 34 | } 35 | } // namespace scs -------------------------------------------------------------------------------- /.github/workflows/cpp.yml: -------------------------------------------------------------------------------- 1 | name: C++ CI 2 | 3 | on: workflow_dispatch 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v4 12 | with: 13 | submodules: "recursive" 14 | - name: install packages 15 | run: sudo apt-get install -y git g++-13 autoconf libtool pkg-config libsodium-dev liblmdb-dev libgmp-dev libtbb-dev wabt 16 | - name: install libfyaml 17 | run: git clone https://github.com/pantoniou/libfyaml.git && cd libfyaml && ./bootstrap.sh && ./configure && make -j && sudo make install 18 | - name: install catch2 19 | run: git clone https://github.com/catchorg/Catch2.git && cd Catch2 && cmake -Bbuild -H. -DBUILD_TESTING=OFF && sudo cmake --build build/ --target install -j 20 | - name: autogen 21 | run: ./autogen.sh 22 | - name: configure 23 | run: ./configure 24 | - name: install wasi 25 | run: cd wasi && ./linux_install.sh 26 | - name: make 27 | run: make 28 | - name: make test -j 29 | run: make test 30 | - name: run tests 31 | run: ./test 32 | 33 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/delete.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/concepts.h" 20 | #include "sdk/alloc.h" 21 | #include "sdk/types.h" 22 | #include "sdk/concepts.h" 23 | #include "sdk/syscall.h" 24 | 25 | #include 26 | #include 27 | 28 | namespace sdk 29 | { 30 | 31 | void delete_last(StorageKey const& key) 32 | { 33 | detail::builtin_syscall(SYSCALLS::DELETE_KEY_LAST, 34 | to_offset(&key), 35 | 0, 0, 0, 0, 0); 36 | } 37 | 38 | } /* sdk */ 39 | -------------------------------------------------------------------------------- /config/static_constants.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | 21 | namespace scs 22 | { 23 | 24 | // must be greater than # of threads created in one run 25 | constexpr static uint32_t TLCACHE_SIZE = 512; 26 | constexpr static uint32_t TLCACHE_BITS_REQUIRED = 9; // 512 = 2^9 27 | 28 | static_assert (static_cast(1) << TLCACHE_BITS_REQUIRED == TLCACHE_SIZE, "mismatch"); 29 | 30 | constexpr static bool PERSISTENT_STORAGE_ENABLED = true; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /cpp_contracts/test_hashset.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "sdk/hashset.h" 18 | #include "sdk/calldata.h" 19 | #include "sdk/invoke.h" 20 | #include "sdk/crypto.h" 21 | 22 | struct calldata_0 23 | { 24 | sdk::StorageKey key; 25 | uint64_t value; 26 | }; 27 | 28 | EXPORT("pub00000000") 29 | hashset_insert() 30 | { 31 | auto calldata = sdk::get_calldata(); 32 | auto hash = sdk::hash(reinterpret_cast(&(calldata.value)), sizeof(uint64_t)); 33 | 34 | sdk::hashset_insert(calldata.key, hash, 0); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/flag.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/general_storage.h" 20 | #include "sdk/nonnegative_int64.h" 21 | 22 | namespace sdk 23 | { 24 | 25 | template 26 | class UniqueFlag 27 | { 28 | const sdk::StorageKey key; 29 | 30 | public: 31 | 32 | constexpr UniqueFlag(sdk::StorageKey k) 33 | : key(std::move(k)) 34 | {} 35 | 36 | void acquire() 37 | { 38 | if (!has_key(key)) 39 | { 40 | int64_set_add(key, count, 0); 41 | } 42 | 43 | int64_set_add(key, count, -1); 44 | } 45 | }; 46 | 47 | } 48 | -------------------------------------------------------------------------------- /cpp_contracts/test_gas_limit.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "sdk/log.h" 18 | #include "sdk/raw_memory.h" 19 | #include "sdk/types.h" 20 | #include "sdk/calldata.h" 21 | #include "sdk/constexpr.h" 22 | 23 | EXPORT("pub00000000") 24 | consume_gas() 25 | { 26 | auto num_loops = sdk::get_calldata(); 27 | 28 | uint64_t out = 0; 29 | 30 | for (uint64_t i = 0; i < num_loops; i++) 31 | { 32 | out += i; 33 | sdk::log(out); 34 | } 35 | } 36 | EXPORT("pub01000000") 37 | infinite_loop() 38 | { 39 | uint64_t out = 0; 40 | while(true) 41 | { 42 | sdk::log(out); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/contracts.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/types.h" 20 | #include "sdk/syscall.h" 21 | 22 | namespace sdk 23 | { 24 | 25 | Hash create_contract(uint32_t contract_idx) 26 | { 27 | Hash out; 28 | detail::builtin_syscall(SYSCALLS::CONTRACT_CREATE, 29 | contract_idx, to_offset(&out), 30 | 0, 0, 0, 0); 31 | return out; 32 | } 33 | 34 | Address 35 | deploy_contract(Hash const& h, uint64_t nonce) 36 | { 37 | Address out; 38 | detail::builtin_syscall(SYSCALLS::CONTRACT_DEPLOY, 39 | to_offset(&h), nonce, to_offset(&out), 40 | 0, 0, 0); 41 | return out; 42 | } 43 | 44 | } // namespace sdk 45 | -------------------------------------------------------------------------------- /common/syscall_nos.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum SYSCALLS 4 | { 5 | // standard syscalls, not groundhog-specific 6 | EXIT = 500, 7 | WRITE = 501, 8 | WRITE_BYTES = 502, 9 | 10 | // groundhog runtime 11 | LOG = 600, 12 | INVOKE = 601, 13 | GET_SENDER = 602, 14 | GET_SELF_ADDR = 603, 15 | GET_SRC_TX_HASH = 604, 16 | GET_INVOKED_TX_HASH = 605, 17 | GET_BLOCK_NUMBER = 606, 18 | 19 | RETURN = 626, 20 | GET_CALLDATA = 627, 21 | GET_CALLDATA_LEN = 628, 22 | 23 | GAS = 629, 24 | 25 | // storage fns 26 | HAS_KEY = 607, 27 | 28 | // raw memory 29 | RAW_MEM_SET = 608, 30 | RAW_MEM_GET = 609, 31 | RAW_MEM_GET_LEN = 610, 32 | 33 | // delete 34 | DELETE_KEY_LAST = 611, 35 | 36 | // nonnegative int 37 | NNINT_SET_ADD = 612, 38 | NNINT_ADD = 613, 39 | NNINT_GET = 614, 40 | 41 | // hashset 42 | HS_INSERT = 615, 43 | HS_INC_LIMIT = 616, 44 | HS_CLEAR = 617, 45 | HS_GET_SIZE = 618, 46 | HS_GET_MAX_SIZE = 619, 47 | HS_GET_INDEX_OF = 620, 48 | HS_GET_INDEX = 621, 49 | 50 | // contracts 51 | CONTRACT_CREATE = 622, 52 | CONTRACT_DEPLOY = 623, 53 | 54 | // witnesses 55 | WITNESS_GET = 624, 56 | WITNESS_GET_LEN = 625, 57 | 58 | // crypto 59 | HASH = 700, 60 | VERIFY_ED25519 = 701, 61 | }; 62 | 63 | -------------------------------------------------------------------------------- /pedersen_ffi/pedersen.cc: -------------------------------------------------------------------------------- 1 | #include "pedersen_ffi/pedersen.h" 2 | 3 | namespace scs 4 | { 5 | 6 | static const void* pedersen_params = nullptr; 7 | 8 | 9 | struct PedersenQuery { 10 | uint64_t query_low; 11 | uint64_t query_high; 12 | uint8_t blinding[32]; 13 | }; 14 | 15 | struct PedersenResponse { 16 | uint8_t serialized[32]; 17 | }; 18 | 19 | /* 20 | namespace detail 21 | { 22 | 23 | extern "C" 24 | { 25 | void* gen_pedersen_params(); 26 | void free_pedersen_params(void*); 27 | PedersenResponse pedersen_commitment(const PedersenQuery*, const void*); 28 | } 29 | 30 | } // detail 31 | 32 | */ 33 | std::array 34 | pedersen_commitment(unsigned __int128 value, Hash const& blinding) 35 | { 36 | throw std::runtime_error("unimpl"); 37 | /* 38 | PedersenQuery query; 39 | query.query_low = value & UINT64_MAX; 40 | query.query_high = value >> 64; 41 | std::memcpy(query.blinding, blinding.data(), 32); 42 | 43 | PedersenResponse response = detail::pedersen_commitment(&query, pedersen_params); 44 | 45 | std::array out; 46 | std::memcpy(out.data(), response.serialized, 32); 47 | return out; */ 48 | } 49 | 50 | void init_pedersen() 51 | { 52 | //pedersen_params = detail::gen_pedersen_params(); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/concepts.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include 20 | #include 21 | 22 | namespace sdk 23 | { 24 | 25 | template 26 | concept TriviallyCopyable 27 | = requires { 28 | typename std::enable_if::value>::type; 29 | }; 30 | 31 | template 32 | uint32_t 33 | to_offset(const T* addr) 34 | { 35 | static_assert(sizeof(void*) == 4, "wasm pointer size"); 36 | return reinterpret_cast(reinterpret_cast(addr)); 37 | } 38 | 39 | template 40 | concept VectorLike 41 | = requires (T object) 42 | { 43 | object.data(); 44 | object.size(); 45 | } && !TriviallyCopyable; 46 | 47 | } /* sdk */ 48 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/witness.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/concepts.h" 20 | #include "sdk/alloc.h" 21 | #include "sdk/types.h" 22 | #include "sdk/concepts.h" 23 | #include "sdk/syscall.h" 24 | 25 | #include 26 | #include 27 | 28 | namespace sdk 29 | { 30 | 31 | template 32 | T get_witness(uint64_t witness) 33 | { 34 | T out; 35 | detail::builtin_syscall(SYSCALLS::WITNESS_GET, 36 | witness, to_offset(&out), sizeof(T), 37 | 0, 0, 0); 38 | return out; 39 | } 40 | 41 | uint32_t get_witness_len(uint64_t wit_idx) 42 | { 43 | return detail::builtin_syscall(SYSCALLS::WITNESS_GET_LEN, 44 | wit_idx, 0, 0, 0, 0, 0); 45 | } 46 | 47 | } // namespace sdk 48 | 49 | 50 | -------------------------------------------------------------------------------- /rpc_server/echo_server.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | 21 | #include "config.h" 22 | 23 | #if USE_RPC 24 | #include "proto/external_call.grpc.pb.h" 25 | #include 26 | #else 27 | #include "rpc_server/mock_external_call.h" 28 | #endif 29 | 30 | namespace scs { 31 | 32 | class EchoServer final : public ExternalCall::Service 33 | { 34 | #if USE_RPC 35 | grpc::Status SendCall(grpc::ServerContext* context, 36 | const GRpcCall* request, 37 | GRpcResult* response) override 38 | { 39 | response->set_result(request->call()); 40 | return grpc::Status::OK; 41 | } 42 | #endif 43 | }; 44 | 45 | } // namespace scs 46 | -------------------------------------------------------------------------------- /cpp_contracts/test_nn_int64.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "sdk/calldata.h" 18 | #include "sdk/log.h" 19 | #include "sdk/raw_memory.h" 20 | #include "sdk/invoke.h" 21 | #include "sdk/nonnegative_int64.h" 22 | 23 | struct calldata_0 { 24 | sdk::StorageKey key; 25 | int64_t delta; 26 | }; 27 | 28 | EXPORT("pub00000000") 29 | call_int64_add() 30 | { 31 | auto calldata = sdk::get_calldata(); 32 | 33 | sdk::int64_add(calldata.key, calldata.delta); 34 | } 35 | 36 | struct calldata_1 { 37 | sdk::StorageKey key; 38 | int64_t value; 39 | int64_t delta; 40 | }; 41 | 42 | EXPORT("pub01000000") 43 | call_int64_set_add() 44 | { 45 | auto calldata = sdk::get_calldata(); 46 | 47 | sdk::int64_set_add(calldata.key, calldata.value, calldata.delta); 48 | } 49 | -------------------------------------------------------------------------------- /cpp_contracts/test_redirect_call.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "sdk/calldata.h" 18 | #include "sdk/log.h" 19 | #include "sdk/invoke.h" 20 | #include "sdk/alloc.h" 21 | 22 | static uint32_t flag = 0; 23 | 24 | EXPORT("pub00000000") 25 | redirect_call_to_proxy() 26 | { 27 | struct calldata_t { 28 | sdk::Address callee; 29 | uint32_t method; 30 | }; 31 | 32 | auto calldata = sdk::get_calldata(); 33 | 34 | sdk::print_debug(calldata); 35 | 36 | flag = 1; 37 | sdk::invoke(calldata.callee, calldata.method, sdk::EmptyStruct{}); 38 | flag = 0; 39 | } 40 | 41 | EXPORT("pub01000000") 42 | self_call() 43 | { 44 | sdk::log((uint8_t)0xFF); 45 | } 46 | 47 | EXPORT("pub02000000") 48 | self_call_reentrant_guard() 49 | { 50 | if (flag) { 51 | abort(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /rpc/rpc_address_db.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "xdr/types.h" 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "config.h" 28 | 29 | #if USE_RPC 30 | #include "proto/external_call.grpc.pb.h" 31 | #endif 32 | 33 | namespace scs { 34 | 35 | struct RpcAddress 36 | { 37 | std::string addr; 38 | }; 39 | 40 | class RpcAddressDB 41 | { 42 | std::map address_db; 43 | 44 | std::shared_mutex mtx; 45 | 46 | public: 47 | RpcAddressDB(); 48 | 49 | #if USE_RPC 50 | std::unique_ptr connect(Hash const& h); 51 | #endif 52 | 53 | void add_mapping(Hash const& h, RpcAddress addr); 54 | }; 55 | 56 | } // namespace scs 57 | -------------------------------------------------------------------------------- /threadlocal/uid.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | 21 | #include 22 | #include "config/static_constants.h" 23 | 24 | namespace scs 25 | { 26 | 27 | /** 28 | * Outputs a 48-bit unique ID 29 | * at every call to get(). 30 | * 31 | * Output is <48 bit tag><16 bit 0s> 32 | */ 33 | class UniqueIdentifier 34 | { 35 | constexpr static uint64_t inc = ((uint64_t)1) << 16; 36 | uint64_t id; 37 | 38 | static_assert(TLCACHE_SIZE <= 512, "insufficient bit length in id offset initialization"); 39 | 40 | public: 41 | 42 | UniqueIdentifier() 43 | : id(static_cast(utils::ThreadlocalIdentifier::get()) << 55) 44 | {} 45 | 46 | // never returns 0 47 | uint64_t get() 48 | { 49 | return id += inc; 50 | } 51 | }; 52 | 53 | } -------------------------------------------------------------------------------- /ansible/aws_install_packages.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: aws init 3 | hosts: all 4 | tasks: 5 | - name: update 6 | shell: "sudo apt-get update" 7 | - name: install packages 8 | shell: "sudo apt-get install -y autoconf cython3 sysstat make bison flex pip libgsl-dev liblmdb-dev git libltdl-dev libsodium-dev cxxtest pkg-config libtool libtbb-dev libglpk-dev cmake" 9 | - name: install cc 10 | shell: "sudo apt-get install -y g++-12 && sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 12 && sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 12" 11 | - name: install libfyaml 12 | shell: "git clone https://github.com/pantoniou/libfyaml.git && cd libfyaml && ./bootstrap.sh && ./configure && make -j && sudo make install" 13 | - name: install catch2 14 | shell: "git clone https://github.com/catchorg/Catch2.git && cd Catch2 && cmake -Bbuild -H. -DBUILD_TESTING=OFF -DCMAKE_CXX_COMPILER=g++ -DCMAKE_C_COMPILER=gcc && sudo cmake --build build/ --target install" 15 | - name: install grpc 16 | shell: "sudo apt-get install -y libgrpc++-dev libgrpc-dev protobuf-compiler protobuf-compiler-grpc" 17 | - name: install rust 18 | shell: "curl https://sh.rustup.rs -sSf | sh -s -- -y" 19 | - name: ldconfig 20 | shell: "sudo ldconfig" 21 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/constexpr.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/shared.h" 20 | 21 | #include "sdk/types.h" 22 | 23 | #include 24 | #include 25 | 26 | namespace sdk 27 | { 28 | 29 | constexpr static 30 | StorageKey 31 | make_static_key(uint64_t a, uint64_t b = 0, uint64_t c = 0, uint64_t d = 0) 32 | { 33 | return scs::make_static_32bytes(a, b, c, d); 34 | } 35 | 36 | /** 37 | * sdk key registry: 38 | * 0: replay cache id 39 | * 1: singlekey auth pk 40 | * 41 | * contract-specific: 42 | * anything with b > 0 or c > 0 or d > 0 43 | */ 44 | 45 | constexpr static 46 | Address 47 | make_static_address(uint64_t a, uint64_t b = 0, uint64_t c = 0, uint64_t d = 0) 48 | { 49 | return scs::make_static_32bytes
(a, b, c, d); 50 | } 51 | 52 | 53 | } -------------------------------------------------------------------------------- /object/make_delta.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "xdr/types.h" 20 | 21 | #include 22 | 23 | #include "xdr/storage_delta.h" 24 | 25 | namespace scs { 26 | 27 | StorageDelta 28 | make_raw_memory_write(xdr::opaque_vec&& data); 29 | 30 | StorageDelta 31 | make_delete_last(); 32 | 33 | StorageDelta 34 | make_nonnegative_int64_set_add(int64_t set, int64_t add); 35 | 36 | StorageDelta 37 | make_hash_set_insert(Hash const& h, uint64_t threshold); 38 | 39 | StorageDelta 40 | make_hash_set_insert(HashSetEntry const& entry); 41 | 42 | StorageDelta 43 | make_hash_set_increase_limit(uint16_t limit); 44 | 45 | StorageDelta 46 | make_hash_set_clear(uint64_t threshold); 47 | 48 | StorageDelta 49 | make_asset_add(int64_t delta); 50 | 51 | } // namespace scs 52 | -------------------------------------------------------------------------------- /transaction_context/method_invocation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "xdr/types.h" 23 | #include "xdr/transaction.h" 24 | 25 | namespace scs { 26 | 27 | struct MethodInvocation 28 | { 29 | const Address addr; 30 | 31 | // Copying from eth design: 32 | // method names are 4 bytes (of valid ascii); 33 | // Here, public/private is denoted by method prefix 34 | // full method name is pub{XXXX} 35 | const uint32_t method_name; 36 | const std::vector calldata; 37 | 38 | std::string 39 | get_invocable_methodname() const; 40 | 41 | MethodInvocation(TransactionInvocation const& root_invocation); 42 | MethodInvocation(const Address& addr, uint32_t method, std::vector&& calldata); 43 | }; 44 | 45 | } /* scs */ 46 | -------------------------------------------------------------------------------- /debug/debug_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "xdr/storage.h" 23 | #include "xdr/storage_delta.h" 24 | 25 | namespace debug { 26 | 27 | std::string 28 | storage_object_to_str(std::optional const& obj); 29 | 30 | std::string 31 | storage_object_to_str(scs::StorageObject const& obj); 32 | 33 | std::string 34 | storage_delta_to_str(scs::StorageDelta const& delta); 35 | 36 | //! Convert a byte array to a hex string. 37 | std::string 38 | array_to_str(const unsigned char* array, const int len); 39 | 40 | template 41 | [[maybe_unused]] 42 | static std::string 43 | array_to_str(const ArrayLike& array) 44 | { 45 | return array_to_str(array.data(), array.size()); 46 | } 47 | 48 | } // namespace debug 49 | -------------------------------------------------------------------------------- /mempool/mempool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "xdr/transaction.h" 25 | 26 | namespace scs { 27 | 28 | class Mempool 29 | { 30 | constexpr static uint64_t MAX_MEMPOOL_SIZE = static_cast(1) << 24; 31 | 32 | std::vector ringbuffer; 33 | std::atomic indices; 34 | 35 | std::mutex mtx; // for add_txs 36 | 37 | public: 38 | Mempool() 39 | : ringbuffer() 40 | , indices(0) 41 | { 42 | ringbuffer.resize(MAX_MEMPOOL_SIZE); 43 | } 44 | 45 | std::optional get_new_tx(); 46 | uint32_t available_size(); 47 | 48 | uint32_t add_txs(std::vector&& txs); 49 | }; 50 | 51 | } // namespace scs 52 | -------------------------------------------------------------------------------- /cpp_contracts/test_rpc.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "sdk/alloc.h" 18 | #include "sdk/calldata.h" 19 | #include "sdk/crypto.h" 20 | #include "sdk/invoke.h" 21 | #include "sdk/log.h" 22 | #include "sdk/nonnegative_int64.h" 23 | #include "sdk/raw_memory.h" 24 | #include "sdk/types.h" 25 | #include "sdk/constexpr.h" 26 | #include "sdk/rpc.h" 27 | #include "sdk/semaphore.h" 28 | 29 | uint64_t dispatch_call(sdk::Hash const& addr, uint64_t input) 30 | { 31 | return sdk::external_call(addr, input); 32 | } 33 | 34 | struct calldata { 35 | sdk::Hash addr; 36 | uint64_t call; 37 | }; 38 | 39 | EXPORT("pub00000000") 40 | dispatch() 41 | { 42 | auto c = sdk::get_calldata(); 43 | 44 | uint64_t res = dispatch_call(c.addr, c.call); 45 | 46 | if (res != c.call) { 47 | abort(); 48 | } 49 | 50 | sdk::log(res); 51 | } 52 | 53 | -------------------------------------------------------------------------------- /cpp_contracts/test_sdk.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "sdk/replay_cache.h" 18 | #include "sdk/semaphore.h" 19 | #include "sdk/constexpr.h" 20 | #include "sdk/calldata.h" 21 | 22 | struct replay_calldata { 23 | uint64_t expiry_time; 24 | }; 25 | 26 | EXPORT("pub00000000") 27 | replay() 28 | { 29 | auto calldata = sdk::get_calldata(); 30 | sdk::record_self_replay(calldata.expiry_time); 31 | } 32 | 33 | static sdk::Semaphore s(sdk::make_static_key(0, 1)); 34 | static sdk::Semaphore<2> s2 (sdk::make_static_key(1, 1)); 35 | 36 | EXPORT("pub01000000") 37 | semaphore() 38 | { 39 | s.acquire(); 40 | } 41 | 42 | EXPORT("pub02000000") 43 | semaphore2() 44 | { 45 | s2.acquire(); 46 | } 47 | 48 | EXPORT("pub03000000") 49 | transientSemaphore() 50 | { 51 | sdk::TransientSemaphore (sdk::make_static_key(2, 1)).acquire(); 52 | } 53 | 54 | -------------------------------------------------------------------------------- /utils/make_calldata.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | namespace scs { 24 | 25 | xdr::opaque_vec<> 26 | static 27 | make_calldata() 28 | { 29 | return {}; 30 | } 31 | 32 | template 33 | xdr::opaque_vec<> static make_calldata(calldata const& data, calldatas const& ...additional) 34 | { 35 | const uint8_t* addr = reinterpret_cast(&data); 36 | xdr::opaque_vec<> out; 37 | 38 | if constexpr (!std::is_empty::value) 39 | { 40 | out.insert(out.end(), addr, addr + sizeof(calldata)); 41 | } 42 | 43 | auto rest = make_calldata(additional...); 44 | 45 | out.insert(out.end(), rest.begin(), rest.end()); 46 | return out; 47 | } 48 | 49 | } // namespace scs 50 | -------------------------------------------------------------------------------- /rpc_server/server_runner.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "config.h" 25 | 26 | #if USE_RPC 27 | #include "proto/external_call.grpc.pb.h" 28 | #include 29 | #include 30 | #else 31 | #include "rpc_server/mock_external_call.h" 32 | #endif 33 | 34 | namespace scs 35 | { 36 | 37 | class ServerRunner 38 | { 39 | std::mutex mtx; 40 | std::condition_variable cv; 41 | 42 | bool done = false; 43 | 44 | #if USE_RPC 45 | std::unique_ptr impl; 46 | std::unique_ptr server; 47 | #endif 48 | 49 | void run(); 50 | public: 51 | 52 | ServerRunner(std::unique_ptr _impl, std::string addr); 53 | 54 | ~ServerRunner(); 55 | }; 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/shared.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | namespace scs 20 | { 21 | 22 | namespace detail 23 | { 24 | 25 | constexpr static 26 | void write_uint64_t(uint8_t* out, uint64_t value) 27 | { 28 | for (size_t i = 0; i < 8; i++) 29 | { 30 | out[i] = (value >> (8*i)) & 0xFF; 31 | } 32 | } 33 | 34 | } 35 | 36 | template 37 | constexpr static 38 | OutputArray 39 | make_static_32bytes(uint64_t a, uint64_t b = 0, uint64_t c = 0, uint64_t d = 0) 40 | { 41 | OutputArray out = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 43 | uint8_t* data = out.data(); 44 | detail::write_uint64_t(data, a); 45 | detail::write_uint64_t(data + 8, b); 46 | detail::write_uint64_t(data + 16, c); 47 | detail::write_uint64_t(data + 24, d); 48 | return out; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/auth_singlekey.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/types.h" 20 | #include "sdk/constexpr.h" 21 | #include "sdk/raw_memory.h" 22 | #include "sdk/invoke.h" 23 | #include "sdk/witness.h" 24 | #include "sdk/crypto.h" 25 | 26 | namespace sdk 27 | { 28 | 29 | namespace detail 30 | { 31 | 32 | constexpr static StorageKey pk_storage_key 33 | = make_static_key(1); 34 | 35 | } 36 | 37 | 38 | void 39 | auth_single_pk_register(const PublicKey& pk) 40 | { 41 | set_raw_memory(detail::pk_storage_key, pk); 42 | } 43 | 44 | void 45 | auth_single_pk_check_sig(uint64_t wit_idx) 46 | { 47 | PublicKey pk = get_raw_memory(detail::pk_storage_key); 48 | Hash h = get_invoked_hash(); 49 | Signature sig = get_witness(wit_idx); 50 | 51 | if (!check_sig_ed25519(pk, sig, h)) 52 | { 53 | abort(); 54 | } 55 | } 56 | 57 | 58 | } -------------------------------------------------------------------------------- /cpp_contracts/sdk/semaphore.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/types.h" 20 | #include "sdk/nonnegative_int64.h" 21 | #include "sdk/delete.h" 22 | 23 | namespace sdk 24 | { 25 | 26 | template 27 | class Semaphore 28 | { 29 | const sdk::StorageKey key; 30 | 31 | public: 32 | 33 | constexpr Semaphore(sdk::StorageKey k) 34 | : key(std::move(k)) 35 | {} 36 | 37 | void acquire() 38 | { 39 | int64_set_add(key, count, -1); 40 | } 41 | }; 42 | 43 | template 44 | class TransientSemaphore 45 | { 46 | const sdk::StorageKey key; 47 | 48 | public: 49 | 50 | constexpr TransientSemaphore(sdk::StorageKey k) 51 | : key(std::move(k)) 52 | {} 53 | 54 | void acquire() 55 | { 56 | int64_set_add(key, count, -1); 57 | } 58 | 59 | ~TransientSemaphore() 60 | { 61 | delete_last(key); 62 | } 63 | }; 64 | 65 | } -------------------------------------------------------------------------------- /utils/load_wasm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | 21 | #include "xdr/types.h" 22 | 23 | namespace scs { 24 | 25 | [[maybe_unused]] std::shared_ptr static load_wasm_from_file( 26 | const char* filename) 27 | { 28 | FILE* f = std::fopen(filename, "r"); 29 | 30 | if (f == nullptr) { 31 | throw std::runtime_error("failed to load wasm file"); 32 | } 33 | 34 | auto contents = std::make_shared(); 35 | 36 | const int BUF_SIZE = 65536; 37 | char buf[BUF_SIZE]; 38 | 39 | int count = -1; 40 | while (count != 0) { 41 | count = std::fread(buf, sizeof(char), BUF_SIZE, f); 42 | if (count > 0) { 43 | contents->insert(contents->end(), buf, buf + count); 44 | } 45 | } 46 | std::fclose(f); 47 | 48 | return contents; 49 | } 50 | 51 | } // namespace scs 52 | -------------------------------------------------------------------------------- /crypto/crypto_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "xdr/types.h" 24 | 25 | namespace scs { 26 | 27 | void __attribute__((constructor)) initialize_crypto(); 28 | 29 | // uses shared key randomly generated at startup 30 | uint32_t 31 | shorthash(const uint8_t* data, uint32_t data_len, const uint32_t modulus); 32 | 33 | bool 34 | check_sig_ed25519(PublicKey const& pk, Signature const& sig, std::vector const& msg); 35 | 36 | Signature 37 | sign_ed25519(SecretKey const& sk, uint8_t const* msg, uint32_t msg_len); 38 | 39 | template 40 | Signature 41 | sign_ed25519(SecretKey const& sk, T const& msg) 42 | { 43 | return sign_ed25519(sk, msg.data(), msg.size()); 44 | } 45 | 46 | std::pair 47 | deterministic_key_gen(uint64_t seed); 48 | 49 | } // namespace scs 50 | -------------------------------------------------------------------------------- /persistence/rocksdb_wrapper.cc: -------------------------------------------------------------------------------- 1 | #include "persistence/rocksdb_wrapper.h" 2 | 3 | #include "utils/mkdir.h" 4 | 5 | namespace scs { 6 | 7 | rocksdb::Options 8 | make_options() 9 | { 10 | rocksdb::Options options; 11 | 12 | options.create_if_missing = true; 13 | options.error_if_exists = true; 14 | 15 | return options; 16 | } 17 | 18 | constexpr void 19 | assert_rdb(bool b) 20 | { 21 | if (!b) { 22 | throw std::runtime_error("status error"); 23 | } 24 | } 25 | 26 | void 27 | RocksdbWrapper::open() 28 | { 29 | auto opts = make_options(); 30 | 31 | utils::mkdir_safe(dbdir); 32 | 33 | rocksdb::Status status = rocksdb::DB::Open(opts, dbdir.c_str(), &db); 34 | assert_rdb(status.ok()); 35 | } 36 | void 37 | RocksdbWrapper::clear_previous() 38 | { 39 | utils::clear_directory(dbdir); 40 | } 41 | 42 | RocksdbWrapper::~RocksdbWrapper() 43 | { 44 | if (db != nullptr) { 45 | delete db; 46 | } 47 | } 48 | 49 | void 50 | RocksdbWrapper::put(rocksdb::Slice const& key_slice, 51 | rocksdb::Slice const& value_slice) 52 | { 53 | auto s = db->Put(write_options, key_slice, value_slice); 54 | assert_rdb(s.ok()); 55 | } 56 | 57 | void 58 | RocksdbWrapper::get(rocksdb::Slice const& key_slice, std::string& value_out) 59 | { 60 | // TODO consider rocksdb::PinnableSlice 61 | auto s = db->Get(read_options, key_slice, &value_out); 62 | assert_rdb(s.ok()); 63 | } 64 | 65 | } // namespace scs 66 | -------------------------------------------------------------------------------- /cpp_contracts/test_log.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "sdk/log.h" 18 | #include "sdk/calldata.h" 19 | #include "sdk/invoke.h" 20 | 21 | EXPORT("pub00000000") 22 | log_value() 23 | { 24 | uint64_t val = 0xAABBCCDD'EEFF0011; 25 | 26 | sdk::log(val); 27 | } 28 | 29 | EXPORT("pub01000000") 30 | log_calldata() 31 | { 32 | uint64_t calldata = sdk::get_calldata(); 33 | sdk::log(calldata); 34 | } 35 | 36 | EXPORT("pub02000000") 37 | log_data_twice() 38 | { 39 | struct calldata_t { 40 | uint32_t a; 41 | uint32_t b; 42 | }; 43 | 44 | auto calldata = sdk::get_calldata(); 45 | sdk::log(calldata.a); 46 | sdk::log(calldata.b); 47 | } 48 | 49 | EXPORT("pub03000000") 50 | log_msg_sender() 51 | { 52 | auto addr = sdk::get_msg_sender(); 53 | sdk::log(addr); 54 | } 55 | 56 | EXPORT("pub04000000") 57 | log_msg_sender_from_self() 58 | { 59 | sdk::invoke(sdk::get_self(), 3, sdk::EmptyStruct{}); 60 | } 61 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/log.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/macros.h" 20 | #include "sdk/alloc.h" 21 | #include "sdk/concepts.h" 22 | #include "sdk/syscall.h" 23 | 24 | #include 25 | 26 | #define LOG_MAX_STR_LEN 256 27 | 28 | namespace sdk 29 | { 30 | 31 | template 32 | void log(T const& val) 33 | { 34 | detail::builtin_syscall(SYSCALLS::LOG, 35 | to_offset(&val), sizeof(T), 36 | 0, 0, 0, 0); 37 | } 38 | 39 | void print(const char* str, uint32_t len) 40 | { 41 | detail::builtin_syscall(SYSCALLS::WRITE, 42 | sdk::to_offset(str), len, 0, 0, 0, 0); 43 | } 44 | 45 | template 46 | void print_debug(T const& val) 47 | { 48 | detail::builtin_syscall(SYSCALLS::WRITE_BYTES, 49 | to_offset(&val), sizeof(T), 0, 0, 0, 0); 50 | } 51 | 52 | void print(const char* str) 53 | { 54 | print(str, strnlen(str, LOG_MAX_STR_LEN)); 55 | } 56 | 57 | } /* sdk */ 58 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/asset.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/macros.h" 20 | #include "sdk/concepts.h" 21 | #include "sdk/alloc.h" 22 | #include "sdk/types.h" 23 | #include "sdk/concepts.h" 24 | 25 | #include 26 | #include 27 | 28 | namespace sdk 29 | { 30 | 31 | namespace detail 32 | { 33 | 34 | BUILTIN("asset_add") 35 | void 36 | asset_add( 37 | uint32_t key_offset, 38 | /* key_len = 32 */ 39 | int64_t delta); 40 | 41 | BUILTIN("asset_get") 42 | uint64_t 43 | asset_get( 44 | uint32_t key_offset 45 | /* key_len = 32 */); 46 | 47 | } /* detail */ 48 | 49 | // creates if doesn't already exist 50 | void 51 | asset_add(StorageKey const& key, int64_t delta) 52 | { 53 | detail::asset_add( 54 | to_offset(&key), 55 | delta); 56 | } 57 | 58 | uint64_t 59 | asset_get(StorageKey const& key) 60 | { 61 | return detail::asset_get( 62 | to_offset(&key)); 63 | } 64 | 65 | } /* sdk */ 66 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/calldata.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/macros.h" 20 | #include "sdk/alloc.h" 21 | #include "sdk/concepts.h" 22 | 23 | #include "sdk/syscall.h" 24 | 25 | #include 26 | 27 | namespace sdk 28 | { 29 | 30 | template 31 | T get_calldata() 32 | { 33 | if constexpr (std::is_empty::value) 34 | { 35 | return T{}; 36 | } 37 | 38 | T out; 39 | detail::builtin_syscall(SYSCALLS::GET_CALLDATA, 40 | to_offset(&out), 0, sizeof(T), 0, 0, 0); 41 | return out; 42 | } 43 | 44 | void 45 | get_calldata_slice(uint8_t* out, uint32_t start_offset, uint32_t end_offset) 46 | { 47 | detail::builtin_syscall(SYSCALLS::GET_CALLDATA, 48 | to_offset(out), start_offset, end_offset, 0, 0, 0); 49 | } 50 | 51 | 52 | uint32_t get_calldata_len() 53 | { 54 | return detail::builtin_syscall(SYSCALLS::GET_CALLDATA_LEN, 55 | 0, 0, 0, 0, 0, 0); 56 | } 57 | 58 | } /* sdk */ 59 | -------------------------------------------------------------------------------- /phase/phases.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | namespace scs 20 | { 21 | 22 | class GlobalContext; 23 | struct BlockContext; 24 | class GroundhogGlobalContext; 25 | struct GroundhogBlockContext; 26 | class SisyphusGlobalContext; 27 | struct SisyphusBlockContext; 28 | 29 | void phase_finish_block(GlobalContext& global_structures, BlockContext& block_structures); 30 | void phase_undo_block(GlobalContext& global_structures, BlockContext& block_structures); 31 | 32 | void phase_finish_block(GroundhogGlobalContext& global_structures, GroundhogBlockContext& block_structures); 33 | void phase_undo_block(GroundhogGlobalContext& global_structures, GroundhogBlockContext& block_structures); 34 | 35 | void phase_finish_block(SisyphusGlobalContext& global_structures, SisyphusBlockContext& block_structures); 36 | void phase_undo_block(SisyphusGlobalContext& global_structures, SisyphusBlockContext& block_structures); 37 | 38 | } /* scs */ 39 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/replay_cache.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/hashset.h" 20 | #include "sdk/types.h" 21 | #include "sdk/constexpr.h" 22 | #include "sdk/invoke.h" 23 | 24 | namespace sdk 25 | { 26 | 27 | namespace detail 28 | { 29 | 30 | constexpr static StorageKey replay_cache_storage_key 31 | = make_static_key(0); 32 | 33 | } // detail 34 | 35 | void record_self_replay(const uint64_t expiration_time) 36 | { 37 | Hash hash_buf = get_invoked_hash(); 38 | hashset_insert(detail::replay_cache_storage_key, hash_buf, expiration_time); 39 | 40 | uint64_t current_block_number = get_block_number(); 41 | if (expiration_time < current_block_number) 42 | { 43 | abort(); 44 | } 45 | 46 | hashset_clear(detail::replay_cache_storage_key, current_block_number); 47 | } 48 | 49 | void replay_cache_size_increase(uint16_t amount) 50 | { 51 | hashset_increase_limit(detail::replay_cache_storage_key, amount); 52 | } 53 | 54 | } 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/auth_singlekey_wasmed25519.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/types.h" 20 | #include "sdk/constexpr.h" 21 | #include "sdk/raw_memory.h" 22 | #include "sdk/invoke.h" 23 | #include "sdk/witness.h" 24 | 25 | #include "ed25519.h" 26 | 27 | namespace sdk 28 | { 29 | 30 | namespace detail 31 | { 32 | 33 | constexpr static StorageKey pk_storage_key 34 | = make_static_key(1); 35 | 36 | } 37 | 38 | 39 | void 40 | wasm_auth_single_pk_register(const PublicKey& pk) 41 | { 42 | set_raw_memory(detail::pk_storage_key, pk); 43 | } 44 | 45 | void 46 | wasm_auth_single_pk_check_sig(uint64_t wit_idx) 47 | { 48 | PublicKey pk = get_raw_memory(detail::pk_storage_key); 49 | Hash h = get_invoked_hash(); 50 | Signature sig = get_witness(wit_idx); 51 | 52 | if (ed25519_verify(sig.data(), h.data(), h.size(), pk.data()) != 1) 53 | //if (!check_sig_ed25519(pk, sig, h)) 54 | { 55 | abort(); 56 | } 57 | } 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /config/print_configs.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "config/print_configs.h" 18 | #include "config.h" 19 | 20 | #include "config/static_constants.h" 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "state_db/sisyphus_state_db.h" 27 | 28 | namespace scs { 29 | 30 | void 31 | print_configs() 32 | { 33 | std::printf("=========== scs configs ==========\n"); 34 | std::printf("USE_RPC = %d\n", USE_RPC); 35 | std::printf("HW THREADS = %u\n", std::thread::hardware_concurrency()); 36 | std::printf("TLCACHE_SIZE = %" PRIu32 "\n", TLCACHE_SIZE); 37 | std::printf("Sisyphus SDB iface = %s\n", typeid(SisyphusStateDB::storage_t).name()); 38 | std::printf("Persistence = %u\n", PERSISTENT_STORAGE_ENABLED); 39 | std::printf("Sisyphus SDB USE_ASSETS = %u\n", SisyphusStateDB::USE_ASSETS); 40 | std::printf("Sisyphus SDB USE_PEDERSEN = %u\n", SisyphusStateDB::USE_PEDERSEN); 41 | } 42 | 43 | } // namespace scs 44 | -------------------------------------------------------------------------------- /metering/cmd/src/main.rs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | use std::env; 18 | use std::fs::File; 19 | use std::io::prelude::*; 20 | 21 | extern crate inject_metering; 22 | 23 | fn main() { 24 | let args: Vec = env::args().collect(); 25 | println!("{:?}", args); 26 | 27 | if args.len() != 3 { 28 | println!("invalid arg count"); 29 | return; 30 | } 31 | 32 | let wasm_file = &args[1]; 33 | 34 | let mut f = File::open(wasm_file).expect("should be able to read file"); 35 | 36 | let mut buffer = Vec::new(); 37 | f.read_to_end(&mut buffer).expect("read to end"); 38 | 39 | let out_mod = match inject_metering::add_metering(&buffer) { 40 | Some(m) => m, 41 | None => { 42 | println!("metering failed"); 43 | return; 44 | } 45 | }; 46 | 47 | let out_filename = &args[2]; 48 | 49 | let mut out_f = File::create(out_filename).expect("opened"); 50 | out_f.write_all(&out_mod).ok(); 51 | } 52 | -------------------------------------------------------------------------------- /metering_ffi/metered_contract.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | #include "xdr/types.h" 25 | 26 | #include "contract_db/runnable_script.h" 27 | 28 | namespace scs { 29 | 30 | namespace detail { 31 | 32 | // matches metering/inject_metering/src/lib.rs:metered_contract 33 | struct metered_contract 34 | { 35 | uint8_t* data; 36 | uint32_t len; 37 | uint32_t capacity; 38 | }; 39 | 40 | } // namespace detail 41 | 42 | class MeteredContract : public utils::NonMovableOrCopyable 43 | { 44 | detail::metered_contract base; 45 | 46 | public: 47 | MeteredContract(std::shared_ptr unmetered); 48 | 49 | ~MeteredContract(); 50 | 51 | operator bool() const { return base.data != nullptr; } 52 | 53 | RunnableScriptView to_view() const; 54 | Hash hash() const; 55 | }; 56 | 57 | using metered_contract_ptr_t = std::shared_ptr; 58 | 59 | } // namespace scs 60 | -------------------------------------------------------------------------------- /threadlocal/cancellable_rpc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "config.h" 24 | 25 | #if USE_RPC 26 | #include 27 | #include 28 | #include 29 | 30 | #include "proto/external_call.grpc.pb.h" 31 | 32 | #endif 33 | 34 | #include "xdr/rpc.h" 35 | 36 | namespace scs 37 | { 38 | 39 | class CancellableRPC 40 | { 41 | std::mutex mtx; 42 | 43 | bool rpcs_allowed; 44 | 45 | #if USE_RPC 46 | std::optional context; 47 | grpc::CompletionQueue cq; 48 | #endif 49 | 50 | public: 51 | 52 | CancellableRPC(); 53 | 54 | // can be called from any thread 55 | void set_allowed(); 56 | void cancel_and_set_disallowed(); 57 | 58 | #if USE_RPC 59 | // should only be called from one thread 60 | std::optional send_query(RpcCall const& request, uint64_t uid, std::unique_ptr const& stub); 61 | #endif 62 | }; 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /rpc/rpc_address_db.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "rpc/rpc_address_db.h" 18 | 19 | #if USE_RPC 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #endif 26 | 27 | namespace scs { 28 | 29 | RpcAddressDB::RpcAddressDB() 30 | : address_db() 31 | , mtx() 32 | {} 33 | 34 | #if USE_RPC 35 | std::unique_ptr 36 | RpcAddressDB::connect(Hash const& h) 37 | { 38 | std::shared_lock lock(mtx); 39 | 40 | auto it = address_db.find(h); 41 | if (it == address_db.end()) { 42 | return {}; 43 | } 44 | 45 | // for now, make a new channel on each call 46 | return 47 | ExternalCall::NewStub(grpc::CreateChannel(it -> second.addr, grpc::InsecureChannelCredentials())); 48 | } 49 | #endif 50 | 51 | void 52 | RpcAddressDB::add_mapping(Hash const& h, RpcAddress addr) 53 | { 54 | std::lock_guard lock(mtx); 55 | 56 | address_db[h] = addr; 57 | } 58 | 59 | } // namespace scs 60 | -------------------------------------------------------------------------------- /xdr/types.x: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | namespace scs 18 | { 19 | 20 | typedef unsigned int uint32; 21 | typedef int int32; 22 | 23 | typedef unsigned hyper uint64; 24 | typedef hyper int64; 25 | 26 | typedef opaque uint128[16]; 27 | typedef opaque uint256[32]; 28 | 29 | typedef opaque Signature[64]; //ed25519 sig len is 512 bits 30 | typedef opaque PublicKey[32]; //ed25519 key len is 256 bits 31 | typedef opaque Hash[32]; // 256 bit hash, i.e. output of sha256 32 | typedef opaque SecretKey[64]; //ed25519 secret key len is 64 bytes, at least on libsodium 33 | 34 | typedef opaque Address[32]; // 256 bit contract addresses 35 | 36 | typedef opaque InvariantKey[32]; // arbitrary 32 bytes. 37 | 38 | typedef opaque AddressAndKey[64]; // in global storage: [contract address + invariant key] = 64 bytes 39 | // Contracts are free to set their own conventions for keys. 40 | 41 | typedef opaque Contract<>; 42 | 43 | typedef opaque TransactionLog<>; 44 | 45 | const MAX_STACK_BYTES = 65536; 46 | 47 | // crypto parameters 48 | const MAX_HASH_LEN = 512; 49 | 50 | } /* scs */ 51 | -------------------------------------------------------------------------------- /persistence/rocksdb_iface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "mtt/memcached_snapshot_trie/durable_interface.h" 5 | 6 | #include "persistence/rocksdb_wrapper.h" 7 | 8 | namespace scs 9 | { 10 | 11 | template 12 | class DirectWriteRocksDBIface 13 | { 14 | RocksdbWrapper& rdb; 15 | 16 | public: 17 | 18 | DirectWriteRocksDBIface(RocksdbWrapper& rdb) 19 | : rdb(rdb) 20 | {} 21 | 22 | constexpr static uint8_t KEY_LEN_BYTES = _KEY_LEN_BYTES; 23 | 24 | using result_t = trie::DurableResult; 25 | 26 | static_assert(std::is_trivially_copyable::value, "design error"); 27 | 28 | void log_durable_value(trie::TimestampPointerPair const& key, 29 | trie::DurableValue const& value) 30 | { 31 | 32 | auto const* ptr = reinterpret_cast(&key); 33 | rocksdb::Slice key_slice(ptr, sizeof(trie::TimestampPointerPair)); 34 | 35 | auto const& value_buf = value.get_buffer(); 36 | 37 | rocksdb::Slice value_slice(reinterpret_cast(value_buf.data()), value_buf.size()); 38 | 39 | rdb.put(key_slice, value_slice); 40 | } 41 | 42 | result_t restore_durable_value(trie::TimestampPointerPair const& key) const 43 | { 44 | auto const* ptr = reinterpret_cast(&key); 45 | 46 | result_t out; 47 | 48 | auto& data = out.get_backing_data(); 49 | 50 | rocksdb::Slice key_slice(ptr, sizeof(trie::TimestampPointerPair)); 51 | 52 | rdb.get(key_slice, data); 53 | 54 | return out; 55 | } 56 | }; 57 | 58 | } // scs 59 | -------------------------------------------------------------------------------- /transaction_context/transaction_results.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "xdr/transaction.h" 20 | #include "xdr/rpc.h" 21 | 22 | #include 23 | #include 24 | 25 | namespace scs { 26 | 27 | class TransactionResultsFrame 28 | { 29 | TransactionResults results; 30 | 31 | const bool validating; 32 | 33 | uint32_t rpc_idx = 0, log_idx = 0; 34 | 35 | public: 36 | 37 | TransactionResultsFrame(NondeterministicResults const& res) 38 | : results() 39 | , validating(true) 40 | { 41 | results.ndeterministic_results = res; 42 | } 43 | TransactionResultsFrame() 44 | : results() 45 | , validating(false) 46 | {} 47 | 48 | bool is_validating() const 49 | { 50 | return validating; 51 | } 52 | 53 | void add_log(TransactionLog log); 54 | 55 | void add_rpc_result(RpcResult result); 56 | RpcResult get_next_rpc_result(); 57 | 58 | TransactionResults get_results() { 59 | return results; 60 | } 61 | 62 | bool validating_check_all_rpc_results_used() const; 63 | }; 64 | 65 | } // namespace scs -------------------------------------------------------------------------------- /utils/atomic_singleton.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | namespace scs 20 | { 21 | 22 | template 23 | class AtomicSingleton 24 | { 25 | mutable std::atomic_flag initialized; 26 | mutable std::atomic value; 27 | 28 | T* conditional_init(auto&&... args) const 29 | { 30 | if (!initialized.test_and_set(std::memory_order_relaxed)) 31 | { 32 | value.store(new T(args...), std::memory_order_relaxed); 33 | } 34 | 35 | while(true) 36 | { 37 | auto* res = value.load(std::memory_order_relaxed); 38 | if (res != nullptr) 39 | { 40 | return res; 41 | } 42 | } 43 | } 44 | 45 | public: 46 | 47 | AtomicSingleton() 48 | : initialized() 49 | , value() 50 | {} 51 | 52 | T& get(auto&&... args) 53 | { 54 | return *conditional_init(args...); 55 | } 56 | 57 | const T& get(auto&&... args) const 58 | { 59 | return *conditional_init(args...); 60 | } 61 | 62 | // obv cannot access object concurrent with dtor, must not double destruct 63 | ~AtomicSingleton() 64 | { 65 | if (value.load() != nullptr) 66 | { 67 | delete (value.load()); 68 | } 69 | } 70 | }; 71 | 72 | } /* scs */ 73 | -------------------------------------------------------------------------------- /rpc_server/server_runner.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "rpc_server/server_runner.h" 18 | 19 | namespace scs { 20 | 21 | void 22 | ServerRunner::run() 23 | { 24 | #if USE_RPC 25 | server->Wait(); 26 | #endif 27 | 28 | std::lock_guard lock(mtx); 29 | done = true; 30 | cv.notify_all(); 31 | } 32 | 33 | ServerRunner::ServerRunner(std::unique_ptr _impl, 34 | std::string addr) 35 | #if USE_RPC 36 | : impl(std::move(_impl)) 37 | , server(nullptr) 38 | #endif 39 | { 40 | #if USE_RPC 41 | grpc::ServerBuilder builder; 42 | builder.AddListeningPort(addr, grpc::InsecureServerCredentials()); 43 | builder.RegisterService(impl.get()); 44 | server = builder.BuildAndStart(); 45 | #endif 46 | 47 | std::thread([this]() { run(); }).detach(); 48 | } 49 | 50 | ServerRunner::~ServerRunner() 51 | { 52 | #if USE_RPC 53 | server->Shutdown(); 54 | #endif 55 | 56 | auto done_lambda = [this]() { return done; }; 57 | 58 | std::unique_lock lock(mtx); 59 | if (done_lambda()) { 60 | return; 61 | } 62 | cv.wait(lock, done_lambda); 63 | } 64 | 65 | } // namespace scs 66 | -------------------------------------------------------------------------------- /transaction_context/method_invocation.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "transaction_context/method_invocation.h" 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | namespace scs 25 | { 26 | 27 | MethodInvocation::MethodInvocation(TransactionInvocation const& root_invocation) 28 | : addr(root_invocation.invokedAddress) 29 | , method_name(root_invocation.method_name) 30 | , calldata(root_invocation.calldata) 31 | {} 32 | 33 | MethodInvocation::MethodInvocation(const Address& addr, uint32_t method, std::vector&& calldata) 34 | : addr(addr) 35 | , method_name(method) 36 | , calldata(std::move(calldata)) 37 | {} 38 | 39 | 40 | std::string 41 | MethodInvocation::get_invocable_methodname() const 42 | { 43 | std::stringstream ss; 44 | ss << "pub"; 45 | ss << std::hex << std::uppercase << std::setw(2) << std::setfill('0'); 46 | uint8_t buf[4]; 47 | 48 | utils::write_unsigned_little_endian(buf, method_name); 49 | 50 | for (auto i = 0u; i < 4; i++) 51 | { 52 | ss << std::setfill('0') << std::setw(2) << static_cast(buf[i]); 53 | } 54 | 55 | return ss.str(); 56 | } 57 | 58 | } /* scs */ 59 | -------------------------------------------------------------------------------- /test_utils/deploy_and_commit_contractdb.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "test_utils/deploy_and_commit_contractdb.h" 18 | 19 | #include 20 | 21 | #include "crypto/hash.h" 22 | 23 | #include "contract_db/contract_db.h" 24 | #include "contract_db/contract_db_proxy.h" 25 | 26 | #include "storage_proxy/transaction_rewind.h" 27 | 28 | namespace scs { 29 | 30 | namespace test { 31 | 32 | void 33 | deploy_and_commit_contractdb(ContractDB& contract_db, 34 | const Address& addr, 35 | std::shared_ptr contract) 36 | { 37 | ContractDBProxy proxy(contract_db); 38 | 39 | Hash h = hash_xdr(*contract); 40 | 41 | proxy.create_contract(contract); 42 | 43 | proxy.deploy_contract_at_specific_address(addr, h); 44 | 45 | { 46 | TransactionRewind rewind; 47 | 48 | proxy.push_updates_to_db(rewind); 49 | 50 | rewind.commit(); 51 | } 52 | 53 | contract_db.commit(0); 54 | 55 | ContractDBProxy proxy_new(contract_db); 56 | 57 | REQUIRE(proxy_new.get_script(addr).data); 58 | } 59 | 60 | } // namespace test 61 | } // namespace scs 62 | -------------------------------------------------------------------------------- /xdr/transaction.x: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | %#include "xdr/types.h" 18 | 19 | %#include "xdr/rpc.h" 20 | 21 | namespace scs 22 | { 23 | 24 | enum TransactionStatus 25 | { 26 | SUCCESS = 0, 27 | FAILURE = 1 28 | //TODO other statuses 29 | }; 30 | 31 | struct TransactionInvocation 32 | { 33 | Address invokedAddress; 34 | uint32 method_name; 35 | opaque calldata<>; 36 | }; 37 | 38 | % static_assert(sizeof(Address) == sizeof(PublicKey), "pk size should be addr size"); 39 | 40 | struct Transaction 41 | { 42 | TransactionInvocation invocation; 43 | uint64 gas_limit; 44 | uint64 gas_rate_bid; 45 | 46 | Contract contracts_to_deploy<>; 47 | }; 48 | 49 | struct WitnessEntry 50 | { 51 | uint64 key; 52 | opaque value<>; 53 | }; 54 | 55 | struct SignedTransaction 56 | { 57 | Transaction tx; 58 | WitnessEntry witnesses<>; 59 | }; 60 | 61 | struct NondeterministicResults 62 | { 63 | RpcResult rpc_results<>; 64 | }; 65 | 66 | struct TxSetEntry 67 | { 68 | SignedTransaction tx; 69 | NondeterministicResults nondeterministic_results<>; 70 | }; 71 | 72 | struct TransactionResults 73 | { 74 | NondeterministicResults ndeterministic_results; 75 | TransactionLog logs<>; 76 | }; 77 | 78 | } /* scs */ 79 | -------------------------------------------------------------------------------- /hash_set/atomic_set.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "xdr/types.h" 24 | #include "xdr/storage.h" 25 | 26 | #include 27 | 28 | namespace scs { 29 | 30 | class AtomicSet : public utils::NonMovableOrCopyable 31 | { 32 | constexpr static float extra_buffer = 1.2; 33 | 34 | uint32_t capacity = 0; 35 | 36 | std::atomic* array = nullptr; 37 | 38 | std::atomic num_filled_slots = 0; 39 | 40 | constexpr static uint32_t TOMBSTONE = 0xFFFF'FFFF; 41 | 42 | public: 43 | AtomicSet(uint32_t max_capacity) 44 | : capacity(max_capacity * extra_buffer) 45 | , array(nullptr) 46 | { 47 | if (capacity > 0) 48 | { 49 | array = new std::atomic[capacity] {}; 50 | } 51 | } 52 | 53 | ~AtomicSet(); 54 | 55 | void resize(uint32_t new_capacity); 56 | 57 | void clear(); 58 | 59 | bool try_insert(const HashSetEntry& h); 60 | 61 | // throws if nexist 62 | void erase(const HashSetEntry& h); 63 | 64 | std::vector get_hashes() const; 65 | }; 66 | 67 | } // namespace scs 68 | -------------------------------------------------------------------------------- /test_utils/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "mtt/trie/debug_macros.h" 20 | #include "mtt/utils/serialize_endian.h" 21 | 22 | #include "xdr/types.h" 23 | 24 | #include 25 | 26 | #include 27 | 28 | namespace scs { 29 | 30 | namespace test { 31 | 32 | [[maybe_unused]] Address 33 | address_from_uint64(uint64_t addr) 34 | { 35 | Address out; 36 | utils::write_unsigned_big_endian(out, addr); 37 | return out; 38 | } 39 | 40 | [[maybe_unused]] uint32_t 41 | method_name_from_human_readable(std::string const& str) 42 | { 43 | if (sodium_init() < 0) { 44 | throw std::runtime_error("sodium init failed"); 45 | } 46 | 47 | Hash hash_buf; 48 | 49 | const uint8_t* data = reinterpret_cast(str.c_str()); 50 | 51 | if (hash_buf.size() != crypto_hash_sha256_BYTES) { 52 | throw std::runtime_error("invalid hash format"); 53 | } 54 | 55 | if (crypto_hash_sha256(hash_buf.data(), data, str.length()) != 0) { 56 | throw std::runtime_error("error in crypto_SHA256"); 57 | } 58 | 59 | return utils::read_unsigned_little_endian(hash_buf.data()); 60 | } 61 | 62 | } // namespace test 63 | 64 | } // namespace scs 65 | -------------------------------------------------------------------------------- /hash_set/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | #include "xdr/storage.h" 21 | #include "object/comparators.h" 22 | 23 | namespace scs 24 | { 25 | 26 | [[maybe_unused]] 27 | static void normalize_hashset(HashSet& hs) 28 | { 29 | auto& h_list = hs.hashes; 30 | std::sort(h_list.begin(), h_list.end(), std::greater()); 31 | } 32 | 33 | [[maybe_unused]] 34 | static void clear_hashset(HashSet& hs, uint64_t threshold) 35 | { 36 | auto& h_list = hs.hashes; 37 | uint32_t min = 0, max = h_list.size(); 38 | uint32_t med = 0; 39 | 40 | while(true) 41 | { 42 | med = (max + min) / 2; 43 | if (max == min) 44 | { 45 | break; 46 | } 47 | 48 | if (h_list[med].index > threshold) 49 | { 50 | min = med + 1; 51 | } 52 | else 53 | { 54 | max = med; 55 | } 56 | } 57 | h_list.resize(med); 58 | 59 | /* 60 | for (auto it = h_list.begin(); it != h_list.end();) 61 | { 62 | if (it -> index <= threshold) 63 | { 64 | it = h_list.erase(it); 65 | } else 66 | { 67 | ++it; 68 | } 69 | } */ 70 | } 71 | 72 | } -------------------------------------------------------------------------------- /cpp_contracts/genesis/deploy.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "sdk/invoke.h" 18 | #include "sdk/calldata.h" 19 | #include "sdk/contracts.h" 20 | #include "sdk/types.h" 21 | 22 | #include "genesis/deploy.h" 23 | 24 | namespace deploy 25 | { 26 | 27 | 28 | EXPORT("pub00000000") 29 | deployAndInitialize() 30 | { 31 | auto calldata_fixed = sdk::get_calldata(); 32 | 33 | uint8_t invoke_data[calldata_fixed.ctor_calldata_size]; 34 | 35 | sdk::get_calldata_slice( 36 | invoke_data, 37 | sizeof(calldata_DeployAndInitialize), 38 | sizeof(calldata_DeployAndInitialize) + calldata_fixed.ctor_calldata_size); 39 | 40 | 41 | auto deployed_addr = sdk::deploy_contract(calldata_fixed.contract_hash, calldata_fixed.nonce); 42 | 43 | sdk::invoke(deployed_addr, calldata_fixed.ctor_method, invoke_data, calldata_fixed.ctor_calldata_size); 44 | } 45 | 46 | EXPORT("pub01000000") 47 | deploy() 48 | { 49 | auto calldata = sdk::get_calldata(); 50 | 51 | sdk::deploy_contract(calldata.contract_hash, calldata.nonce); 52 | } 53 | 54 | EXPORT("pub02000000") 55 | create() 56 | { 57 | auto calldata = sdk::get_calldata(); 58 | 59 | sdk::create_contract(calldata.contract_idx); 60 | } 61 | 62 | 63 | } -------------------------------------------------------------------------------- /contract_db/uncommitted_contracts.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "metering_ffi/metered_contract.h" 20 | 21 | #include "xdr/storage.h" 22 | #include "xdr/storage_delta.h" 23 | #include "xdr/types.h" 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | namespace scs { 34 | 35 | class ContractDB; 36 | 37 | class UncommittedContracts : public utils::NonMovableOrCopyable 38 | { 39 | // map contract hash to contract 40 | std::map new_contracts; 41 | 42 | // map address to contract hash 43 | std::map new_deployments; 44 | 45 | // temporary bad solution 46 | std::mutex mtx; 47 | 48 | public: 49 | // caller must ensure script_hash exists 50 | void deploy_contract_to_address(Address const& addr, 51 | Hash const& script_hash); 52 | 53 | void undo_deploy_contract_to_address(Address const& addr); 54 | 55 | void add_new_contract(Hash const& h, metered_contract_ptr_t new_contract); 56 | 57 | void commit(ContractDB& contract_db); 58 | 59 | void clear(); 60 | }; 61 | 62 | } // namespace scs 63 | -------------------------------------------------------------------------------- /state_db/modified_keys_list.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "mtt/ephemeral_trie/atomic_ephemeral_trie.h" 20 | 21 | #include 22 | 23 | #include "xdr/types.h" 24 | 25 | #include "config/static_constants.h" 26 | 27 | namespace scs { 28 | 29 | class ModifiedKeysList 30 | { 31 | public: 32 | using value_t = trie::EmptyValue; 33 | using trie_prefix_t = trie::ByteArrayPrefix; 34 | 35 | using map_t = trie::AtomicTrie; 36 | private: 37 | map_t keys; 38 | using serial_trie_t = trie::AtomicTrieReference; 39 | 40 | using cache_t = utils::ThreadlocalCache; 41 | 42 | cache_t cache; 43 | 44 | bool logs_merged = false; 45 | 46 | void assert_logs_merged() const; 47 | void assert_logs_not_merged() const; 48 | 49 | public: 50 | void log_key(const AddressAndKey& key); 51 | 52 | void merge_logs(); 53 | 54 | const map_t& get_keys() const 55 | { 56 | assert_logs_merged(); 57 | return keys; 58 | } 59 | 60 | size_t size() const { 61 | return keys.size(); 62 | } 63 | 64 | void clear(); 65 | 66 | Hash hash(); 67 | }; 68 | 69 | } // namespace scs 70 | -------------------------------------------------------------------------------- /transaction_context/transaction_results.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "transaction_context/transaction_results.h" 18 | 19 | #include "transaction_context/error.h" 20 | 21 | namespace scs 22 | { 23 | 24 | using xdr::operator==; 25 | 26 | 27 | void 28 | TransactionResultsFrame::add_log(TransactionLog log) 29 | { 30 | results.logs.push_back(log); 31 | } 32 | 33 | void 34 | TransactionResultsFrame::add_rpc_result(RpcResult result) 35 | { 36 | if (!validating) 37 | { 38 | results.ndeterministic_results.rpc_results.push_back(result); 39 | } 40 | else 41 | { 42 | throw HostError("added rpc result when validating"); 43 | } 44 | } 45 | 46 | RpcResult 47 | TransactionResultsFrame::get_next_rpc_result() 48 | { 49 | if (rpc_idx < results.ndeterministic_results.rpc_results.size()) 50 | { 51 | auto const& out = results.ndeterministic_results.rpc_results[rpc_idx]; 52 | rpc_idx ++; 53 | return out; 54 | } 55 | else 56 | { 57 | throw HostError("insufficient rpc results stored"); 58 | } 59 | } 60 | 61 | bool 62 | TransactionResultsFrame::validating_check_all_rpc_results_used() const 63 | { 64 | if (!validating) { 65 | return true; 66 | } 67 | 68 | return (rpc_idx == results.ndeterministic_results.rpc_results.size()); 69 | } 70 | 71 | 72 | } 73 | -------------------------------------------------------------------------------- /state_db/modified_keys_list.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "state_db/modified_keys_list.h" 18 | 19 | #include "debug/debug_utils.h" 20 | 21 | namespace scs { 22 | 23 | void 24 | ModifiedKeysList::assert_logs_merged() const 25 | { 26 | if (!logs_merged) { 27 | throw std::runtime_error("logs not merged"); 28 | } 29 | } 30 | void 31 | ModifiedKeysList::assert_logs_not_merged() const 32 | { 33 | if (logs_merged) { 34 | throw std::runtime_error("logs already merged"); 35 | } 36 | } 37 | 38 | void 39 | ModifiedKeysList::log_key(const AddressAndKey& key) 40 | { 41 | assert_logs_not_merged(); 42 | auto& local_trie = cache.get(keys); 43 | local_trie.insert(key); 44 | } 45 | 46 | void 47 | ModifiedKeysList::merge_logs() 48 | { 49 | assert_logs_not_merged(); 50 | // keys.template batch_merge_in(cache); 51 | 52 | logs_merged = true; 53 | } 54 | 55 | Hash 56 | ModifiedKeysList::hash() 57 | { 58 | assert_logs_merged(); 59 | Hash out; 60 | auto h = keys.hash(); 61 | std::memcpy(out.data(), h.data(), h.size()); 62 | 63 | return out; 64 | } 65 | 66 | void 67 | ModifiedKeysList::clear() 68 | { 69 | cache.clear(); 70 | keys.clear(); 71 | logs_merged = false; 72 | } 73 | 74 | } // namespace scs -------------------------------------------------------------------------------- /cpp_contracts/genesis/deploy.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "sdk/alloc.h" 18 | #include "sdk/types.h" 19 | 20 | #include "genesis/addresses.h" 21 | 22 | namespace deploy 23 | { 24 | 25 | struct calldata_DeployAndInitialize 26 | { 27 | sdk::Hash contract_hash; 28 | uint64_t nonce; 29 | uint32_t ctor_method; 30 | uint32_t ctor_calldata_size; 31 | }; 32 | 33 | struct calldata_Deploy 34 | { 35 | sdk::Hash contract_hash; 36 | uint64_t nonce; 37 | }; 38 | 39 | struct calldata_Create 40 | { 41 | uint32_t contract_idx; 42 | }; 43 | 44 | [[maybe_unused]] 45 | static void 46 | deploy_and_initialize( 47 | sdk::Hash const& h, 48 | uint64_t nonce, 49 | uint32_t ctor_method, 50 | uint8_t const* ctor_calldata, 51 | const uint32_t ctor_calldata_len) 52 | { 53 | uint8_t calldata[sizeof(calldata_DeployAndInitialize) + ctor_calldata_len]; 54 | 55 | calldata_DeployAndInitialize& c = *reinterpret_cast(calldata); 56 | 57 | c.contract_hash = h; 58 | c.nonce = nonce; 59 | c.ctor_method = ctor_method; 60 | c.ctor_calldata_size = ctor_calldata_len; 61 | 62 | std::memcpy(calldata + sizeof(calldata_DeployAndInitialize), ctor_calldata, ctor_calldata_len); 63 | 64 | sdk::invoke(genesis::DEPLOY_ADDRESS, 0, calldata, sizeof(calldata_DeployAndInitialize) + ctor_calldata_len); 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /xdr/storage.x: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | %#include "xdr/types.h" 18 | 19 | namespace scs 20 | { 21 | 22 | enum ObjectType 23 | { 24 | RAW_MEMORY = 0, 25 | NONNEGATIVE_INT64 = 1, 26 | HASH_SET = 2, 27 | UNCONSTRAINED_INT64 = 3, 28 | KNOWN_SUPPLY_ASSET = 4, 29 | }; 30 | 31 | const RAW_MEMORY_MAX_LEN = 4096; 32 | 33 | struct RawMemoryStorage 34 | { 35 | opaque data; 36 | }; 37 | 38 | struct HashSetEntry 39 | { 40 | Hash hash; 41 | uint64 index; 42 | }; 43 | 44 | struct HashSet 45 | { 46 | HashSetEntry hashes<>; 47 | uint32 max_size; 48 | }; 49 | 50 | const MAX_HASH_SET_SIZE = 65535; 51 | const START_HASH_SET_SIZE = 64; 52 | 53 | struct AssetObject { 54 | uint64 amount; 55 | }; 56 | 57 | struct StorageObject 58 | { 59 | union switch (ObjectType type) 60 | { 61 | case RAW_MEMORY: 62 | RawMemoryStorage raw_memory_storage; 63 | case NONNEGATIVE_INT64: 64 | int64 nonnegative_int64; 65 | case HASH_SET: 66 | HashSet hash_set; 67 | case UNCONSTRAINED_INT64: 68 | int64 unconstrained_int64; 69 | case KNOWN_SUPPLY_ASSET: 70 | AssetObject asset; 71 | } body; 72 | 73 | uint64 escrowed_fee; 74 | }; 75 | 76 | // in case of none: 77 | // first ensure all are of same type -- if not, all fail 78 | // then apply the single type semantics, using default starting value 79 | 80 | } /* scs */ 81 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/rpc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/macros.h" 20 | #include "sdk/concepts.h" 21 | #include "sdk/alloc.h" 22 | #include "sdk/types.h" 23 | #include "sdk/concepts.h" 24 | 25 | #include 26 | #include 27 | 28 | namespace sdk 29 | { 30 | 31 | namespace detail 32 | { 33 | 34 | BUILTIN("external_call") 35 | void 36 | external_call( 37 | uint32_t target_addr, 38 | /* addr_len = 32 */ 39 | uint32_t call_data_offset, 40 | uint32_t call_data_len, 41 | uint32_t response_offset, 42 | uint32_t response_max_len); 43 | } 44 | 45 | template 46 | R 47 | external_call(const Address& addr, C const& calldata) 48 | { 49 | R out; 50 | 51 | detail::external_call( 52 | to_offset(&addr), 53 | to_offset(&calldata), 54 | sizeof(C), 55 | to_offset(&out), 56 | sizeof(R)); 57 | return out; 58 | } 59 | 60 | template 61 | std::vector 62 | external_call(const Address& addr, C const& calldata, uint32_t output_max_len) 63 | { 64 | std::vector out; 65 | out.resize(output_max_len); 66 | 67 | detail::external_call( 68 | to_offset(&addr), 69 | to_offset(calldata.data()), 70 | calldata.size(), 71 | to_offset(out.data()), 72 | output_max_len); 73 | return out; 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /utils/atomic_uint128.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | namespace scs 23 | { 24 | 25 | 26 | //atomic 128 that does not allow reads 27 | //without a synchronization barrier (external) 28 | class AtomicUint128 29 | { 30 | std::atomic lowbits, highbits; 31 | 32 | public: 33 | 34 | void add(uint64_t v) 35 | { 36 | uint64_t prev_lowbits = lowbits.fetch_add(v, std::memory_order_relaxed); 37 | 38 | if (__builtin_add_overflow_p(prev_lowbits, v, static_cast(0))) 39 | { 40 | highbits.fetch_add(1, std::memory_order_relaxed); 41 | } 42 | } 43 | 44 | void sub(uint64_t v) 45 | { 46 | uint64_t prev_lowbits = lowbits.fetch_sub(v, std::memory_order_relaxed); 47 | 48 | if (__builtin_sub_overflow_p(prev_lowbits, v, static_cast(0))) 49 | { 50 | highbits.fetch_sub(1, std::memory_order_relaxed); 51 | } 52 | } 53 | 54 | // returns UINT64_MAX if greater than uint64 55 | uint64_t fetch_cap() 56 | { 57 | if (highbits.load(std::memory_order_relaxed) > 0) 58 | { 59 | return UINT64_MAX; 60 | } 61 | return lowbits.load(std::memory_order_relaxed); 62 | } 63 | 64 | void clear() 65 | { 66 | highbits.store(0, std::memory_order_relaxed); 67 | lowbits.store(0, std::memory_order_relaxed); 68 | } 69 | }; 70 | 71 | } -------------------------------------------------------------------------------- /cpp_contracts/sdk/raw_memory.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/macros.h" 20 | #include "sdk/concepts.h" 21 | #include "sdk/alloc.h" 22 | #include "sdk/types.h" 23 | #include "sdk/concepts.h" 24 | #include "sdk/syscall.h" 25 | 26 | #include 27 | #include 28 | 29 | namespace sdk 30 | { 31 | 32 | 33 | template 34 | void set_raw_memory(const StorageKey& key, const T& value) 35 | { 36 | detail::builtin_syscall(SYSCALLS::RAW_MEM_SET, 37 | to_offset(key.data()), 38 | to_offset(&value), 39 | sizeof(T), 40 | 0, 0, 0); 41 | } 42 | 43 | template 44 | std::optional 45 | get_raw_memory_opt(const StorageKey& key) 46 | { 47 | std::optional out = T{}; 48 | int64_t res = detail::builtin_syscall(SYSCALLS::RAW_MEM_GET, 49 | to_offset(key.data()), 50 | to_offset(&out), 51 | sizeof(T), 0, 0, 0); 52 | 53 | if (res < 0) 54 | { 55 | return std::nullopt; 56 | } 57 | return out; 58 | } 59 | 60 | template 61 | T 62 | get_raw_memory(const StorageKey& key) 63 | { 64 | T out; 65 | int64_t res = detail::builtin_syscall(SYSCALLS::RAW_MEM_GET, 66 | to_offset(key.data()), 67 | to_offset(&out), 68 | sizeof(T), 0, 0, 0); 69 | 70 | if (res < 0) 71 | { 72 | abort(); 73 | } 74 | return out; 75 | } 76 | 77 | } /* sdk */ 78 | -------------------------------------------------------------------------------- /metering_ffi/metered_contract.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "metering_ffi/metered_contract.h" 18 | #include "crypto/hash.h" 19 | 20 | namespace scs { 21 | 22 | namespace detail { 23 | 24 | /** 25 | * Imported from the rust library under ../metering 26 | */ 27 | extern "C" 28 | { 29 | 30 | // does NOT take ownership of data 31 | metered_contract add_metering_ext(uint8_t const* data, uint32_t len); 32 | 33 | void free_metered_contract(metered_contract contract); 34 | 35 | } 36 | 37 | metered_contract timed_add_metering_ext(uint8_t const* data, uint32_t len) 38 | { 39 | auto out = add_metering_ext(data, len); 40 | return out; 41 | } 42 | 43 | } // namespace detail 44 | 45 | MeteredContract::MeteredContract(std::shared_ptr unmetered) 46 | : base(detail::timed_add_metering_ext(unmetered->data(), unmetered->size())) 47 | {} 48 | 49 | MeteredContract::~MeteredContract() 50 | { 51 | if (base.data != nullptr) { 52 | detail::free_metered_contract(base); 53 | } 54 | } 55 | 56 | 57 | RunnableScriptView 58 | MeteredContract::to_view() const 59 | { 60 | return RunnableScriptView(base.data, base.len); 61 | } 62 | 63 | Hash 64 | MeteredContract::hash() const 65 | { 66 | Hash out; 67 | hash_raw(base.data, base.len, out.data()); 68 | return out; 69 | } 70 | 71 | } // namespace scs 72 | -------------------------------------------------------------------------------- /debug/debug_macros.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "mtt/common/debug_levels.h" 20 | 21 | #define CONTRACT_DEBUG DEBUG_LEVEL_NONE 22 | #define OBJECT_DEBUG DEBUG_LEVEL_NONE 23 | #define EXECUTION_TRACE DEBUG_LEVEL_NONE 24 | 25 | #define LOG(s, ...) std::printf((std::string("%-45s") + s + "\n").c_str(), (std::string(__FILE__) + "." + std::to_string(__LINE__) + ":").c_str() __VA_OPT__(,) __VA_ARGS__) 26 | 27 | #if CONTRACT_DEBUG <= DEBUG_LEVEL_ERROR 28 | #define CONTRACT_ERROR(s, ...) LOG(s, __VA_ARGS__) 29 | #define CONTRACT_ERROR_F(s) s 30 | #else 31 | #define CONTRACT_ERROR(s, ...) (void)0 32 | #define CONTRACT_ERROR_F(s) (void)0 33 | #endif 34 | 35 | #if CONTRACT_DEBUG <= DEBUG_LEVEL_INFO 36 | #define CONTRACT_INFO(s, ...) LOG(s, __VA_ARGS__) 37 | #define CONTRACT_INFO_F(s) s 38 | #else 39 | #define CONTRACT_INFO(s, ...) (void)0 40 | #define CONTRACT_INFO_F(s) (void)0 41 | #endif 42 | 43 | #if OBJECT_DEBUG <= DEBUG_LEVEL_INFO 44 | #define OBJECT_INFO(s, ...) LOG(s, __VA_ARGS__) 45 | #define OBJECT_INFO_F(s) s 46 | #else 47 | #define OBJECT_INFO(s, ...) (void)0 48 | #define OBJECT_INFO_F(s) (void)0 49 | #endif 50 | 51 | #if EXECUTION_TRACE <= DEBUG_LEVEL_INFO 52 | #define EXEC_TRACE(s, ...) LOG(s, __VA_ARGS__) 53 | #define EXEC_TRACE_F(s) s 54 | #else 55 | #define EXEC_TRACE(s, ...) (void)0 56 | #define EXEC_TRACE_F(s) (void)0 57 | #endif 58 | 59 | -------------------------------------------------------------------------------- /contract_db/contract_utils.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "contract_db/contract_utils.h" 18 | 19 | #include "crypto/hash.h" 20 | 21 | namespace scs { 22 | 23 | 24 | // Guarantee -- no collisions on deploy contracts 25 | Address 26 | compute_contract_deploy_address(Address const& deployer_address, 27 | Hash const& contract_hash, 28 | uint64_t nonce) 29 | { 30 | std::vector bytes; 31 | bytes.insert(bytes.end(), deployer_address.begin(), deployer_address.end()); 32 | bytes.insert(bytes.end(), contract_hash.begin(), contract_hash.end()); 33 | bytes.insert(bytes.end(), 34 | reinterpret_cast(&nonce), 35 | reinterpret_cast(&nonce) + sizeof(uint64_t)); 36 | 37 | return hash_vec(bytes); 38 | } 39 | 40 | void write_uint64_t(uint8_t* out, uint64_t value) 41 | { 42 | for (size_t i = 0; i < 8; i++) 43 | { 44 | out[i] = (value >> (8*i)) & 0xFF; 45 | } 46 | } 47 | 48 | InvariantKey 49 | make_static_key( 50 | uint64_t a, 51 | uint64_t b, 52 | uint64_t c, 53 | uint64_t d) 54 | { 55 | InvariantKey out; 56 | write_uint64_t(out.data(), a); 57 | write_uint64_t(out.data() + 8, b); 58 | write_uint64_t(out.data() + 16, c); 59 | write_uint64_t(out.data() + 24, d); 60 | return out; 61 | } 62 | 63 | } // namespace scs 64 | -------------------------------------------------------------------------------- /threadlocal/threadlocal_context.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "threadlocal/threadlocal_context.h" 18 | 19 | #include "transaction_context/global_context.h" 20 | 21 | #include "transaction_context/transaction_context.h" 22 | #include "transaction_context/execution_context.h" 23 | 24 | #define TLC_TEMPLATE 25 | #define TLC_DECL ThreadlocalContextStore 26 | 27 | namespace scs { 28 | 29 | TLC_TEMPLATE 30 | uint64_t 31 | TLC_DECL::get_uid() 32 | { 33 | return cache.get().uid.get(); 34 | } 35 | 36 | TLC_TEMPLATE 37 | void 38 | TLC_DECL::stop_rpcs() 39 | { 40 | auto& ctxs = cache.get_objects(); 41 | for (auto& ctx : ctxs) { 42 | if (ctx) { 43 | ctx -> rpc.cancel_and_set_disallowed(); 44 | } 45 | } 46 | } 47 | 48 | TLC_TEMPLATE 49 | void 50 | TLC_DECL::enable_rpcs() 51 | { 52 | auto& ctxs = cache.get_objects(); 53 | for (auto& ctx : ctxs) { 54 | if (ctx) { 55 | ctx -> rpc.set_allowed(); 56 | } 57 | } 58 | } 59 | 60 | #if USE_RPC 61 | 62 | TLC_TEMPLATE 63 | std::optional 64 | TLC_DECL::send_cancellable_rpc(std::unique_ptr 65 | const& stub, RpcCall const& call) 66 | { 67 | auto& ctx = cache.get(); 68 | uint64_t uid = ctx.uid.get(); 69 | 70 | return ctx.rpc.send_query(call, uid, stub); 71 | } 72 | 73 | #endif 74 | 75 | #undef TLC_DECL 76 | #undef TLC_TEMPLATE 77 | 78 | } // namespace scs 79 | -------------------------------------------------------------------------------- /block_assembly/limits.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "block_assembly/limits.h" 18 | 19 | namespace scs { 20 | 21 | std::optional 22 | AssemblyLimits::reserve_tx(SignedTransaction const& tx) 23 | { 24 | if (tx.tx.gas_limit > gas_limit_per_tx) { 25 | return std::nullopt; 26 | } 27 | 28 | int64_t res = max_txs.fetch_sub(1, std::memory_order_relaxed); 29 | if (res <= 0) { 30 | max_txs.fetch_add(1, std::memory_order_relaxed); 31 | return std::nullopt; 32 | } 33 | 34 | // can cause spurious failures, but that's ok 35 | res = overall_gas_limit.fetch_sub(tx.tx.gas_limit, 36 | std::memory_order_relaxed); 37 | if (res <= 0) { 38 | overall_gas_limit.fetch_add(tx.tx.gas_limit, std::memory_order_relaxed); 39 | return std::nullopt; 40 | } 41 | 42 | return std::make_optional(tx.tx.gas_limit, *this); 43 | } 44 | 45 | void 46 | AssemblyLimits::notify_done() 47 | { 48 | std::lock_guard lock(mtx); 49 | shutdown = true; 50 | cv.notify_one(); 51 | } 52 | 53 | void 54 | AssemblyLimits::wait_for(std::chrono::milliseconds timeout) 55 | { 56 | std::unique_lock lock(mtx); 57 | 58 | auto done = [this]() { return shutdown; }; 59 | 60 | if (done()) { 61 | return; 62 | } 63 | 64 | cv.wait_for(lock, timeout, done); 65 | } 66 | 67 | } // namespace scs 68 | -------------------------------------------------------------------------------- /vm/genesis.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "vm/genesis.h" 18 | 19 | #include "contract_db/contract_db.h" 20 | #include "contract_db/contract_db_proxy.h" 21 | 22 | #include "storage_proxy/transaction_rewind.h" 23 | 24 | #include "utils/load_wasm.h" 25 | 26 | #include "cpp_contracts/sdk/shared.h" 27 | 28 | namespace scs { 29 | 30 | Address 31 | make_address(uint64_t a, uint64_t b, uint64_t c, uint64_t d) 32 | { 33 | auto buf = make_static_32bytes>(a, b, c, d); 34 | Address out; 35 | std::memcpy(out.data(), buf.data(), out.size()); 36 | return out; 37 | } 38 | 39 | void 40 | install_contract(ContractDBProxy& db, 41 | std::shared_ptr contract, 42 | const Address& addr) 43 | { 44 | auto h = db.create_contract(contract); 45 | db.deploy_contract_at_specific_address(addr, h); 46 | } 47 | 48 | void 49 | install_genesis_contracts(ContractDB& contract_db) 50 | { 51 | ContractDBProxy proxy(contract_db); 52 | 53 | // address registry should mirror cpp_contracts/genesis/addresses.h 54 | install_contract(proxy, 55 | load_wasm_from_file("cpp_contracts/genesis/deploy.wasm"), 56 | DEPLOYER_ADDRESS); 57 | 58 | { 59 | TransactionRewind rewind; 60 | 61 | proxy.push_updates_to_db(rewind); 62 | 63 | rewind.commit(); 64 | } 65 | 66 | contract_db.commit(0); 67 | } 68 | 69 | } // namespace scs 70 | -------------------------------------------------------------------------------- /tx_block/tests/test_unique_txset.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | 19 | #include "tx_block/unique_tx_set.h" 20 | #include "xdr/transaction.h" 21 | #include "crypto/hash.h" 22 | 23 | namespace scs { 24 | 25 | TEST_CASE("test unique txset", "[txset]") 26 | { 27 | UniqueTxSet set; 28 | 29 | auto add_tx = [&] (SignedTransaction const& stx) 30 | { 31 | auto h = hash_xdr(stx); 32 | return set.try_add_transaction(h, stx, NondeterministicResults()); 33 | }; 34 | 35 | auto simple_make_unique_tx = [] (uint64_t nonce) { 36 | 37 | SignedTransaction t; 38 | t.tx.gas_limit = nonce; 39 | return t; 40 | }; 41 | 42 | SECTION("single inserts good") 43 | { 44 | REQUIRE(add_tx(simple_make_unique_tx(0))); 45 | REQUIRE(add_tx(simple_make_unique_tx(1))); 46 | REQUIRE(add_tx(simple_make_unique_tx(2))); 47 | 48 | set.finalize(); 49 | 50 | Block b; 51 | set.serialize_block(b); 52 | 53 | REQUIRE(b.transactions.size() == 3); 54 | } 55 | SECTION("double inserts bad") 56 | { 57 | REQUIRE(add_tx(simple_make_unique_tx(0))); 58 | REQUIRE(add_tx(simple_make_unique_tx(1))); 59 | REQUIRE(!add_tx(simple_make_unique_tx(1))); 60 | 61 | set.finalize(); 62 | 63 | Block b; 64 | set.serialize_block(b); 65 | 66 | REQUIRE(b.transactions.size() == 2); 67 | } 68 | } 69 | 70 | } // namespace scs 71 | -------------------------------------------------------------------------------- /storage_proxy/transaction_rewind.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | 21 | #include "contract_db/contract_db_proxy.h" 22 | #include "object/revertable_object.h" 23 | 24 | namespace scs { 25 | 26 | namespace detail { 27 | 28 | template 29 | class RewindVector; 30 | 31 | template 32 | class RewindVector : public RewindVector 33 | { 34 | std::vector objs; 35 | 36 | public: 37 | template::value>::type* = nullptr> 39 | void add(acc&& new_obj) 40 | { 41 | objs.emplace_back(std::move(new_obj)); 42 | } 43 | 44 | template::value>::type* = nullptr> 46 | void add(acc&& new_obj) 47 | { 48 | RewindVector::add(std::move(new_obj)); 49 | } 50 | 51 | void commit() 52 | { 53 | for (auto& obj : objs) { 54 | obj.commit(); 55 | } 56 | RewindVector::commit(); 57 | } 58 | }; 59 | 60 | template<> 61 | class RewindVector<> 62 | { 63 | public: 64 | void commit() {} 65 | }; 66 | 67 | } // namespace detail 68 | 69 | struct TransactionRewind 70 | : public detail::RewindVector 73 | {}; 74 | 75 | } // namespace scs 76 | -------------------------------------------------------------------------------- /object/object_defaults.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "object/object_defaults.h" 18 | 19 | #include 20 | 21 | namespace scs 22 | { 23 | 24 | StorageObject 25 | object_from_delta_class(StorageDeltaClass const& dc, std::optional const& prev_object) 26 | { 27 | StorageObject out; 28 | out.body.type(dc.type()); 29 | 30 | if (prev_object) 31 | { 32 | if (prev_object -> body.type() != out.body.type()) 33 | { 34 | throw std::runtime_error("type mismatch in object_from_delta_class"); 35 | } 36 | } 37 | switch(out.body.type()) 38 | { 39 | case ObjectType::RAW_MEMORY: 40 | { 41 | out.body.raw_memory_storage().data = dc.data(); 42 | break; 43 | } 44 | case ObjectType::NONNEGATIVE_INT64: 45 | { 46 | out.body.nonnegative_int64() = dc.nonnegative_int64(); 47 | break; 48 | } 49 | case ObjectType::HASH_SET: 50 | { 51 | out.body.hash_set().max_size = START_HASH_SET_SIZE; 52 | 53 | if (prev_object) 54 | { 55 | out.body.hash_set().max_size = prev_object -> body.hash_set().max_size; 56 | out.body.hash_set().hashes = prev_object -> body.hash_set().hashes; 57 | } 58 | break; 59 | } 60 | case ObjectType::KNOWN_SUPPLY_ASSET: 61 | { 62 | out.body.asset().amount = 0; 63 | if (prev_object) 64 | { 65 | out.body.asset().amount = prev_object -> body.asset().amount; 66 | } 67 | break; 68 | } 69 | break; 70 | default: 71 | throw std::runtime_error("unimpl sdc object_defaults.cc"); 72 | } 73 | return out; 74 | } 75 | 76 | } /* scs */ 77 | -------------------------------------------------------------------------------- /contract_db/uncommitted_contracts.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "contract_db/uncommitted_contracts.h" 18 | #include "contract_db/contract_db.h" 19 | 20 | #include "crypto/hash.h" 21 | 22 | namespace scs { 23 | 24 | void 25 | UncommittedContracts::deploy_contract_to_address( 26 | Address const& addr, 27 | Hash const& script_hash) 28 | { 29 | std::lock_guard lock(mtx); 30 | 31 | new_deployments.emplace(addr, script_hash); 32 | } 33 | 34 | void 35 | UncommittedContracts::undo_deploy_contract_to_address( 36 | Address const& addr) 37 | { 38 | std::lock_guard lock(mtx); 39 | 40 | new_deployments.erase(addr); 41 | } 42 | 43 | void 44 | UncommittedContracts::add_new_contract( 45 | Hash const& h, 46 | metered_contract_ptr_t new_contract) 47 | { 48 | std::lock_guard lock(mtx); 49 | 50 | auto [_, inserted] = new_contracts.emplace(h, new_contract); 51 | 52 | if (!inserted) 53 | { 54 | throw std::runtime_error("invalid add_new_contract (already existed)"); 55 | } 56 | } 57 | 58 | void 59 | UncommittedContracts::clear() 60 | { 61 | new_contracts.clear(); 62 | new_deployments.clear(); 63 | } 64 | 65 | void 66 | UncommittedContracts::commit(ContractDB& contract_db) 67 | { 68 | for (auto const& [hash, script] : new_contracts) { 69 | contract_db.commit_contract_to_db(hash, script); 70 | } 71 | 72 | for (auto const& [addr, hash] : new_deployments) { 73 | contract_db.commit_registration(addr, hash); 74 | } 75 | clear(); 76 | } 77 | 78 | } // namespace scs 79 | -------------------------------------------------------------------------------- /persistence/accumulate_kvs_iface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "mtt/memcached_snapshot_trie/durable_interface.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include "persistence/rocksdb_wrapper.h" 14 | 15 | 16 | namespace scs { 17 | 18 | template 19 | class AccumulateKVsInterface 20 | { 21 | public: 22 | constexpr static uint8_t KEY_LEN_BYTES = _KEY_LEN_BYTES; 23 | using result_t = trie::DurableResult; 24 | using value_t = trie::DurableValue; 25 | using pair_t = std::pair; 26 | 27 | private: 28 | utils::ThreadlocalCache, TLCACHE_SIZE> cache; 29 | RocksdbWrapper& rdb; 30 | 31 | public: 32 | 33 | AccumulateKVsInterface(RocksdbWrapper& rdb) 34 | : cache() 35 | , rdb(rdb) 36 | {} 37 | 38 | void log_durable_value(trie::TimestampPointerPair const& key, 39 | trie::DurableValue const& value) 40 | { 41 | auto& buf = cache.get(); 42 | buf.emplace_back(key, value); 43 | } 44 | 45 | result_t restore_durable_value(trie::TimestampPointerPair const& key) const 46 | { 47 | auto const* ptr = reinterpret_cast(&key); 48 | 49 | result_t out; 50 | 51 | auto& data = out.get_backing_data(); 52 | 53 | rocksdb::Slice key_slice(ptr, sizeof(trie::TimestampPointerPair)); 54 | 55 | rdb.get(key_slice, data); 56 | 57 | return out; 58 | } 59 | 60 | void swap_buffers(std::array, TLCACHE_SIZE>& old_buffers) { 61 | auto& bufs = cache.get_objects(); 62 | for (size_t i = 0; i < TLCACHE_SIZE; i++) 63 | { 64 | if (!bufs[i]) 65 | { 66 | bufs[i].emplace(); 67 | } 68 | std::swap(*bufs[i], old_buffers[i]); 69 | } 70 | } 71 | }; 72 | 73 | } // namespace scs 74 | -------------------------------------------------------------------------------- /threadlocal/gc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | namespace scs { 23 | 24 | template 25 | class GarbageCollector 26 | { 27 | 28 | std::vector> ptrs_to_gc; 29 | 30 | public: 31 | void deferred_delete(const T* ptr) 32 | { 33 | ptrs_to_gc.push_back(std::unique_ptr(ptr)); 34 | } 35 | 36 | void post_block_clear() { ptrs_to_gc.clear(); } 37 | }; 38 | 39 | template 40 | class MultitypeGarbageCollector; 41 | 42 | template 43 | class MultitypeGarbageCollector 44 | : public MultitypeGarbageCollector 45 | { 46 | GarbageCollector gc; 47 | 48 | public: 49 | template::value>::type* = nullptr> 51 | void deferred_delete(const delete_t* ptr) 52 | { 53 | gc.deferred_delete(ptr); 54 | } 55 | 56 | template::value>::type* = nullptr> 58 | void deferred_delete(const delete_t* ptr) 59 | { 60 | MultitypeGarbageCollector::deferred_delete(ptr); 61 | } 62 | 63 | void post_block_clear() 64 | { 65 | gc.post_block_clear(); 66 | MultitypeGarbageCollector::post_block_clear(); 67 | } 68 | }; 69 | 70 | template<> 71 | class MultitypeGarbageCollector<> 72 | { 73 | public: 74 | void post_block_clear() {} 75 | }; 76 | 77 | } // namespace scs 78 | -------------------------------------------------------------------------------- /vm/groundhog_vm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "transaction_context/global_context.h" 20 | 21 | #include 22 | #include 23 | 24 | #include "xdr/transaction.h" 25 | #include "xdr/block.h" 26 | 27 | #include 28 | 29 | #include "vm/base_vm.h" 30 | 31 | #include "mempool/mempool.h" 32 | 33 | #include "state_db/async_keys_to_disk.h" 34 | 35 | //#include "persistence/async_rdb_bulkload.h" 36 | 37 | 38 | namespace scs { 39 | 40 | class AssemblyLimits; 41 | 42 | /** 43 | * Block policy: 44 | * Header is 45 | * We reject a block if prev_hash doesn't match our hash, 46 | * but if we execute a block and find no errors 47 | * but find a hash mismatch at the end, 48 | * we say that's ok, and move on (presumably rejecting subsequent 49 | * blocks from that proposer). 50 | * 51 | * Groundhog version, no persistence 52 | */ 53 | 54 | class GroundhogVirtualMachine : public BaseVirtualMachine 55 | { 56 | 57 | AsyncKeysToDisk keys_persist; 58 | //AsyncRDBBulkLoad keys_persist; 59 | 60 | public: 61 | 62 | GroundhogVirtualMachine() 63 | : BaseVirtualMachine() 64 | , keys_persist()//global_context.state_db.get_rdb()) 65 | {} 66 | 67 | BlockHeader propose_tx_block(AssemblyLimits& limits, uint64_t max_time_ms, uint32_t n_threads, Block& out); 68 | 69 | std::optional 70 | try_exec_tx_block(Block const& txs); 71 | }; 72 | 73 | 74 | } // namespace scs 75 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/crypto.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/macros.h" 20 | #include "sdk/concepts.h" 21 | #include "sdk/alloc.h" 22 | #include "sdk/types.h" 23 | #include "sdk/concepts.h" 24 | #include "sdk/syscall.h" 25 | 26 | #include 27 | #include 28 | 29 | namespace sdk 30 | { 31 | 32 | Hash hash(uint8_t const* data, uint32_t size) 33 | { 34 | Hash out; 35 | detail::builtin_syscall(SYSCALLS::HASH, 36 | to_offset(data), size, to_offset(out.data()), 0, 0, 0); 37 | return out; 38 | } 39 | 40 | template 41 | Hash hash(T const& object) 42 | { 43 | return hash(object.data(), object.size()); 44 | } 45 | 46 | template 47 | void hash(T const& object, StorageKey& out) 48 | { 49 | detail::builtin_syscall(SYSCALLS::HASH, 50 | to_offset(object.data()), object.size(), to_offset(out.data()), 51 | 0, 0, 0); 52 | } 53 | 54 | template 55 | Hash hash(T const& obj) 56 | { 57 | return hash(reinterpret_cast(&obj), sizeof(T)); 58 | } 59 | 60 | template 61 | void hash(T const& obj, StorageKey& out) 62 | { 63 | detail::builtin_syscall(SYSCALLS::HASH, 64 | to_offset(&obj), sizeof(T), to_offset(out.data()), 65 | 0, 0, 0); 66 | } 67 | 68 | template 69 | bool 70 | check_sig_ed25519( 71 | const PublicKey& pk, 72 | const Signature& sig, 73 | const msg& m) 74 | { 75 | return detail::builtin_syscall(SYSCALLS::VERIFY_ED25519, 76 | to_offset(pk.data()), 77 | to_offset(sig.data()), 78 | to_offset(&m), 79 | sizeof(msg), 80 | 0, 0) != 0; 81 | } 82 | 83 | } /* sdk */ 84 | -------------------------------------------------------------------------------- /sisyphus_vm/vm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "transaction_context/global_context.h" 20 | 21 | #include 22 | #include 23 | 24 | #include "xdr/transaction.h" 25 | #include "xdr/block.h" 26 | 27 | #include 28 | 29 | #include "mempool/mempool.h" 30 | 31 | #include "state_db/async_keys_to_disk.h" 32 | 33 | #include "block_assembly/assembly_worker.h" 34 | 35 | #include "vm/base_vm.h" 36 | 37 | namespace scs { 38 | 39 | class AssemblyLimits; 40 | 41 | /** 42 | * Block policy: 43 | * Header is 44 | * We reject a block if prev_hash doesn't match our hash, 45 | * but if we execute a block and find no errors 46 | * but find a hash mismatch at the end, 47 | * we say that's ok, and move on (presumably rejecting subsequent 48 | * blocks from that proposer). 49 | * 50 | * Sisyphus version 51 | */ 52 | class SisyphusVirtualMachine : public BaseVirtualMachine 53 | { 54 | 55 | AsyncKeysToDisk keys_persist; 56 | 57 | public: 58 | SisyphusVirtualMachine() 59 | : BaseVirtualMachine() 60 | , keys_persist() 61 | {} 62 | 63 | std::optional 64 | try_exec_tx_block(Block const& txs); 65 | 66 | BlockHeader propose_tx_block(AssemblyLimits& limits, uint64_t max_time_ms, uint32_t n_threads, Block& out, ModIndexLog& out_modlog, 67 | std::unique_ptr* extract_block_context = nullptr); 68 | 69 | const auto& get_global_context() const { 70 | return global_context; 71 | } 72 | }; 73 | 74 | } // namespace scs 75 | -------------------------------------------------------------------------------- /threadlocal/rate_limiter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | namespace scs { 25 | 26 | class RateLimiter 27 | { 28 | // threads overall running, possibly not with slots 29 | // std::atomic running_threads = 0; 30 | 31 | // threads with slots 32 | std::atomic active_threads = 0; 33 | std::atomic max_active_threads = 0; 34 | 35 | std::atomic _shutdown = false; 36 | 37 | std::condition_variable wake_cond; 38 | std::mutex mtx; 39 | 40 | inline static thread_local bool has_slot = false; 41 | 42 | // std::condition_variable join_cond; 43 | 44 | void shutdown() 45 | { 46 | _shutdown = true; 47 | wake_cond.notify_all(); 48 | } 49 | 50 | // void notify_join() 51 | // { 52 | // if (active_threads.load(std::memory_order_relaxed) == 0) { 53 | // std::lock_guard lock(mtx); 54 | // join_cond.notify_one(); 55 | // } 56 | // } 57 | 58 | bool fastpath_wait_for_opening(); 59 | bool slowpath_wait_for_opening(); 60 | 61 | inline static std::atomic unique_init = false; 62 | 63 | public: 64 | RateLimiter(); 65 | 66 | bool wait_for_opening(); 67 | 68 | void notify(); 69 | 70 | void claim_one_slot(); 71 | void free_one_slot(); 72 | 73 | void start_threads(uint64_t max_active); 74 | 75 | void prep_for_notify(); 76 | 77 | void stop_threads(); 78 | 79 | // void join_threads(); 80 | 81 | // ~RateLimiter() { join_threads(); } 82 | }; 83 | 84 | } // namespace scs 85 | -------------------------------------------------------------------------------- /tx_block/unique_tx_set.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "mtt/common/prefix.h" 20 | #include "mtt/ephemeral_trie/atomic_ephemeral_trie.h" 21 | 22 | #include 23 | 24 | #include "xdr/transaction.h" 25 | #include "xdr/types.h" 26 | #include "xdr/block.h" 27 | 28 | #include 29 | 30 | #include 31 | 32 | #include "config/static_constants.h" 33 | 34 | #include "mtt/trie/utils.h" 35 | 36 | namespace scs { 37 | 38 | class UniqueTxSet 39 | { 40 | static std::vector serialize(const TxSetEntry& v) 41 | { 42 | return xdr::xdr_to_opaque(v); 43 | } 44 | 45 | friend struct UniqueInsertFn; 46 | 47 | 48 | using value_t = trie::XdrTypeWrapper; 49 | 50 | using prefix_t = trie::ByteArrayPrefix; 51 | 52 | using map_t = trie::AtomicTrie; 53 | 54 | map_t txs; 55 | 56 | using cache_t = utils::ThreadlocalCache, TLCACHE_SIZE>; 57 | 58 | cache_t cache; 59 | 60 | bool txs_merged = false; 61 | 62 | void assert_txs_merged() const; 63 | void assert_txs_not_merged() const; 64 | 65 | public: 66 | 67 | bool try_add_transaction(const Hash& hash, const SignedTransaction& tx, const NondeterministicResults& nres); 68 | 69 | void finalize(); 70 | 71 | void serialize_block(Block& out) const; 72 | 73 | Hash hash(); 74 | 75 | void clear(); 76 | 77 | // for testing 78 | 79 | bool contains_tx(const Hash& hash) const 80 | { 81 | auto const* r = txs.get_value(hash); 82 | 83 | return (r != nullptr); 84 | } 85 | }; 86 | 87 | } // namespace scs 88 | -------------------------------------------------------------------------------- /utils/recycling_allocator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | namespace scs 25 | { 26 | 27 | template 28 | class RecyclingAllocatorLine : public utils::NonMovableOrCopyable 29 | { 30 | void* buffer; 31 | 32 | constexpr static size_t BUF_SIZE_BYTES = sizeof(T) * BUFFER_SIZE; 33 | 34 | std::atomic active_size; 35 | 36 | uint32_t prev_active_size; 37 | 38 | public: 39 | 40 | RecyclingAllocatorLine() 41 | : buffer(malloc(BUF_SIZE_BYTES)) 42 | , active_size(0) 43 | , prev_active_size(0) 44 | {} 45 | 46 | T* 47 | allocate() 48 | { 49 | uint32_t slot = active_size.fetch_add(1, std::memory_order_relaxed); 50 | 51 | if (slot >= BUFFER_SIZE) 52 | { 53 | return nullptr; 54 | } 55 | 56 | T* ptr = (static_cast(buffer) + slot); 57 | 58 | if (slot < prev_active_size) 59 | { 60 | ptr -> ~T(); 61 | } 62 | 63 | return new (static_cast(ptr)) T(); 64 | } 65 | 66 | void clear_and_reset() 67 | { 68 | prev_active_size = std::max(prev_active_size, active_size.load(std::memory_order_relaxed)); 69 | active_size = 0; 70 | } 71 | 72 | ~RecyclingAllocatorLine() 73 | { 74 | clear_and_reset(); 75 | 76 | for (uint32_t i = 0; i < std::min(prev_active_size, BUFFER_SIZE); i++) 77 | { 78 | T* ptr = (static_cast(buffer) + i); 79 | ptr -> ~T(); 80 | } 81 | 82 | free(buffer); 83 | } 84 | }; 85 | 86 | 87 | 88 | 89 | } -------------------------------------------------------------------------------- /block_assembly/limits.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "xdr/transaction.h" 27 | 28 | #include 29 | 30 | namespace scs { 31 | 32 | class AssemblyLimits 33 | { 34 | std::atomic max_txs; 35 | std::atomic overall_gas_limit; 36 | 37 | const uint64_t gas_limit_per_tx = 10'000'000; 38 | 39 | void undo_tx_reservation(uint64_t gas) 40 | { 41 | max_txs.fetch_add(1, std::memory_order_relaxed); 42 | overall_gas_limit.fetch_add(gas, std::memory_order_relaxed); 43 | } 44 | 45 | std::mutex mtx; 46 | std::condition_variable cv; 47 | bool shutdown = false; 48 | 49 | public: 50 | AssemblyLimits(int64_t max_txs, int64_t overall_gas_limit) 51 | : max_txs(max_txs) 52 | , overall_gas_limit(overall_gas_limit) 53 | {} 54 | 55 | class Reservation : public utils::NonMovableOrCopyable 56 | { 57 | uint64_t gas; 58 | AssemblyLimits& main; 59 | 60 | public: 61 | Reservation(uint64_t gas, AssemblyLimits& main) 62 | : gas(gas) 63 | , main(main) 64 | {} 65 | 66 | void commit() { gas = 0; } 67 | 68 | ~Reservation() 69 | { 70 | if (gas > 0) { 71 | main.undo_tx_reservation(gas); 72 | } 73 | } 74 | }; 75 | 76 | void notify_done(); 77 | 78 | std::optional reserve_tx(SignedTransaction const& tx); 79 | 80 | void wait_for(std::chrono::milliseconds timeout); 81 | }; 82 | 83 | } // namespace scs 84 | -------------------------------------------------------------------------------- /experiments/payment_experiment.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "vm/vm.h" 20 | #include "sisyphus_vm/vm.h" 21 | #include "vm/groundhog_vm.h" 22 | 23 | #include "xdr/types.h" 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | namespace scs { 30 | 31 | class PaymentExperiment 32 | { 33 | size_t num_accounts; 34 | uint16_t hs_size_inc; 35 | 36 | struct account_entry 37 | { 38 | PublicKey pk; 39 | SecretKey sk; 40 | Address wallet_address; 41 | }; 42 | 43 | std::mutex mtx; 44 | 45 | std::map account_map; 46 | 47 | TxSetEntry make_deploy_wallet_transaction( 48 | size_t idx, 49 | Hash const& wallet_contract_hash, 50 | Address const& token_addr, 51 | uint16_t size_inc); 52 | 53 | std::pair, std::vector> 54 | make_accounts_and_mints(const char* erc20_contract); 55 | 56 | SignedTransaction make_random_payment(uint64_t expiration_time, 57 | uint64_t nonce, 58 | std::minstd_rand& gen); 59 | 60 | public: 61 | PaymentExperiment(size_t num_accounts, uint16_t hs_size_inc = 0); 62 | 63 | std::unique_ptr prepare_vm(); 64 | std::unique_ptr prepare_sisyphus_vm(); 65 | std::unique_ptr prepare_groundhog_vm(); 66 | 67 | std::vector get_active_key_set(); 68 | 69 | std::vector gen_transaction_batch( 70 | size_t batch_size, 71 | uint64_t expiration_time = UINT64_MAX); 72 | }; 73 | 74 | } // namespace scs 75 | -------------------------------------------------------------------------------- /persistence/async_rdb_bulkload.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include "utils/save_load_xdr.h" 9 | 10 | #include 11 | 12 | #include "config/static_constants.h" 13 | 14 | #include "persistence/accumulate_kvs_iface.h" 15 | 16 | #include "persistence/rocksdb_wrapper.h" 17 | 18 | namespace scs { 19 | 20 | class AsyncRDBBulkLoad : public utils::AsyncWorker 21 | { 22 | 23 | using pair_t = std::pair>; 24 | 25 | std::array, TLCACHE_SIZE> work_item; 26 | bool work_done = true; 27 | uint32_t work_ts = 0; 28 | 29 | RocksdbWrapper& rdb; 30 | 31 | bool exists_work_to_do() override final { return !work_done; } 32 | 33 | void run() 34 | { 35 | while (true) { 36 | std::unique_lock lock(mtx); 37 | 38 | if ((!done_flag) && (!exists_work_to_do())) { 39 | cv.wait(lock, 40 | [this]() { return done_flag || exists_work_to_do(); }); 41 | } 42 | if (done_flag) { 43 | return; 44 | } 45 | 46 | throw std::runtime_error("unimpl"); 47 | 48 | //TODO 49 | 50 | work_done = true; 51 | cv.notify_all(); 52 | } 53 | } 54 | 55 | public: 56 | AsyncRDBBulkLoad(RocksdbWrapper& rdb) 57 | : utils::AsyncWorker() 58 | , work_item() 59 | , rdb(rdb) 60 | { 61 | start_async_thread([this] { run(); }); 62 | } 63 | 64 | ~AsyncRDBBulkLoad() { terminate_worker(); } 65 | 66 | void log_keys(AccumulateKVsInterface& storage_iface, uint32_t timestamp) 67 | { 68 | std::lock_guard lock(mtx); 69 | storage_iface.swap_buffers(work_item); 70 | work_done = false; 71 | work_ts = timestamp; 72 | cv.notify_all(); 73 | } 74 | 75 | void log_keys(DirectWriteRocksDBIface const& rdb, uint32_t timestamp) 76 | {} 77 | 78 | void log_keys(trie::NullInterface& iface, uint32_t timestamp) 79 | {} 80 | 81 | using AsyncWorker::wait_for_async_task; 82 | }; 83 | 84 | } // namespace scs 85 | -------------------------------------------------------------------------------- /vm/base_vm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "transaction_context/global_context.h" 20 | 21 | #include 22 | #include 23 | 24 | #include "xdr/transaction.h" 25 | #include "xdr/block.h" 26 | 27 | #include 28 | 29 | #include "mempool/mempool.h" 30 | #include "block_assembly/assembly_worker.h" 31 | 32 | namespace scs { 33 | 34 | class AssemblyLimits; 35 | 36 | template 37 | class BaseVirtualMachine : public utils::NonMovableOrCopyable 38 | { 39 | protected: 40 | GlobalContext_t global_context; 41 | std::unique_ptr current_block_context; 42 | Mempool mempool; 43 | 44 | AssemblyWorkerCache worker_cache; 45 | 46 | Hash prev_block_hash; 47 | 48 | using TransactionContext_t = typename BlockContext_t::tx_context_t; 49 | 50 | private: 51 | utils::ThreadlocalCache, TLCACHE_SIZE> executors; 52 | 53 | protected: 54 | 55 | void assert_initialized() const; 56 | 57 | bool validate_tx_block(Block const& txs); 58 | 59 | void advance_block_number(); 60 | 61 | BlockHeader make_block_header(); 62 | 63 | public: 64 | BaseVirtualMachine() 65 | : global_context() 66 | , current_block_context() 67 | , mempool() 68 | , worker_cache(mempool, global_context) 69 | , prev_block_hash() 70 | , executors() 71 | {} 72 | 73 | void init_default_genesis(); 74 | 75 | std::optional 76 | try_exec_tx_block(Block const& txs); 77 | 78 | Mempool& get_mempool() { 79 | return mempool; 80 | } 81 | 82 | uint64_t get_current_block_number() const; 83 | 84 | ~BaseVirtualMachine(); 85 | }; 86 | 87 | } // namespace scs 88 | -------------------------------------------------------------------------------- /cpp_contracts/payment_experiment/payment.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "erc20.h" 18 | 19 | #include "sdk/replay_cache.h" 20 | #include "sdk/semaphore.h" 21 | #include "sdk/constexpr.h" 22 | #include "sdk/raw_memory.h" 23 | #include "sdk/invoke.h" 24 | #include "sdk/calldata.h" 25 | #include "sdk/auth_singlekey.h" 26 | #include "sdk/log.h" 27 | 28 | namespace payment 29 | { 30 | 31 | struct calldata_init 32 | { 33 | sdk::Address token; 34 | sdk::PublicKey pk; 35 | uint16_t size_increase; 36 | }; 37 | 38 | constexpr static sdk::StorageKey token_addr = sdk::make_static_key(0, 2); 39 | 40 | EXPORT("pub00000000") 41 | init() 42 | { 43 | sdk::Semaphore init_semaphore(sdk::make_static_key(1, 2)); 44 | init_semaphore.acquire(); 45 | 46 | auto calldata = sdk::get_calldata(); 47 | if (sdk::get_raw_memory_opt(token_addr)) 48 | { 49 | abort(); 50 | } 51 | 52 | sdk::set_raw_memory(token_addr, calldata.token); 53 | 54 | sdk::auth_single_pk_register(calldata.pk); 55 | 56 | erc20::Ierc20 token(calldata.token); 57 | 58 | token.allowanceDelta(sdk::get_self(), INT64_MAX); 59 | 60 | sdk::replay_cache_size_increase(calldata.size_increase); 61 | } 62 | 63 | struct calldata_transfer 64 | { 65 | sdk::Address to; 66 | int64_t amount; 67 | uint64_t nonce; 68 | uint64_t expiration_time; 69 | }; 70 | 71 | EXPORT("pub01000000") 72 | transfer() 73 | { 74 | auto calldata = sdk::get_calldata(); 75 | 76 | sdk::record_self_replay(calldata.expiration_time); 77 | 78 | sdk::auth_single_pk_check_sig(0); 79 | 80 | auto token_key = sdk::get_raw_memory(token_addr); 81 | 82 | erc20::Ierc20 token(token_key); 83 | 84 | token.transferFrom(sdk::get_self(), calldata.to, calldata.amount); 85 | } 86 | 87 | } -------------------------------------------------------------------------------- /object/make_delta.cc: -------------------------------------------------------------------------------- 1 | #include "object/make_delta.h" 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | namespace scs { 20 | 21 | StorageDelta 22 | make_raw_memory_write(xdr::opaque_vec&& data) 23 | { 24 | StorageDelta d; 25 | d.type(DeltaType::RAW_MEMORY_WRITE); 26 | d.data() = std::move(data); 27 | return d; 28 | } 29 | 30 | StorageDelta 31 | make_delete_last() 32 | { 33 | StorageDelta d; 34 | d.type(DeltaType::DELETE_LAST); 35 | return d; 36 | } 37 | 38 | StorageDelta 39 | make_nonnegative_int64_set_add(int64_t set, int64_t add) 40 | { 41 | StorageDelta d; 42 | d.type(DeltaType::NONNEGATIVE_INT64_SET_ADD); 43 | d.set_add_nonnegative_int64().set_value = set; 44 | d.set_add_nonnegative_int64().delta = add; 45 | return d; 46 | } 47 | 48 | StorageDelta 49 | make_hash_set_insert(Hash const& h, uint64_t threshold) 50 | { 51 | StorageDelta d; 52 | d.type(DeltaType::HASH_SET_INSERT); 53 | d.hash() = HashSetEntry(h, threshold); 54 | return d; 55 | } 56 | 57 | StorageDelta 58 | make_hash_set_insert(HashSetEntry const& entry) 59 | { 60 | StorageDelta d; 61 | d.type(DeltaType::HASH_SET_INSERT); 62 | d.hash() = entry; 63 | return d; 64 | } 65 | 66 | StorageDelta 67 | make_hash_set_increase_limit(uint16_t limit) 68 | { 69 | StorageDelta d; 70 | d.type(DeltaType::HASH_SET_INCREASE_LIMIT); 71 | d.limit_increase() = limit; 72 | return d; 73 | } 74 | 75 | StorageDelta 76 | make_hash_set_clear(uint64_t threshold) 77 | { 78 | StorageDelta d; 79 | d.type(DeltaType::HASH_SET_CLEAR); 80 | d.threshold() = threshold; 81 | return d; 82 | } 83 | 84 | StorageDelta 85 | make_asset_add(int64_t delta) 86 | { 87 | StorageDelta d; 88 | d.type(DeltaType::ASSET_OBJECT_ADD); 89 | d.asset_delta() = delta; 90 | return d; 91 | } 92 | 93 | } // namespace scs 94 | -------------------------------------------------------------------------------- /cpp_contracts/payment_experiment/payment_wasmsig.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "erc20.h" 18 | 19 | #include "sdk/replay_cache.h" 20 | #include "sdk/semaphore.h" 21 | #include "sdk/constexpr.h" 22 | #include "sdk/raw_memory.h" 23 | #include "sdk/invoke.h" 24 | #include "sdk/calldata.h" 25 | #include "sdk/log.h" 26 | #include "sdk/auth_singlekey_wasmed25519.h" 27 | 28 | namespace payment 29 | { 30 | 31 | struct calldata_init 32 | { 33 | sdk::Address token; 34 | sdk::PublicKey pk; 35 | uint16_t size_increase; 36 | }; 37 | 38 | constexpr static sdk::StorageKey token_addr = sdk::make_static_key(0, 2); 39 | 40 | EXPORT("pub00000000") 41 | init() 42 | { 43 | sdk::Semaphore init_semaphore(sdk::make_static_key(1, 2)); 44 | init_semaphore.acquire(); 45 | 46 | auto calldata = sdk::get_calldata(); 47 | if (sdk::get_raw_memory_opt(token_addr)) 48 | { 49 | abort(); 50 | } 51 | 52 | sdk::set_raw_memory(token_addr, calldata.token); 53 | 54 | sdk::wasm_auth_single_pk_register(calldata.pk); 55 | 56 | erc20::Ierc20 token(calldata.token); 57 | 58 | token.allowanceDelta(sdk::get_self(), INT64_MAX); 59 | 60 | sdk::replay_cache_size_increase(calldata.size_increase); 61 | } 62 | 63 | struct calldata_transfer 64 | { 65 | sdk::Address to; 66 | int64_t amount; 67 | uint64_t nonce; 68 | uint64_t expiration_time; 69 | }; 70 | 71 | EXPORT("pub01000000") 72 | transfer() 73 | { 74 | auto calldata = sdk::get_calldata(); 75 | 76 | sdk::record_self_replay(calldata.expiration_time); 77 | 78 | sdk::wasm_auth_single_pk_check_sig(0); 79 | 80 | auto token_key = sdk::get_raw_memory(token_addr); 81 | 82 | erc20::Ierc20 token(token_key); 83 | 84 | token.transferFrom(sdk::get_self(), calldata.to, calldata.amount); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /state_db/state_db_v2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "xdr/storage.h" 20 | #include "xdr/types.h" 21 | 22 | #include "mtt/snapshot_trie/atomic_merkle_trie.h" 23 | #include "mtt/common/utils.h" 24 | 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #include "object/revertable_object.h" 31 | 32 | #include "config/static_constants.h" 33 | 34 | namespace scs { 35 | 36 | class ModifiedKeysList; 37 | 38 | class StateDBv2 39 | { 40 | static std::vector serialize(const RevertableObject& v) 41 | { 42 | auto const& res = v.get_committed_object(); 43 | if (res) { 44 | return xdr::xdr_to_opaque(*res); 45 | } 46 | return {}; 47 | } 48 | 49 | static bool validate_value(const RevertableObject& v) 50 | { 51 | return (bool)v.get_committed_object(); 52 | } 53 | 54 | template 55 | using value_wrapper_t = trie::OptionalValue; 56 | 57 | public: 58 | using prefix_t = trie::ByteArrayPrefix; 59 | 60 | using value_t = trie::SerializeWrapper; 61 | 62 | using metadata_t = trie::SnapshotTrieMetadataBase; 63 | 64 | using trie_t = trie::AtomicMerkleTrie; 65 | 66 | private: 67 | trie_t state_db; 68 | 69 | public: 70 | std::optional get_committed_value( 71 | const AddressAndKey& a) const; 72 | 73 | std::optional try_apply_delta( 74 | const AddressAndKey& a, 75 | const StorageDelta& delta); 76 | 77 | void commit_modifications(const ModifiedKeysList& list); 78 | 79 | void rewind_modifications(const ModifiedKeysList& list); 80 | 81 | Hash hash(); 82 | }; 83 | 84 | } // namespace scs 85 | -------------------------------------------------------------------------------- /storage_proxy/storage_proxy.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "xdr/storage.h" 20 | #include "xdr/types.h" 21 | 22 | #include "storage_proxy/storage_proxy_value.h" 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | namespace scs 29 | { 30 | 31 | class TransactionRewind; 32 | class ModifiedKeysList; 33 | class TypedModificationIndex; 34 | 35 | template 36 | class StorageProxy 37 | { 38 | StateDB_t& state_db; 39 | 40 | using value_t = StorageProxyValue; 41 | 42 | mutable std::map cache; 43 | 44 | value_t& get_local(AddressAndKey const& key) const; 45 | 46 | bool committed_local_values = false; 47 | 48 | void assert_not_committed_local_values() const; 49 | 50 | public: 51 | 52 | StorageProxy(StateDB_t& state_db); 53 | 54 | std::optional 55 | get(AddressAndKey const& key) const; 56 | 57 | void 58 | raw_memory_write(AddressAndKey const& key, xdr::opaque_vec&& bytes); 59 | 60 | void 61 | nonnegative_int64_set_add(AddressAndKey const& key, int64_t set_value, int64_t delta); 62 | 63 | void 64 | nonnegative_int64_add(AddressAndKey const& key, int64_t delta); 65 | 66 | void 67 | delete_object_last(AddressAndKey const& key); 68 | 69 | void 70 | hashset_insert(AddressAndKey const& key, Hash const& h, uint64_t threshold); 71 | 72 | void 73 | hashset_increase_limit(AddressAndKey const& key, uint32_t limit); 74 | 75 | void 76 | hashset_clear(AddressAndKey const& key, uint64_t threshold); 77 | 78 | void 79 | asset_add(AddressAndKey const& key, int64_t d); 80 | 81 | bool 82 | __attribute__((warn_unused_result)) 83 | push_deltas_to_statedb(TransactionRewind& rewind) const; 84 | 85 | void log_modified_keys(ModifiedKeysList& keys, const Hash&); 86 | void log_modified_keys(TypedModificationIndex& keys, const Hash& src_hash); 87 | }; 88 | 89 | } /* scs */ 90 | -------------------------------------------------------------------------------- /state_db/typed_modification_index.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /** 3 | * Copyright 2023 Geoffrey Ramseyer 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "mtt/ephemeral_trie/atomic_ephemeral_trie.h" 19 | 20 | #include 21 | 22 | #include 23 | 24 | #include "xdr/types.h" 25 | #include "xdr/storage_delta.h" 26 | 27 | #include "config/static_constants.h" 28 | 29 | #include "state_db/modification_metadata.h" 30 | 31 | namespace scs 32 | { 33 | 34 | class TypedModificationIndex 35 | { 36 | 37 | static void serialize(std::vector& buf, const StorageDelta& v) 38 | { 39 | xdr::append_xdr_to_opaque(buf, v); 40 | } 41 | 42 | public: 43 | using value_t = trie::BetterSerializeWrapper; 44 | // keys are [addrkey] [modification type] [modification] [txid] 45 | constexpr static size_t modification_key_length = 32 + 8; // len(hash) + len(tag), for hashset entries 46 | 47 | using trie_prefix_t = trie::ByteArrayPrefix; 48 | using map_t = trie::AtomicTrie; 49 | 50 | private: 51 | map_t keys; 52 | using serial_trie_t = trie::AtomicTrieReference; 53 | 54 | using cache_t = utils::ThreadlocalCache; 55 | 56 | cache_t cache; 57 | 58 | public: 59 | 60 | void log_modification(AddressAndKey const& addrkey, StorageDelta const& mod, Hash const& src_tx_hash); 61 | 62 | const map_t& get_keys() const 63 | { 64 | return keys; 65 | } 66 | 67 | size_t size() const { 68 | return keys.size(); 69 | } 70 | 71 | void save_modifications(ModIndexLog& out); 72 | 73 | Hash hash(); 74 | void clear(); 75 | }; 76 | 77 | 78 | // public for testing 79 | TypedModificationIndex::trie_prefix_t 80 | make_index_key(AddressAndKey const& addrkey, StorageDelta const& delta, Hash const& src_tx_hash); 81 | 82 | } -------------------------------------------------------------------------------- /cpp_contracts/erc721.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/types.h" 20 | #include "sdk/invoke.h" 21 | 22 | namespace erc721 23 | { 24 | 25 | struct calldata_approve 26 | { 27 | sdk::Hash nft; 28 | sdk::Address approved; 29 | }; 30 | 31 | struct calldata_approveAll 32 | { 33 | sdk::Address op; 34 | bool auth; 35 | }; 36 | 37 | struct calldata_transferFrom 38 | { 39 | sdk::Address from; 40 | sdk::Address to; 41 | sdk::Hash nft; 42 | }; 43 | 44 | class Ierc721 45 | { 46 | const sdk::Address& addr; 47 | 48 | public: 49 | 50 | constexpr 51 | Ierc721(const sdk::Address& addr) 52 | : addr(addr) 53 | {} 54 | 55 | inline void 56 | approve(sdk::Hash const& nft, sdk::Address const& approved) 57 | { 58 | approve( 59 | calldata_approve { 60 | .nft = nft, 61 | .approved = approved 62 | }); 63 | } 64 | 65 | inline void 66 | approve(calldata_approve const& calldata) 67 | { 68 | sdk::invoke(addr, 0, calldata); 69 | } 70 | 71 | inline void 72 | approveAll(sdk::Address const& op, bool auth) 73 | { 74 | approveAll( 75 | calldata_approveAll { 76 | .op = op, 77 | .auth = auth 78 | }); 79 | } 80 | 81 | inline void 82 | approveAll(calldata_approveAll const& calldata) 83 | { 84 | sdk::invoke(addr, 1, calldata); 85 | } 86 | 87 | inline void 88 | transferFrom(sdk::Address const& from, sdk::Address const& to, sdk::Hash const& nft) 89 | { 90 | transferFrom( 91 | calldata_transferFrom { 92 | .from = from, 93 | .to = to, 94 | .nft = nft 95 | }); 96 | } 97 | 98 | inline void 99 | transferFrom(calldata_transferFrom const& calldata) 100 | { 101 | sdk::invoke(addr, 2, calldata); 102 | } 103 | }; 104 | 105 | 106 | } -------------------------------------------------------------------------------- /vm/vm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "transaction_context/global_context.h" 20 | 21 | #include 22 | #include 23 | 24 | #include "xdr/transaction.h" 25 | #include "xdr/block.h" 26 | 27 | #include 28 | 29 | #include "vm/base_vm.h" 30 | 31 | #include "mempool/mempool.h" 32 | 33 | namespace scs { 34 | 35 | class AssemblyLimits; 36 | 37 | /** 38 | * Block policy: 39 | * Header is 40 | * We reject a block if prev_hash doesn't match our hash, 41 | * but if we execute a block and find no errors 42 | * but find a hash mismatch at the end, 43 | * we say that's ok, and move on (presumably rejecting subsequent 44 | * blocks from that proposer). 45 | * 46 | * Groundhog version, no persistence 47 | */ 48 | 49 | class VirtualMachine : public BaseVirtualMachine 50 | { 51 | 52 | public: 53 | BlockHeader propose_tx_block(AssemblyLimits& limits, uint64_t max_time_ms, uint32_t n_threads, Block& out); 54 | }; 55 | 56 | #if 0 57 | class VirtualMachine : public utils::NonMovableOrCopyable 58 | { 59 | GlobalContext global_context; 60 | std::unique_ptr current_block_context; 61 | Mempool mempool; 62 | 63 | Hash prev_block_hash; 64 | 65 | void assert_initialized() const; 66 | 67 | bool validate_tx_block(Block const& txs); 68 | 69 | void advance_block_number(); 70 | 71 | BlockHeader make_block_header(); 72 | 73 | public: 74 | void init_default_genesis(); 75 | 76 | std::optional 77 | try_exec_tx_block(Block const& txs); 78 | 79 | Mempool& get_mempool() { 80 | return mempool; 81 | } 82 | 83 | BlockHeader propose_tx_block(AssemblyLimits& limits, uint64_t max_time_ms, uint32_t n_threads, Block& out); 84 | 85 | uint64_t get_current_block_number() const; 86 | 87 | ~VirtualMachine(); 88 | }; 89 | #endif 90 | 91 | } // namespace scs 92 | -------------------------------------------------------------------------------- /crypto/hash.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * Copyright 2023 Geoffrey Ramseyer 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "xdr/types.h" 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | 26 | namespace scs { 27 | 28 | template 29 | concept XdrType = requires(const T object) 30 | { 31 | xdr::xdr_to_opaque(object); 32 | }; 33 | 34 | //! Hash an xdr (serializable) type. 35 | //! Must call sodium_init() prior to usage. 36 | template 37 | Hash 38 | hash_xdr(const xdr_type& value) 39 | { 40 | Hash hash_buf; 41 | auto serialized = xdr::xdr_to_opaque(value); 42 | 43 | if (crypto_generichash(hash_buf.data(), 44 | hash_buf.size(), 45 | serialized.data(), 46 | serialized.size(), 47 | NULL, 48 | 0) 49 | != 0) { 50 | throw std::runtime_error("error in crypto_generichash"); 51 | } 52 | return hash_buf; 53 | } 54 | 55 | [[maybe_unused]] 56 | static Hash 57 | hash_vec(std::vector const& bytes) 58 | { 59 | Hash hash_buf; 60 | 61 | if (crypto_generichash(hash_buf.data(), 62 | hash_buf.size(), 63 | bytes.data(), 64 | bytes.size(), 65 | NULL, 66 | 0) 67 | != 0) { 68 | throw std::runtime_error("error in crypto_generichash"); 69 | } 70 | return hash_buf; 71 | } 72 | 73 | [[maybe_unused]] 74 | static void 75 | hash_raw(const uint8_t* data, size_t len, uint8_t* hash_out) 76 | { 77 | if (crypto_generichash(hash_out, 78 | sizeof(Hash), 79 | data, 80 | len, 81 | NULL, 82 | 0) 83 | != 0) { 84 | throw std::runtime_error("error in crypto_generichash"); 85 | } 86 | } 87 | 88 | } // namespace scs 89 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/nonnegative_int64.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/macros.h" 20 | #include "sdk/concepts.h" 21 | #include "sdk/alloc.h" 22 | #include "sdk/types.h" 23 | #include "sdk/concepts.h" 24 | 25 | #include 26 | #include 27 | 28 | namespace sdk 29 | { 30 | 31 | 32 | // creates if doesn't already exist 33 | void 34 | int64_add(StorageKey const& key, int64_t delta) 35 | { 36 | detail::builtin_syscall(SYSCALLS::NNINT_ADD, 37 | to_offset(&key), 38 | delta, 39 | 0, 0, 0, 0); 40 | } 41 | 42 | void 43 | int64_set_add(StorageKey const& key, int64_t set_value, int64_t delta) 44 | { 45 | detail::builtin_syscall(SYSCALLS::NNINT_SET_ADD, 46 | to_offset(&key), 47 | set_value, 48 | delta, 49 | 0, 0, 0); 50 | } 51 | 52 | void 53 | int64_set(StorageKey const& key, int64_t set_value) 54 | { 55 | detail::builtin_syscall(SYSCALLS::NNINT_SET_ADD, 56 | to_offset(&key), 57 | set_value, 58 | 0 /* delta */, 59 | 0, 0, 0); 60 | } 61 | 62 | // returns 0 in default case where it does not exist 63 | int64_t 64 | int64_get(StorageKey const& key) 65 | { 66 | return detail::builtin_syscall(SYSCALLS::NNINT_GET, 67 | to_offset(&key), 68 | 0, 0, 0, 0, 0); 69 | } 70 | 71 | class NNInt64 72 | { 73 | StorageKey key; 74 | 75 | public: 76 | 77 | const int64_t set_value; 78 | int64_t delta; 79 | 80 | NNInt64(StorageKey&& key) 81 | : key(key) 82 | , set_value(int64_get(key)) 83 | , delta(0) 84 | {} 85 | 86 | NNInt64(StorageKey&& key, int64_t set) 87 | : key(key) 88 | , set_value(set) 89 | , delta(0) 90 | {} 91 | 92 | int64_t safe_get_value() const 93 | { 94 | int64_t out; 95 | if (__builtin_add_overflow(set_value, delta, &out)) 96 | { 97 | abort(); 98 | } 99 | return out; 100 | } 101 | 102 | ~NNInt64() 103 | { 104 | int64_set_add(key, set_value, delta); 105 | } 106 | 107 | }; 108 | 109 | } /* sdk */ 110 | -------------------------------------------------------------------------------- /mempool/mempool.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "mempool/mempool.h" 18 | 19 | namespace scs { 20 | 21 | std::optional 22 | Mempool::get_new_tx() 23 | { 24 | uint64_t i = indices.fetch_add(1, std::memory_order_acquire); 25 | 26 | uint32_t consumed_idx = i & 0xFFFF'FFFF; 27 | uint32_t filled_idx = i >> 32; 28 | 29 | if (consumed_idx >= filled_idx) { 30 | return std::nullopt; 31 | } 32 | std::optional out 33 | = std::move(ringbuffer[consumed_idx % MAX_MEMPOOL_SIZE]); 34 | 35 | return out; 36 | } 37 | 38 | uint32_t 39 | Mempool::available_size() 40 | { 41 | uint64_t i = indices.load(std::memory_order_relaxed); 42 | 43 | uint32_t consumed_idx = i & 0xFFFF'FFFF; 44 | uint32_t filled_idx = i >> 32; 45 | 46 | if (consumed_idx > filled_idx) 47 | { 48 | return 0; 49 | } 50 | return (filled_idx - consumed_idx); 51 | } 52 | 53 | uint32_t 54 | Mempool::add_txs(std::vector&& txs) 55 | { 56 | std::lock_guard lock(mtx); 57 | 58 | uint64_t i = indices.load(std::memory_order_acquire); 59 | 60 | uint32_t consumed_idx = i & 0xFFFF'FFFF; 61 | uint32_t filled_idx = i >> 32; 62 | 63 | if (consumed_idx > filled_idx) 64 | { 65 | consumed_idx = filled_idx; 66 | } 67 | 68 | // consumed_idx only increases, so this only overestimates space 69 | uint32_t used_space = filled_idx - consumed_idx; 70 | 71 | // underestimate 72 | uint32_t write_now 73 | = std::min(MAX_MEMPOOL_SIZE - used_space, txs.size()); 74 | 75 | for (size_t cpy = 0; cpy < write_now; cpy++) { 76 | ringbuffer[(filled_idx + cpy) % MAX_MEMPOOL_SIZE] = std::move(txs[cpy]); 77 | } 78 | 79 | filled_idx = (filled_idx + write_now) % MAX_MEMPOOL_SIZE; 80 | consumed_idx = consumed_idx % MAX_MEMPOOL_SIZE; 81 | 82 | indices.store((static_cast(filled_idx) << 32) + consumed_idx, 83 | std::memory_order_release); 84 | 85 | return write_now; 86 | } 87 | 88 | } // namespace scs 89 | -------------------------------------------------------------------------------- /notes/replay-mechanisms.txt: -------------------------------------------------------------------------------- 1 | 2 | Tx format: 3 | - replay-info(*) ] 4 | - metadata (gas limit, fee) ] 5 | - exec-script ] covered by TxID 6 | - method ] 7 | - call-data ] 8 | - witness-data 9 | 10 | 11 | (*) What is replay-info? possibilities below: 12 | 13 | # Design 1 14 | 15 | replay info is list of: 16 | 17 | Replay cache (first-class ledger entry): 18 | - seqNum 19 | - key-(seqNum,value) map 20 | - validation script: (tx, replay-cache) -> ⊥ | replay-cache-entries 21 | 22 | Tx invalid if seqNum in replay-info is less than in replay cache 23 | 24 | Bumping seqNum (in exec-script) deletes all entries in the map with 25 | lower seqNum values 26 | 27 | Replay prevention: 28 | seqNum is timestamp (minute granularity epoch #) 29 | script refuses if timestamp < seqNum 30 | script requires witness-data to include appropriate signature 31 | script updates seqNum to timestamp (flushing timestamp-1 and earlier) 32 | No coordination needed between machines issuing payments at bank 33 | 34 | Ratchet: bump sequence number to invalidate old signed transaction 35 | 36 | 37 | In a payment channel/relative timelock/declare-then-close paradigm: 38 | 39 | Declare transaction require a shared lock 40 | Delta is max(prev-version, new-version) 41 | Note: technically don't even need the shared lock 42 | Close transactions require an exclusive lock 43 | Enforce relative timelock in the contrack 44 | 45 | Q: How to prevent spam on locks 46 | Lock has script to validate transaction 47 | Q: Should we pre-specify all locks 48 | Problem: what if you want to auction a lock 49 | or otherwise dynamically chose who should get it 50 | 51 | Proposal: lock validation script outputs 0 for rejected 52 | otherwise, outputs a score. Highest (score, tx-hash) wins? 53 | 54 | Note: we aren't too worried about rogue nodes proposing illegal blocks 55 | that take time to validate, since there shouldn't be anonymous miners 56 | participating in a wholesale CBDC. 57 | 58 | Declare transaction must write current time for relative timelock. So 59 | is that a dynamic delta? Or is current time/ledger number just one of 60 | a small number of things that should be encodable in deltas, as well 61 | as immediate values. 62 | 63 | What about oracle feed? That won't depend on on-chain state. 64 | 65 | # Design 2 66 | 67 | Replay prevention is a mechanism for preventing replays across blocks, needs storage of data 68 | for a potentially long period of time (bounded). 69 | Semaphores only apply to one block. Any longer-running semaphore-like objects can be built on-chain, in the exec script. 70 | 71 | Have a simple reader-writer (shared/exclusive) lock. 72 | 73 | -------------------------------------------------------------------------------- /cpp_contracts/sdk/hashset.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2023 Geoffrey Ramseyer 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include "sdk/macros.h" 20 | #include "sdk/concepts.h" 21 | #include "sdk/alloc.h" 22 | #include "sdk/types.h" 23 | #include "sdk/concepts.h" 24 | 25 | #include "sdk/syscall.h" 26 | 27 | #include 28 | #include 29 | 30 | namespace sdk 31 | { 32 | 33 | void hashset_insert( 34 | StorageKey const& key, 35 | Hash const& hash, 36 | uint64_t threshold) 37 | { 38 | detail::builtin_syscall(SYSCALLS::HS_INSERT, 39 | to_offset(&key), 40 | to_offset(&hash), 41 | threshold, 0, 0, 0); 42 | } 43 | 44 | void 45 | hashset_increase_limit( 46 | StorageKey const& key, 47 | uint16_t limit_increase) 48 | { 49 | detail::builtin_syscall(SYSCALLS::HS_INC_LIMIT, 50 | to_offset(&key), 51 | limit_increase, 52 | 0, 0, 0, 0); 53 | } 54 | 55 | void 56 | hashset_clear( 57 | StorageKey const& key, 58 | uint64_t threshold) 59 | { 60 | detail::builtin_syscall(SYSCALLS::HS_CLEAR, 61 | to_offset(&key), 62 | threshold, 0, 0, 0, 0); 63 | } 64 | 65 | uint32_t 66 | hashset_get_size( 67 | StorageKey const& key) 68 | { 69 | return detail::builtin_syscall(SYSCALLS::HS_GET_SIZE, 70 | to_offset(&key), 71 | 0, 0, 0, 0, 0); 72 | } 73 | 74 | uint32_t 75 | hashset_get_max_size( 76 | StorageKey const& key) 77 | { 78 | return detail::builtin_syscall(SYSCALLS::HS_GET_MAX_SIZE, 79 | to_offset(&key), 80 | 0, 0, 0, 0, 0); 81 | } 82 | 83 | /** 84 | * if two things with same threshold, 85 | * returns lowest index. 86 | * If none, returns UINT32_MAX 87 | **/ 88 | uint32_t 89 | hashset_get_index_of( 90 | StorageKey const& key, 91 | uint64_t threshold) 92 | { 93 | return detail::builtin_syscall(SYSCALLS::HS_GET_INDEX_OF, 94 | to_offset(&key), 95 | threshold, 96 | 0, 0, 0, 0); 97 | } 98 | 99 | std::pair 100 | hashset_get_index( 101 | StorageKey const& key, 102 | uint32_t index) 103 | { 104 | Hash out; 105 | uint64_t threshold = detail::builtin_syscall(SYSCALLS::HS_GET_INDEX, 106 | to_offset(&key), 107 | index, 108 | to_offset(&out), 109 | 0, 0, 0); 110 | return {threshold, out}; 111 | } 112 | 113 | } /* sdk */ 114 | --------------------------------------------------------------------------------