10 Commits

Author SHA1 Message Date
Luke Parker
f70fee65b8 Add shellcheck to the CI
Updates our scripts to pass. Achieves POSIX compliance for
`increase_default_stack_size.sh` via replacing `hexdump` with `od` and `tr`.
Replaces the non-POSIX `dd status=none` with the POSIX `dd 2> /dev/null`.
2025-12-08 20:04:23 -05:00
Luke Parker
0849d60f28 Run Bitcoin, Monero nodes on Alpine
While prior this didn't work well, presumably due to stack size limitations,
a shell script is included to raise the default stack size limit. This should
be tried again.
2025-12-08 02:30:34 -05:00
Luke Parker
3a792f9ce5 Update documentation on the serai-runtime build.rs 2025-12-08 02:22:29 -05:00
Luke Parker
50959fa0e3 Update the polkadot-sdk used
Removes `parity-wasm` as a dependency, closing
https://github.com/serai-dex/issues/227 and tidying our `deny.toml`.

This removes the `import-memory` flag from the linker as part of
`parity-wasm`'s usage was to map imports into exports
(5a1128b94b/substrate/client/executor/common/src/runtime_blob/runtime_blob.rs (L91-L142)).
2025-12-08 02:22:25 -05:00
Luke Parker
2fb90ebe55 Extend crates we patch to be empty from the Ethereum ecosystem
`ruint` pulls in many versions of many crates. This has it pull in less.
2025-12-06 08:27:34 -05:00
Luke Parker
b24adcbd14 Add panic-on-poison to no-std std_shims::sync::Mutex
We already had this behavior on `std`. It was omitted when no-`std` due to
deferring to `spin::Mutex`, which does not track poisoning at all. This
increases the parity of the two.

Part of https://github.com/serai-dex/serai/issues/698.
2025-12-06 08:06:38 -05:00
Luke Parker
b791256648 Remove substrate-wasm-builder
By defining our own build script, we gain complete clarity and control over how
the WASM is built. This also removes the need to patch the upstream due to it
allowing pollution of the environment variables from the host.

Notable appreciation is given to
https://github.com/rust-lang/rust/issues/145491 for identifying an issue
encountered here, with the associated PR clarifying the necessary flags for the
linker to fix this.
2025-12-04 23:23:38 -05:00
Luke Parker
36ac9c56a4 Remove workaround for lack of musl-dev now that musl-dev is provided in Rust Alpine images
Additionally, optimizes the build process a bit via leaving only the runtime
(and `busybox`) in the final image, and additionally building the runtime
without `std` (as we solely need the WASM blob from this process).
2025-12-04 11:58:38 -05:00
Luke Parker
57bf4984f8 panic = "abort"
`panic = "unwind"` was originally a requirement of Substrate, notably due to
its [native runtime](https://github.com/paritytech/substrate/issues/10874).
This does not mean all of Serai should use this setting however.

As the native runtime has been removed, we do no longer need this for the
Substrate node. With a review of our derivative, a panic guard is only used
when fetching the version from the runtime, causing an error on boot if a
panic occurs. Accordingly, we shouldn't have a need for `panic = "unwind"`
within the node, and the runtime itself should be fine.

The rest of Serai's services already registered bespoke hooks to ensure any
panic caused the process to exit. Those are left as-is, even though they're
now unnecessary.
2025-12-04 11:58:38 -05:00
Luke Parker
87750407de cargo-deny 0.18.8, remove bip39 git dependency
The former is necessary due to `cargo-deny` misinterpreting select licenses.
The latter is finally possible with the recent 2.2.1 release 🎉
2025-12-04 11:58:28 -05:00
46 changed files with 975 additions and 649 deletions

View File

@@ -52,7 +52,7 @@ runs:
- name: Install solc
shell: bash
run: |
cargo +1.91.1 install svm-rs --version =0.5.21
cargo +1.91.1 install svm-rs --version =0.5.22
svm install 0.8.29
svm use 0.8.29

View File

@@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # 6.0.0
- name: Install cargo deny
run: cargo +1.91.1 install cargo-deny --version =0.18.7
run: cargo +1.91.1 install cargo-deny --version =0.18.8
- name: Run cargo deny
run: cargo deny -L error --all-features check --hide-inclusion-graph

View File

@@ -46,7 +46,7 @@ jobs:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # 6.0.0
- name: Install cargo deny
run: cargo +1.91.1 install cargo-deny --version =0.18.7
run: cargo +1.91.1 install cargo-deny --version =0.18.8
- name: Run cargo deny
run: cargo deny -L error --all-features check --hide-inclusion-graph
@@ -201,3 +201,14 @@ jobs:
cp processor/ethereum/erc20/contracts/IERC20.sol processor/ethereum/router/contracts/
cd processor/ethereum/router/contracts
slither Router.sol
shellcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # 6.0.0
- name: shellcheck
run: |
sudo apt install shellcheck
find . -iname "*.sh" | while read -r script; do
shellcheck --enable=all --shell=sh --severity=info $script
done

459
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -116,6 +116,19 @@ members = [
"tests/reproducible-runtime",
]
[profile.dev]
panic = "abort"
overflow-checks = true
[profile.release]
panic = "abort"
overflow-checks = true
# These do not respect the `panic` configuration value, so we don't provide them
[profile.test]
# panic = "abort" # https://github.com/rust-lang/issues/67650
overflow-checks = true
[profile.bench]
overflow-checks = true
[profile.dev.package]
# Always compile Monero (and a variety of dependencies) with optimizations due
# to the extensive operations required for Bulletproofs
@@ -165,17 +178,17 @@ revm-precompile = { opt-level = 3 }
revm-primitives = { opt-level = 3 }
revm-state = { opt-level = 3 }
[profile.release]
panic = "unwind"
overflow-checks = true
[patch.crates-io]
# Point to empty crates for crates unused within in our tree
alloy-eip2124 = { path = "patches/ethereum/alloy-eip2124" }
ark-ff-3 = { package = "ark-ff", path = "patches/ethereum/ark-ff-0.3" }
ark-ff-4 = { package = "ark-ff", path = "patches/ethereum/ark-ff-0.4" }
c-kzg = { path = "patches/ethereum/c-kzg" }
secp256k1-30 = { package = "secp256k1", path = "patches/ethereum/secp256k1-30" }
fastrlp-3 = { package = "fastrlp", path = "patches/ethereum/fastrlp-0.3" }
fastrlp-4 = { package = "fastrlp", path = "patches/ethereum/fastrlp-0.4" }
primitive-types-12 = { package = "primitive-types", path = "patches/ethereum/primitive-types-0.12" }
rlp = { path = "patches/ethereum/rlp" }
secp256k1-30 = { package = "secp256k1", path = "patches/ethereum/secp256k1-0.30" }
# Dependencies from monero-oxide which originate from within our own tree, potentially shimmed to account for deviations since publishing
std-shims = { path = "patches/std-shims" }

View File

@@ -6,12 +6,63 @@ pub use std::sync::{Arc, Weak};
mod mutex_shim {
#[cfg(not(feature = "std"))]
pub use spin::{Mutex, MutexGuard};
mod spin_mutex {
use core::ops::{Deref, DerefMut};
// We wrap this in an `Option` so we can consider `None` as poisoned
pub(super) struct Mutex<T>(spin::Mutex<Option<T>>);
/// An acquired view of a `Mutex`.
pub struct MutexGuard<'mutex, T> {
mutex: spin::MutexGuard<'mutex, Option<T>>,
// This is `Some` for the lifetime of this guard, and is only represented as an `Option` due
// to needing to move it on `Drop` (which solely gives us a mutable reference to `self`)
value: Option<T>,
}
impl<T> Mutex<T> {
pub(super) const fn new(value: T) -> Self {
Self(spin::Mutex::new(Some(value)))
}
pub(super) fn lock(&self) -> MutexGuard<'_, T> {
let mut mutex = self.0.lock();
// Take from the `Mutex` so future acquisitions will see `None` unless this is restored
let value = mutex.take();
// Check the prior acquisition did in fact restore the value
if value.is_none() {
panic!("locking a `spin::Mutex` held by a thread which panicked");
}
MutexGuard { mutex, value }
}
}
impl<T> Deref for MutexGuard<'_, T> {
type Target = T;
fn deref(&self) -> &T {
self.value.as_ref().expect("no value yet checked upon lock acquisition")
}
}
impl<T> DerefMut for MutexGuard<'_, T> {
fn deref_mut(&mut self) -> &mut T {
self.value.as_mut().expect("no value yet checked upon lock acquisition")
}
}
impl<'mutex, T> Drop for MutexGuard<'mutex, T> {
fn drop(&mut self) {
// Restore the value
*self.mutex = self.value.take();
}
}
}
#[cfg(not(feature = "std"))]
pub use spin_mutex::*;
#[cfg(feature = "std")]
pub use std::sync::{Mutex, MutexGuard};
/// A shimmed `Mutex` with an API mutual to `spin` and `std`.
#[derive(Default, Debug)]
pub struct ShimMutex<T>(Mutex<T>);
impl<T> ShimMutex<T> {
/// Construct a new `Mutex`.
@@ -21,8 +72,9 @@ mod mutex_shim {
/// Acquire a lock on the contents of the `Mutex`.
///
/// On no-`std` environments, this may spin until the lock is acquired. On `std` environments,
/// this may panic if the `Mutex` was poisoned.
/// This will panic if the `Mutex` was poisoned.
///
/// On no-`std` environments, the implementation presumably defers to that of a spin lock.
pub fn lock(&self) -> MutexGuard<'_, T> {
#[cfg(feature = "std")]
let res = self.0.lock().unwrap();

View File

@@ -7,8 +7,7 @@ db-urls = ["https://github.com/rustsec/advisory-db"]
yanked = "deny"
ignore = [
"RUSTSEC-2022-0061", # https://github.com/serai-dex/serai/227
"RUSTSEC-2024-0370", # proc-macro-error is unmaintained
"RUSTSEC-2024-0370", # `proc-macro-error` is unmaintained, in-tree due to Substrate/`litep2p`
"RUSTSEC-2024-0436", # paste is unmaintained
]
@@ -79,7 +78,6 @@ exceptions = [
{ allow = ["AGPL-3.0-only"], name = "serai-coordinator-libp2p-p2p" },
{ allow = ["AGPL-3.0-only"], name = "serai-coordinator" },
{ allow = ["AGPL-3.0-only"], name = "pallet-session" },
{ allow = ["AGPL-3.0-only"], name = "substrate-median" },
{ allow = ["AGPL-3.0-only"], name = "serai-core-pallet" },
@@ -152,6 +150,5 @@ allow-git = [
"https://github.com/rust-lang-nursery/lazy-static.rs",
"https://github.com/kayabaNerve/elliptic-curves",
"https://github.com/monero-oxide/monero-oxide",
"https://github.com/rust-bitcoin/rust-bip39",
"https://github.com/serai-dex/patch-polkadot-sdk",
]

View File

@@ -1,9 +1,10 @@
#!/bin/sh
set -e
RPC_USER="${RPC_USER:=serai}"
RPC_PASS="${RPC_PASS:=seraidex}"
bitcoind -regtest --port=8333 \
-rpcuser=$RPC_USER -rpcpassword=$RPC_PASS \
-rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" \
-rpcbind=0.0.0.0 -rpcallowip=0.0.0.0/0 -rpcport=8332 \
$@
"$@"

View File

@@ -1,3 +1,4 @@
#!/bin/sh
set -e
~/.foundry/bin/anvil --host 0.0.0.0 --no-cors --no-mining --slots-in-an-epoch 32 --silent

View File

@@ -1,4 +1,5 @@
#!/bin/sh
set -e
monero-wallet-rpc \
--allow-mismatched-daemon-version \

View File

@@ -1,4 +1,5 @@
#!/bin/sh
set -e
RPC_USER="${RPC_USER:=serai}"
RPC_PASS="${RPC_PASS:=seraidex}"
@@ -7,5 +8,5 @@ RPC_PASS="${RPC_PASS:=seraidex}"
monerod --non-interactive --regtest --offline --fixed-difficulty=1 \
--no-zmq --rpc-bind-ip=0.0.0.0 --rpc-bind-port=18081 --confirm-external-bind \
--rpc-access-control-origins "*" --disable-rpc-ban \
--rpc-login=$RPC_USER:$RPC_PASS --log-level 2 \
$@
--rpc-login="$RPC_USER":"$RPC_PASS" --log-level 2 \
"$@"

View File

@@ -1,3 +1,5 @@
#!/bin/sh
set -e
serai-node --unsafe-rpc-external --rpc-cors all --chain local --$SERAI_NAME
${SERAI_NAME:?} # Ensure this is present in the environment
serai-node --unsafe-rpc-external --rpc-cors all --chain local --"$SERAI_NAME"

View File

@@ -0,0 +1,176 @@
#!/bin/sh
# Raises `PT_GNU_STACK`'s memory to be at least 8 MB.
#
# This causes `musl` to use a 8 MB default for new threads, resolving the primary
# compatibility issue faced when executing a program on a `musl` system.
#
# See https://wiki.musl-libc.org/functional-differences-from-glibc.html#Thread-stack-size
# for reference. This differs that instead of setting at time of link, it
# patches the binary as an already-linked ELF executable.
set -e
ELF="$1"
if [ ! -f "$ELF" ]; then
echo "\`increase_default_stack_size.sh\` [ELF binary]"
echo ""
echo "Sets the \`PT_GNU_STACK\` program header to its existing value or 8 MB,"
echo "whichever is greater."
exit 1
fi
hex() {
od -tx1 -v -A none | tr -d "[:space:]"
}
read_bytes() {
dd bs=1 skip="$1" count="$2" if="$ELF" 2> /dev/null | hex
}
write_bytes() {
POS=$1
BYTES=$2
while [ ! "$BYTES" = "" ]; do
NEXT=$(printf "%s" "$BYTES" | head -c2)
# Advance to the third byte, as in, after the first two bytes
BYTES=$(printf "%s" "$BYTES" | tail -c+3)
# shellcheck disable=SC2059
printf "\x$NEXT" | dd conv=notrunc bs=1 seek="$POS" of="$ELF" 2> /dev/null
POS=$((POS + 1))
done
}
# Magic
MAGIC=$(read_bytes 0 4)
EXPECTED_MAGIC=$(printf "\x7ELF" | hex)
if [ ! "$MAGIC" = "$EXPECTED_MAGIC" ]; then
echo "Not ELF"
exit 2
fi
# 1 if 32-bit, 2 if 64-bit
BITS=$(read_bytes 4 1)
case $BITS in
"01") BITS=32;;
"02") BITS=64;;
*)
echo "Not 32- or 64- bit"
exit 3
;;
esac
# For `value_per_bits a b`, `a` if 32-bit and `b` if 64-bit
value_per_bits() {
RESULT=$(($1))
if [ $BITS = 64 ]; then
RESULT=$(($2))
fi
printf "%s" "$RESULT"
}
# Read an integer by its offset, differing depending on if 32- or 64-bit
read_integer_by_offset() {
OFFSET=$(value_per_bits "$1" "$2")
BYTES=$(read_bytes "$OFFSET" "$3")
BYTES=$(swap_native_endian "$BYTES")
printf "%i" $(( 0x$BYTES ))
}
# 1 if little-endian, 2 if big-endian
LITTLE_ENDIAN=$(read_bytes 5 1)
case $LITTLE_ENDIAN in
"01") LITTLE_ENDIAN=1;;
"02") LITTLE_ENDIAN=0;;
*)
echo "Not little- or big- endian"
exit 4
;;
esac
# While this script is written in big-endian, we need to work with the file in
# its declared endian. This function swaps from big to native, or vice versa,
# as necessary.
swap_native_endian() {
BYTES="$1"
if [ "$BYTES" = "" ]; then
read -r BYTES
fi
if [ "$LITTLE_ENDIAN" -eq 0 ]; then
printf "%s" "$BYTES"
return
fi
while [ ! "$BYTES" = "" ]; do
printf "%s" "$BYTES" | tail -c2
BYTES=$(printf "%s" "$BYTES" | head -c-2)
done
}
ELF_VERSION=$(read_bytes 6 1)
if [ ! "$ELF_VERSION" = "01" ]; then
echo "Unknown ELF Version ($ELF_VERSION)"
exit 5
fi
ELF_VERSION_2=$(read_bytes $((0x14)) 4)
if [ ! "$ELF_VERSION_2" = "$(swap_native_endian 00000001)" ]; then
echo "Unknown secondary ELF Version ($ELF_VERSION_2)"
exit 6
fi
# Find where the program headers are
PROGRAM_HEADERS_OFFSET=$(read_integer_by_offset 0x1c 0x20 "$(value_per_bits 4 8)")
PROGRAM_HEADER_SIZE=$(value_per_bits 0x20 0x38)
DECLARED_PROGRAM_HEADER_SIZE=$(read_integer_by_offset 0x2a 0x36 2)
if [ ! "$PROGRAM_HEADER_SIZE" -eq "$DECLARED_PROGRAM_HEADER_SIZE" ]; then
echo "Unexpected size of a program header ($DECLARED_PROGRAM_HEADER_SIZE)"
exit 7
fi
program_header_start() {
printf "%i" $((PROGRAM_HEADERS_OFFSET + ($1 * PROGRAM_HEADER_SIZE)))
}
read_program_header() {
START=$(program_header_start "$1")
read_bytes "$START" "$PROGRAM_HEADER_SIZE"
}
# Iterate over each program header
PROGRAM_HEADERS=$(read_integer_by_offset 0x2c 0x38 2)
NEXT_PROGRAM_HEADER=$(( PROGRAM_HEADERS - 1 ))
FOUND=0
while [ "$NEXT_PROGRAM_HEADER" -ne -1 ]; do
THIS_PROGRAM_HEADER=$NEXT_PROGRAM_HEADER
NEXT_PROGRAM_HEADER=$(( NEXT_PROGRAM_HEADER - 1 ))
PROGRAM_HEADER=$(read_program_header "$THIS_PROGRAM_HEADER")
HEADER_TYPE=$(printf "%s" "$PROGRAM_HEADER" | head -c8)
HEADER_TYPE=$(swap_native_endian "$HEADER_TYPE")
# `PT_GNU_STACK`
# https://github.com/torvalds/linux/blob/c2f2b01b74be8b40a2173372bcd770723f87e7b2/include/uapi/linux/elf.h#L41
if [ ! "$HEADER_TYPE" = "6474e551" ]; then
continue
fi
FOUND=1
MEMSZ_OFFSET=$(( $(program_header_start "$THIS_PROGRAM_HEADER") + $(value_per_bits 0x14 0x28) ))
MEMSZ_LEN=$(value_per_bits 4 8)
# `MEMSZ_OFFSET MEMSZ_OFFSET` as we've already derived it depending on the amount of bits
MEMSZ=$(read_integer_by_offset "$MEMSZ_OFFSET" "$MEMSZ_OFFSET" "$MEMSZ_LEN")
DESIRED_STACK_SIZE=$((8 * 1024 * 1024))
# Only run if the inherent value is _smaller_
if [ "$MEMSZ" -lt "$DESIRED_STACK_SIZE" ]; then
# `2 *`, as this is its length in hexadecimal
HEX_MEMSZ=$(printf %."$((2 * MEMSZ_LEN))"x "$DESIRED_STACK_SIZE")
HEX_MEMSZ=$(swap_native_endian "$HEX_MEMSZ")
write_bytes "$MEMSZ_OFFSET" "$HEX_MEMSZ"
fi
done
if [ "$FOUND" -eq 0 ]; then
echo "\`PT_GNU_STACK\` program header not found"
exit 8
fi
echo "All instances of \`PT_GNU_STACK\` patched to be at least 8 MB"
exit 0

View File

@@ -1,28 +1,8 @@
#check=skip=FromPlatformFlagConstDisallowed
# We want to explicitly set the platform to ensure a constant host environment
# rust:1.91.1-alpine as of November 11th, 2025 (GMT)
FROM --platform=linux/amd64 rust@sha256:700c0959b23445f69c82676b72caa97ca4359decd075dca55b13339df27dc4d3
# In order to compile the runtime, including the `proc-macro`s and build scripts, we need the
# required development libraries. These are traditionally provided by `musl-dev` which is not
# inherently included with this image (https://github.com/rust-lang/docker-rust/issues/68). While we
# could install it here, we'd be unable to pin the installed package by its hash as desired.
#
# Rust does have self-contained libraries, intended to be used when the desired development files
# are not otherwise available. These can be enabled with `link-self-contained=yes`. Unfortunately,
# this doesn't work here (https://github.com/rust-lang/rust/issues/149371).
#
# While we can't set `link-self-contained=yes`, we can install Rust's self-contained libraries onto
# our system so they're generally available.
RUN echo '#!/bin/sh' > libs.sh
RUN echo 'set -e' >> libs.sh
RUN echo 'SYSROOT=$(rustc --print sysroot)' >> libs.sh
RUN echo 'LIBS=$SYSROOT/lib/rustlib/x86_64-unknown-linux-musl/lib/self-contained' >> libs.sh
RUN echo 'ln -s $LIBS/Scrt1.o $LIBS/crti.o $LIBS/crtn.o /usr/lib' >> libs.sh
# We also need `libc.so` which is already present on the system, just not under that name
RUN echo 'ln -s /lib/libc.musl-x86_64.so.1 /usr/lib/libc.so' >> libs.sh
RUN /bin/sh ./libs.sh
# rust:1.91.1-alpine as of December 4th, 2025 (GMT)
FROM --platform=linux/amd64 rust@sha256:84f263251b0ada72c1913d82a824d47be15a607f3faf015d8bdae48db544cdf2 AS builder
# Add the WASM toolchain
RUN rustup target add wasm32v1-none
@@ -47,11 +27,16 @@ ADD AGPL-3.0 /serai
WORKDIR /serai
# Build the runtime
RUN cargo build --release -p serai-runtime
# Copy the artifact
RUN cp /serai/target/release/wbuild/serai-runtime/serai_runtime.wasm /serai/serai.wasm
# Clean up the build directory
RUN cargo clean
RUN cargo build --release -p serai-runtime --no-default-features
# Copy the runtime to the provided volume
CMD ["cp", "/serai/serai.wasm", "/volume/serai.wasm"]
# Copy the artifact to its own image which solely exists to further export it
FROM scratch
# Copy `busybox`, including the necessary shared libraries, from the builder for a functioning `cp`
COPY --from=builder /lib/ld-musl-x86_64.so.1 /lib/libc.musl-x86_64.so.1 /lib/
COPY --from=builder /bin/busybox /bin/
ENV LD_LIBRARY_PATH=/lib/
ENV PATH=/bin
# Copy the artifact itself
COPY --from=builder /serai/target/release/serai_runtime.wasm /serai.wasm
# By default, copy the artifact to `/volume`, presumably a provided volume
CMD ["busybox", "cp", "/serai.wasm", "/volume/serai.wasm"]

View File

@@ -29,7 +29,7 @@ RUN tar xzvf bitcoin-${BITCOIN_VERSION}-$(uname -m)-linux-gnu.tar.gz
RUN mv bitcoin-${BITCOIN_VERSION}/bin/bitcoind .
"#;
let setup = mimalloc(Os::Debian) + DOWNLOAD_BITCOIN;
let setup = mimalloc(Os::Alpine) + DOWNLOAD_BITCOIN;
let run_bitcoin = format!(
r#"
@@ -43,7 +43,7 @@ CMD ["/run.sh"]
network.label()
);
let run = os(Os::Debian, "", "bitcoin") + &run_bitcoin;
let run = os(Os::Alpine, "", "bitcoin") + &run_bitcoin;
let res = setup + &run;
let mut bitcoin_path = orchestration_path.to_path_buf();

View File

@@ -21,7 +21,7 @@ fn monero_internal(
};
#[rustfmt::skip]
let download_monero = format!(r#"
let mut download_monero = format!(r#"
FROM alpine:latest AS monero
RUN apk --no-cache add wget gnupg
@@ -41,6 +41,16 @@ RUN tar -xvjf monero-linux-{arch}-v{MONERO_VERSION}.tar.bz2 --strip-components=1
network.label(),
);
if os == Os::Alpine {
// Increase the default stack size, as Monero does heavily use its stack
download_monero += &format!(
r#"
ADD orchestration/increase_default_stack_size.sh .
RUN ./increase_default_stack_size.sh {monero_binary}
"#
);
}
let setup = mimalloc(os) + &download_monero;
let run_monero = format!(
@@ -69,13 +79,13 @@ CMD ["/run.sh"]
}
pub fn monero(orchestration_path: &Path, network: Network) {
monero_internal(network, Os::Debian, orchestration_path, "monero", "monerod", "18080 18081")
monero_internal(network, Os::Alpine, orchestration_path, "monero", "monerod", "18080 18081")
}
pub fn monero_wallet_rpc(orchestration_path: &Path) {
monero_internal(
Network::Dev,
Os::Debian,
Os::Alpine,
orchestration_path,
"monero-wallet-rpc",
"monero-wallet-rpc",

View File

@@ -1,9 +1,10 @@
#!/bin/sh
set -e
RPC_USER="${RPC_USER:=serai}"
RPC_PASS="${RPC_PASS:=seraidex}"
bitcoind -testnet -port=8333 \
-rpcuser=$RPC_USER -rpcpassword=$RPC_PASS \
-rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" \
-rpcbind=0.0.0.0 -rpcallowip=0.0.0.0/0 -rpcport=8332 \
--datadir=/volume

View File

@@ -1,3 +1,4 @@
#!/bin/sh
set -e
RUST_LOG=info lighthouse bn --execution-endpoint http://localhost:8551 --execution-jwt /home/ethereum/.jwt

View File

@@ -1,3 +1,4 @@
#!/bin/sh
set -e
exit 1

View File

@@ -1,4 +1,5 @@
#!/bin/sh
set -e
#geth --dev --networkid 5208 \
# --http --http.api "web3,net,eth,miner" \

View File

@@ -1,3 +1,4 @@
#!/bin/sh
set -e
RUST_LOG=info reth node --authrpc.jwtsecret /home/ethereum/.jwt

View File

@@ -1,50 +0,0 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
# This GPG-signed message exists to confirm the SHA256 sums of Monero binaries.
#
# Please verify the signature against the key for binaryFate in the
# source code repository (/utils/gpg_keys).
#
#
## CLI
6122f0bcaca12d5badd92002338847d16032f6d52d86155c203bcb67d4fe1518 monero-android-armv7-v0.18.4.2.tar.bz2
3b248c3201f028205915403b4b2f173df0dd8bf47eeb268fd67a4661251469d3 monero-android-armv8-v0.18.4.2.tar.bz2
b4e2b7de80107a1b4613b878d8e2114244b3fb16397821d69baa72d9b0f8c8d5 monero-freebsd-x64-v0.18.4.2.tar.bz2
ecb2577499a3b0901d731e11d462d3fadcd70095f3ab0def0c27ee64dc56b061 monero-linux-armv7-v0.18.4.2.tar.bz2
a39530054dac348b219f1048a24ca629da26990f72cf9c1f6b6853e3d8c39a79 monero-linux-armv8-v0.18.4.2.tar.bz2
18492ace80bf8ef2f44aa9a99b4f20adf00fd59c675a6a496211a720088d5d1a monero-linux-riscv64-v0.18.4.2.tar.bz2
41d023f2357244ea43ee0a74796f5705ce75ce7373a5865d4959fefa13ecab06 monero-linux-x64-v0.18.4.2.tar.bz2
03e77a4836861a47430664fa703dd149a355b3b214bc400b04ed38eb064a3ef0 monero-linux-x86-v0.18.4.2.tar.bz2
9b98da6911b4769abef229c20e21f29d919b11db156965d6f139d2e1ad6625c2 monero-mac-armv8-v0.18.4.2.tar.bz2
b1b1b580320118d3b6eaa5575fdbd73cf4db90fcc025b7abf875c5e5b4e335c1 monero-mac-x64-v0.18.4.2.tar.bz2
14dd5aa11308f106183dd7834aa200e74ce6f3497103973696b556e893a4fef2 monero-win-x64-v0.18.4.2.zip
934d9dbeb06ff5610d2c96ebe34fa480e74f78eaeb3fa3e47d89b7961c9bc5e0 monero-win-x86-v0.18.4.2.zip
e9ec2062b3547db58f00102e6905621116ab7f56a331e0bc9b9e892607b87d24 monero-source-v0.18.4.2.tar.bz2
#
## GUI
9d6e87add7e3ac006ee34c13c4f629252595395f54421db768f72dc233e94ea8 monero-gui-install-win-x64-v0.18.4.2.exe
e4fcdea3f0ff27c3616a8a75545f42a4e4866ea374fa2eeaa9c87027573358ea monero-gui-linux-x64-v0.18.4.2.tar.bz2
3dfee5c5d8e000c72eb3755bf0eb03ca7c5928b69c3a241e147ad22d144e00a7 monero-gui-mac-armv8-v0.18.4.2.dmg
16abadcbd608d4f7ba20d17a297f2aa2c9066d33f6f22bf3fcdca679ab603990 monero-gui-mac-x64-v0.18.4.2.dmg
4daff8850280173d46464ba9a9de7f712228ad1ef76a1c4954531e4fd2b86d86 monero-gui-win-x64-v0.18.4.2.zip
691085e61ece6c56738431f3cfd395536ca0675214e5991e0dbfab85025e82d7 monero-gui-source-v0.18.4.2.tar.bz2
#
#
# ~binaryFate
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCAAdFiEEgaxZH+nEtlxYBq/D8K9NRioL35IFAmitx+kACgkQ8K9NRioL
35J6cQ/7ByvGstg/a5lIYbB+Lz5bNiPozCILD9/offvC7GgOvna9rkHuofuLS+pX
qhYEMrjFjmp03XMY+i68M83qkBEZ+yU5iNDbwRuHUNMMWaaGlhnhm3nyUVtDpjjr
4xwVsee+dzi0JZhVQG7HJFURiP2Ub5Ua6bSaATDoT/aUYdhmrOnQiH2+VxogiCv3
JStDqXq6LpFjzw7UkAfxxu1PW+AQFNBzi3L0qWfzb5WWL7xuK63wXGmEkYBlvult
qt3LUhDUzMrfZ5GiiOYDEw44Y2atD4ibOYtBnllCX9CKNb0o2KKU6Qkj+CYqqtnE
uGNOt1oT09VPOtE7OUkBLVkALjef7ZXRibE7tN4wSnsrG39DP795/52L6CGJbl4n
UDnHzLCUbuvhnoAu5U+rUP5nUEDYS9ANNyj610ogNCo7YjfzLH641WSQ/UnuXKkA
RmK8xIiKoOnUeOanX99zqeXqV7gQdQMlfwLUr3pQzCI2YjdvxdRoedSEi5nX5KvO
Snf3BcCYMBemGYqVMdo95tc0Gmsw12/O8WwrBbTea+PeAXJuLaBxrLNn+RNZLfF/
UJYq2VcEwxG6vXb3cJ5lDKmRDDRI8Fxu6Amdab+6ponhM8Zy3eAynVIO952pLA7N
dtl72RsimM+sgHXP4ERYL4c6WARSHE5sAiog43dr56l3PPmM8pE=
=SoHG
-----END PGP SIGNATURE-----

View File

@@ -0,0 +1,50 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
# This GPG-signed message exists to confirm the SHA256 sums of Monero binaries.
#
# Please verify the signature against the key for binaryFate in the
# source code repository (/utils/gpg_keys).
#
#
## CLI
7c2ad18ca3a1ad5bc603630ca935a753537a38a803e98d645edd6a3b94a5f036 monero-android-armv7-v0.18.4.4.tar.bz2
eb81b71f029884ab5fec76597be583982c95fd7dc3fc5f5083a422669cee311e monero-android-armv8-v0.18.4.4.tar.bz2
bc539178df23d1ae8b69569d9c328b5438ae585c0aacbebe12d8e7d387a745b0 monero-freebsd-x64-v0.18.4.4.tar.bz2
2040dc22748ef39ed8a755324d2515261b65315c67b91f449fa1617c5978910b monero-linux-armv7-v0.18.4.4.tar.bz2
b9daede195a24bdd05bba68cb5cb21e42c2e18b82d4d134850408078a44231c5 monero-linux-armv8-v0.18.4.4.tar.bz2
c939ea6e8002798f24a56ac03cbfc4ff586f70d7d9c3321b7794b3bcd1fa4c45 monero-linux-riscv64-v0.18.4.4.tar.bz2
7fe45ee9aade429ccdcfcad93b905ba45da5d3b46d2dc8c6d5afc48bd9e7f108 monero-linux-x64-v0.18.4.4.tar.bz2
8c174b756e104534f3d3a69fe68af66d6dc4d66afa97dfe31735f8d069d20570 monero-linux-x86-v0.18.4.4.tar.bz2
645e9bbae0275f555b2d72a9aa30d5f382df787ca9528d531521750ce2da9768 monero-mac-armv8-v0.18.4.4.tar.bz2
af3d98f09da94632db3e2f53c62cc612e70bf94aa5942d2a5200b4393cd9c842 monero-mac-x64-v0.18.4.4.tar.bz2
7eb3b87a105b3711361dd2b3e492ad14219d21ed8fd3dd726573a6cbd96e83a6 monero-win-x64-v0.18.4.4.zip
a148a2bd2b14183fb36e2cf917fce6f33fb687564db2ed53193b8432097ab398 monero-win-x86-v0.18.4.4.zip
84570eee26238d8f686605b5e31d59569488a3406f32e7045852de91f35508a2 monero-source-v0.18.4.4.tar.bz2
#
## GUI
4c81c8e97bd542daa453776d888557db1ceb2a718d43f6135ad68b12c8119948 monero-gui-install-win-x64-v0.18.4.4.exe
e45cb3fa9d972d67628cfed6463fb7604ae1414a11ba449f5e2f901c769ac788 monero-gui-linux-x64-v0.18.4.4.tar.bz2
a6f071719c401df339dba2d43ec6fffe103fda3e1df46f354b2496f34bb61cc4 monero-gui-mac-armv8-v0.18.4.4.dmg
811df70811a25f31289f24ebc0edc8f7648670384698d4c768bac5c2acbf2026 monero-gui-mac-x64-v0.18.4.4.dmg
b96faa56aa77cabed1f31f3fc9496e756a8da8c1124da2b9cb0b3730a8b6fbd9 monero-gui-win-x64-v0.18.4.4.zip
a7f6b91bc9efaa83173a397614626bf7612123e0017a48f66137ac397f7d19f8 monero-gui-source-v0.18.4.4.tar.bz2
#
#
# ~binaryFate
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCAAdFiEEgaxZH+nEtlxYBq/D8K9NRioL35IFAmkbGLgACgkQ8K9NRioL
35LWYRAAnPeUu7TADV9Nly2gBlwu7bMK6l7pcUzs3hHhCMpg/Zb7wF8lx4D/r/hT
3wf3gNVK6tYl5GMPpF7GSKvK35SSzNN+8khRd7vhRByG75LGLnrNlcBsQU2wOzUv
Rmm2R8L8GP0B/+zXO92uJDMZ7Q7x72O+3fVX05217HBwz2kvzE1NpXe+EJPnUukA
Tr5CRnxKhxPbilvIhoEHdwkScMZqHMfsbdrefrB3KpO3xEaUz+gO9wESp7nzr4vp
Du6gJYBPK25Z2heZHCRsGN4WQP4QQv4MC0IFczc9fkVDBjywsJeNRRUbGtxR/BNt
vNJGI/kS+7KV140j6GkqAh/leZcaVJ5LRyCaHAwEQNA2T5okhrM0WZpoOAsZMi5K
bW4lNOXfWSw6/tokEPeuoi49yw0f9z0C8a4VLNOZGWKqmHcsA8WE6oVfmvVk6xWu
BqTU1Z9LJqL17GWRAReSX1ZuNA0Q0Pb/klUwP4X2afJcCVZ2YeBNr4jr21u3dYXY
QiLj0Gv7gg7a/GiMpVglNn5GzCu6mT0D94sbMNK+U5Tbve7aOtijJZ8JR62eO/mR
h+oNEys/xEcP9PQ5p74cNL71hNSfWSOcNi+GLSgXC75vsOGr7i96uaamilsHnsYB
p8PZMHzOf1pi6i/L5oOEuRgaujd9IjyCbxoYh3bbxxjBOhNEMqU=
=CVLA
-----END PGP SIGNATURE-----

View File

@@ -1,4 +1,5 @@
#!/bin/sh
set -e
RPC_USER="${RPC_USER:=serai}"
RPC_PASS="${RPC_PASS:=seraidex}"
@@ -7,5 +8,5 @@ RPC_PASS="${RPC_PASS:=seraidex}"
monerod --non-interactive --stagenet \
--no-zmq --rpc-bind-ip=0.0.0.0 --rpc-bind-port=18081 --confirm-external-bind \
--rpc-access-control-origins "*" --disable-rpc-ban \
--rpc-login=$RPC_USER:$RPC_PASS \
--rpc-login="$RPC_USER":"$RPC_PASS" \
--data-dir=/volume

View File

@@ -1,3 +1,4 @@
#!/bin/sh
set -e
serai-node --base-path /volume --unsafe-rpc-external --rpc-cors all --chain testnet --validator

View File

@@ -0,0 +1,19 @@
[package]
name = "fastrlp"
version = "0.3.99"
description = "Patch to an empty crate"
license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/patches/ethereum/fastrlp-0.3"
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
keywords = []
edition = "2021"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[workspace]
[features]
alloc = []
std = []

View File

@@ -0,0 +1,19 @@
[package]
name = "fastrlp"
version = "0.4.99"
description = "Patch to an empty crate"
license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/patches/ethereum/fastrlp-0.4"
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
keywords = []
edition = "2021"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[workspace]
[features]
alloc = []
std = []

View File

@@ -0,0 +1 @@
const _NEVER_COMPILED: [(); 0 - 1] = [(); 0 - 1];

View File

@@ -0,0 +1,18 @@
[package]
name = "primitive-types"
version = "0.12.99"
description = "Patch to an empty crate"
license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/patches/ethereum/primitive-types"
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
keywords = []
edition = "2021"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[workspace]
[features]
std = []

View File

@@ -0,0 +1 @@
const _NEVER_COMPILED: [(); 0 - 1] = [(); 0 - 1];

View File

@@ -0,0 +1,18 @@
[package]
name = "rlp"
version = "0.5.99"
description = "Patch to an empty crate"
license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/patches/ethereum/rlp"
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
keywords = []
edition = "2021"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[workspace]
[features]
std = []

View File

@@ -0,0 +1 @@
const _NEVER_COMPILED: [(); 0 - 1] = [(); 0 - 1];

View File

@@ -3,7 +3,7 @@ name = "secp256k1"
version = "0.30.99"
description = "Patch to an empty crate"
license = "MIT"
repository = "https://github.com/serai-dex/serai/tree/develop/patches/ethereum/secp256k1-30"
repository = "https://github.com/serai-dex/serai/tree/develop/patches/ethereum/secp256k1-0.30"
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
keywords = []
edition = "2021"

View File

@@ -0,0 +1 @@
const _NEVER_COMPILED: [(); 0 - 1] = [(); 0 - 1];

View File

@@ -15,7 +15,7 @@ rustdoc-args = ["--cfg", "docsrs"]
[workspace]
[dependencies]
bip39 = { git = "https://github.com/rust-bitcoin/rust-bip39", commit = "f735e2559f30049f6738d1bf68c69a0b7bd7b858", default-features = false }
bip39 = { version = "2.2.1", default-features = false }
[features]
default = ["bip39/default"]

View File

@@ -1,3 +1,3 @@
#![cfg_attr(not(feature = "std"), no_std)]
#![no_std]
pub use bip39::*;

View File

@@ -74,7 +74,7 @@ fn wasm_binary(dev: bool) -> Vec<u8> {
}
log::info!("using built-in wasm");
serai_runtime::WASM_BINARY.ok_or("compiled in wasm not available").unwrap().to_vec()
serai_runtime::WASM.to_vec()
}
fn devnet_genesis(validators: &[&'static str], endowed_accounts: Vec<Public>) -> GenesisConfig {

View File

@@ -6,7 +6,7 @@ use sp_timestamp::InherentDataProvider as TimestampInherent;
use sp_consensus_babe::{SlotDuration, inherents::InherentDataProvider as BabeInherent};
use sp_io::SubstrateHostFunctions;
use sc_executor::{sp_wasm_interface::ExtendedHostFunctions, WasmExecutor};
use sc_executor::{sp_wasm_interface::ExtendedHostFunctions, HeapAllocStrategy, WasmExecutor};
use sc_network::{Event, NetworkEventStream, NetworkBackend};
use sc_service::{error::Error as ServiceError, Configuration, TaskManager, TFullClient};
@@ -99,14 +99,13 @@ pub fn new_partial(
})
.transpose()?;
#[allow(deprecated)]
let executor = Executor::new(
config.executor.wasm_method,
config.executor.default_heap_pages,
config.executor.max_runtime_instances,
None,
config.executor.runtime_cache_size,
);
let executor = Executor::builder()
.with_execution_method(config.executor.wasm_method)
.with_onchain_heap_alloc_strategy(HeapAllocStrategy::Dynamic { maximum_pages: None })
.with_offchain_heap_alloc_strategy(HeapAllocStrategy::Dynamic { maximum_pages: None })
.with_max_runtime_instances(config.executor.max_runtime_instances)
.with_runtime_cache_size(config.executor.runtime_cache_size)
.build();
let (client, backend, keystore_container, task_manager) = {
let telemetry = telemetry.as_ref().map(|(_, telemetry)| telemetry.handle());

View File

@@ -17,11 +17,31 @@ ignored = ["scale"]
[lints]
workspace = true
[dependencies]
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
[target.'cfg(not(target_family = "wasm"))'.dependencies]
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"], optional = true }
sp-version = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false, optional = true }
sp-runtime = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false, optional = true }
sp-api = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false, optional = true }
sp-transaction-pool = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false, optional = true }
sp-inherents = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false, optional = true }
sp-block-builder = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false, optional = true }
sp-consensus-babe = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false, optional = true }
sp-consensus-grandpa = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false, optional = true }
sp-authority-discovery = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false, optional = true }
serai-abi = { path = "../abi", default-features = false, features = ["substrate"], optional = true }
[target.'cfg(target_family = "wasm")'.dependencies]
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
borsh = { version = "1", default-features = false }
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false }
sp-version = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false }
sp-runtime = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false }
sp-session = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false }
sp-timestamp = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false }
sp-api = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false }
sp-transaction-pool = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false }
@@ -31,15 +51,6 @@ sp-consensus-babe = { git = "https://github.com/serai-dex/patch-polkadot-sdk", d
sp-consensus-grandpa = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false }
sp-authority-discovery = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false }
serai-abi = { path = "../abi", default-features = false, features = ["substrate"] }
[target.'cfg(target_family = "wasm")'.dependencies]
borsh = { version = "1", default-features = false }
sp-core = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false }
sp-session = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false }
sp-timestamp = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false }
frame-system = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false }
frame-support = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false }
frame-executive = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false }
@@ -49,6 +60,8 @@ pallet-session = { git = "https://github.com/serai-dex/patch-polkadot-sdk", defa
pallet-babe = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false }
pallet-grandpa = { git = "https://github.com/serai-dex/patch-polkadot-sdk", default-features = false }
serai-abi = { path = "../abi", default-features = false, features = ["substrate"] }
serai-core-pallet = { path = "../core", default-features = false }
serai-coins-pallet = { path = "../coins", default-features = false }
serai-validator-sets-pallet = { path = "../validator-sets", default-features = false }
@@ -57,9 +70,6 @@ serai-dex-pallet = { path = "../dex", default-features = false }
serai-genesis-liquidity-pallet = { path = "../genesis-liquidity", default-features = false }
serai-in-instructions-pallet = { path = "../in-instructions", default-features = false }
[build-dependencies]
substrate-wasm-builder = { git = "https://github.com/serai-dex/patch-polkadot-sdk" }
[features]
std = [
"scale/std",
@@ -72,6 +82,7 @@ std = [
"sp-runtime/std",
"sp-api/std",
"sp-transaction-pool/std",
"sp-inherents/std",
"sp-block-builder/std",
"sp-consensus-babe/std",
"sp-consensus-grandpa/std",

View File

@@ -1,4 +1,101 @@
fn main() {
#[cfg(feature = "std")]
substrate_wasm_builder::WasmBuilder::build_using_defaults();
use std::{path::PathBuf, fs, env, process::Command};
// Prevent recursing infinitely
if env::var("TARGET").unwrap() == "wasm32v1-none" {
return;
}
// https://github.com/rust-lang/rust/issues/145491
const ONE_45491: &str = "-C link-arg=--mllvm=-mcpu=mvp,--mllvm=-mattr=+mutable-globals";
const WASM: &str = "-C link-arg=--export-table";
const REQUIRED_BY_SUBSTRATE: &str = "--cfg substrate_runtime";
const SAFETY: &str = "-C overflow-checks=true -C panic=abort";
// `symbol-mangling-version` is defined to provide an explicit, canonical definition of symbols.
// `embed-bitcode=false` is set as the bitcode is unnecessary yet takes notable time to compile.
/*
Rust's LTO requires bitcode, forcing us to defer to the linker's LTO. While this would suggest
we _should_ set `embed-bitcode=true`, Rust's documentation suggests that's likely not desired
and should solely be done when compiling one library with mixed methods of linking. When
compiling and linking just once (as seen here), it's suggested to use the linker's LTO instead.
https://doc.rust-lang.org/1.91.1/rustc/codegen-options/index.html#embed-bitcode
*/
const COMPILATION: &str =
"-C symbol-mangling-version=v0 -C embed-bitcode=false -C linker-plugin-lto=true";
let profile = env::var("PROFILE").unwrap();
let release = profile == "release";
let rustflags = format!("{ONE_45491} {WASM} {REQUIRED_BY_SUBSTRATE} {SAFETY} {COMPILATION}");
let rustflags = if release {
format!("{rustflags} -C codegen-units=1 -C strip=symbols -C debug-assertions=false")
} else {
rustflags
};
let target_dir = PathBuf::from(env::var("OUT_DIR").unwrap()).join("target");
let cargo_command = || {
let cargo = env::var("CARGO").unwrap();
let mut command = Command::new(&cargo);
command
.current_dir(env::var("CARGO_MANIFEST_DIR").unwrap())
.env_clear()
.env("PATH", env::var("PATH").unwrap())
.env("CARGO", cargo)
.env("RUSTC", env::var("RUSTC").unwrap())
.env("RUSTFLAGS", &rustflags)
.env("CARGO_TARGET_DIR", &target_dir);
command
};
let workspace = {
let workspace = cargo_command()
.arg("locate-project")
.arg("--workspace")
.arg("--message-format")
.arg("plain")
.output()
.unwrap();
assert!(workspace.status.success());
let mut workspace = PathBuf::from(String::from_utf8(workspace.stdout).unwrap().trim());
assert_eq!(workspace.file_name().unwrap(), "Cargo.toml");
assert!(workspace.pop());
workspace
};
// Re-run anytime the workspace changes
// TODO: Re-run anytime `Cargo.lock` or specifically the `src` folders change
println!("cargo::rerun-if-changed={}", workspace.display());
let mut command = cargo_command();
command
.arg("rustc")
.arg("--package")
.arg(env::var("CARGO_PKG_NAME").unwrap())
.arg("--target")
.arg("wasm32v1-none")
.arg("--crate-type")
.arg("cdylib")
.arg("--no-default-features");
if release {
command.arg("--release");
}
assert!(command.status().unwrap().success());
// Place the resulting WASM blob into the parent `target` directory
{
let wasm_file = env::var("CARGO_PKG_NAME").unwrap().replace('-', "_") + ".wasm";
let src_file = target_dir.join("wasm32v1-none").join(&profile).join(&wasm_file);
let dst_file = {
// TODO: This sets `dst_dir` to the default target directory, not the actual
let mut dst_dir = workspace.clone();
// e.g. workspace/target/debug
dst_dir.extend(["target", &profile]);
let _ = fs::create_dir_all(&dst_dir);
// e.g. workspace/target/debug/serai_runtime.wasm
dst_dir.join(&wasm_file)
};
fs::copy(&src_file, &dst_file).unwrap();
}
}

View File

@@ -0,0 +1,39 @@
use alloc::vec::Vec;
use serai_abi::{
primitives::{
crypto::{Public, EmbeddedEllipticCurveKeys, SignedEmbeddedEllipticCurveKeys, KeyPair},
network_id::{ExternalNetworkId, NetworkId},
validator_sets::{Session, ExternalValidatorSet, ValidatorSet},
balance::{Amount, Balance},
address::SeraiAddress,
},
Event,
};
/// The genesis configuration for Serai.
#[derive(scale::Encode, scale::Decode)]
pub struct GenesisConfig {
/// The genesis validators for the network.
pub validators: Vec<(Public, Vec<SignedEmbeddedEllipticCurveKeys>)>,
/// The accounts to start with balances, intended solely for testing purposes.
pub coins: Vec<(Public, Balance)>,
}
sp_api::decl_runtime_apis! {
pub trait GenesisApi {
fn build(genesis: GenesisConfig);
}
pub trait SeraiApi {
fn events() -> Vec<Vec<Vec<u8>>>;
fn validators(network: NetworkId) -> Vec<Public>;
fn current_session(network: NetworkId) -> Option<Session>;
fn current_stake(network: NetworkId) -> Option<Amount>;
fn keys(set: ExternalValidatorSet) -> Option<KeyPair>;
fn current_validators(network: NetworkId) -> Option<Vec<SeraiAddress>>;
fn pending_slash_report(network: ExternalNetworkId) -> bool;
fn embedded_elliptic_curve_keys(
validator: SeraiAddress,
network: ExternalNetworkId,
) -> Option<EmbeddedEllipticCurveKeys>;
}
}

View File

@@ -1,222 +1,28 @@
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(any(feature = "std", target_family = "wasm"))]
extern crate alloc;
use alloc::vec::Vec;
use serai_abi::{
primitives::{
crypto::{Public, EmbeddedEllipticCurveKeys, SignedEmbeddedEllipticCurveKeys, KeyPair},
network_id::{ExternalNetworkId, NetworkId},
validator_sets::{Session, ExternalValidatorSet, ValidatorSet},
balance::{Amount, Balance},
address::SeraiAddress,
},
Event,
};
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
#[cfg(any(feature = "std", target_family = "wasm"))]
mod common;
#[cfg(any(feature = "std", target_family = "wasm"))]
pub use common::*;
// If this is WASM, we build the runtime proper
#[cfg(target_family = "wasm")]
mod wasm;
/// The genesis configuration for Serai.
#[derive(scale::Encode, scale::Decode)]
pub struct GenesisConfig {
/// The genesis validators for the network.
pub validators: Vec<(Public, Vec<SignedEmbeddedEllipticCurveKeys>)>,
/// The accounts to start with balances, intended solely for testing purposes.
pub coins: Vec<(Public, Balance)>,
}
// If this is `std`, we solely stub with `impl_runtime_apis` for the `RuntimeApi` the node requires
#[cfg(feature = "std")]
mod std_runtime_api;
#[cfg(feature = "std")]
pub use std_runtime_api::RuntimeApi;
sp_api::decl_runtime_apis! {
pub trait GenesisApi {
fn build(genesis: GenesisConfig);
}
pub trait SeraiApi {
fn events() -> Vec<Vec<Vec<u8>>>;
fn validators(network: NetworkId) -> Vec<Public>;
fn current_session(network: NetworkId) -> Option<Session>;
fn current_stake(network: NetworkId) -> Option<Amount>;
fn keys(set: ExternalValidatorSet) -> Option<KeyPair>;
fn current_validators(network: NetworkId) -> Option<Vec<SeraiAddress>>;
fn pending_slash_report(network: ExternalNetworkId) -> bool;
fn embedded_elliptic_curve_keys(
validator: SeraiAddress,
network: ExternalNetworkId,
) -> Option<EmbeddedEllipticCurveKeys>;
}
}
// We stub `impl_runtime_apis` to generate the `RuntimeApi` object the node needs
#[cfg(not(target_family = "wasm"))]
mod apis {
use alloc::borrow::Cow;
use serai_abi::{SubstrateHeader as Header, SubstrateBlock as Block};
use super::*;
#[sp_version::runtime_version]
pub const VERSION: sp_version::RuntimeVersion = sp_version::RuntimeVersion {
spec_name: Cow::Borrowed("serai"),
impl_name: Cow::Borrowed("core"),
authoring_version: 0,
// Use the highest possible value so the node doesn't attempt to use this in place of the WASM
spec_version: 0xffffffff,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
transaction_version: 0,
system_version: 0,
};
/// A `struct` representing the runtime as necessary to define the available APIs.
pub struct Runtime;
sp_api::impl_runtime_apis! {
impl sp_api::Core<Block> for Runtime {
fn version() -> sp_version::RuntimeVersion {
VERSION
}
fn initialize_block(header: &Header) -> sp_runtime::ExtrinsicInclusionMode {
unimplemented!("runtime is only implemented when WASM")
}
fn execute_block(block: Block) {
unimplemented!("runtime is only implemented when WASM")
}
}
impl sp_block_builder::BlockBuilder<Block> for Runtime {
fn apply_extrinsic(
extrinsic: <Block as sp_runtime::traits::Block>::Extrinsic,
) -> sp_runtime::ApplyExtrinsicResult {
unimplemented!("runtime is only implemented when WASM")
}
fn finalize_block() -> Header {
unimplemented!("runtime is only implemented when WASM")
}
fn inherent_extrinsics(
data: sp_inherents::InherentData,
) -> Vec<<Block as sp_runtime::traits::Block>::Extrinsic> {
unimplemented!("runtime is only implemented when WASM")
}
fn check_inherents(
block: Block,
data: sp_inherents::InherentData,
) -> sp_inherents::CheckInherentsResult {
unimplemented!("runtime is only implemented when WASM")
}
}
impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
fn validate_transaction(
source: sp_runtime::transaction_validity::TransactionSource,
tx: <Block as sp_runtime::traits::Block>::Extrinsic,
block_hash: <Block as sp_runtime::traits::Block>::Hash,
) -> sp_runtime::transaction_validity::TransactionValidity {
unimplemented!("runtime is only implemented when WASM")
}
}
impl sp_consensus_babe::BabeApi<Block> for Runtime {
fn configuration() -> sp_consensus_babe::BabeConfiguration {
unimplemented!("runtime is only implemented when WASM")
}
fn current_epoch_start() -> sp_consensus_babe::Slot {
unimplemented!("runtime is only implemented when WASM")
}
fn current_epoch() -> sp_consensus_babe::Epoch {
unimplemented!("runtime is only implemented when WASM")
}
fn next_epoch() -> sp_consensus_babe::Epoch {
unimplemented!("runtime is only implemented when WASM")
}
fn generate_key_ownership_proof(
_slot: sp_consensus_babe::Slot,
_authority_id: sp_consensus_babe::AuthorityId,
) -> Option<sp_consensus_babe::OpaqueKeyOwnershipProof> {
unimplemented!("runtime is only implemented when WASM")
}
fn submit_report_equivocation_unsigned_extrinsic(
equivocation_proof: sp_consensus_babe::EquivocationProof<Header>,
_: sp_consensus_babe::OpaqueKeyOwnershipProof,
) -> Option<()> {
unimplemented!("runtime is only implemented when WASM")
}
}
impl sp_consensus_grandpa::GrandpaApi<Block> for Runtime {
fn grandpa_authorities() -> sp_consensus_grandpa::AuthorityList {
unimplemented!("runtime is only implemented when WASM")
}
fn current_set_id() -> sp_consensus_grandpa::SetId {
unimplemented!("runtime is only implemented when WASM")
}
fn generate_key_ownership_proof(
_set_id: sp_consensus_grandpa::SetId,
_authority_id: sp_consensus_grandpa::AuthorityId,
) -> Option<sp_consensus_grandpa::OpaqueKeyOwnershipProof> {
unimplemented!("runtime is only implemented when WASM")
}
fn submit_report_equivocation_unsigned_extrinsic(
equivocation_proof: sp_consensus_grandpa::EquivocationProof<
<Block as sp_runtime::traits::Block>::Hash,
u64,
>,
_: sp_consensus_grandpa::OpaqueKeyOwnershipProof,
) -> Option<()> {
unimplemented!("runtime is only implemented when WASM")
}
}
impl sp_authority_discovery::AuthorityDiscoveryApi<Block> for Runtime {
fn authorities() -> Vec<sp_authority_discovery::AuthorityId> {
unimplemented!("runtime is only implemented when WASM")
}
}
impl crate::SeraiApi<Block> for Runtime {
fn events() -> Vec<Vec<Vec<u8>>> {
unimplemented!("runtime is only implemented when WASM")
}
fn validators(
network: NetworkId
) -> Vec<serai_abi::primitives::crypto::Public> {
unimplemented!("runtime is only implemented when WASM")
}
fn current_session(network: NetworkId) -> Option<Session> {
unimplemented!("runtime is only implemented when WASM")
}
fn current_stake(network: NetworkId) -> Option<Amount> {
unimplemented!("runtime is only implemented when WASM")
}
fn keys(set: ExternalValidatorSet) -> Option<KeyPair> {
unimplemented!("runtime is only implemented when WASM")
}
fn current_validators(network: NetworkId) -> Option<Vec<SeraiAddress>> {
unimplemented!("runtime is only implemented when WASM")
}
fn pending_slash_report(network: ExternalNetworkId) -> bool {
unimplemented!("runtime is only implemented when WASM")
}
fn embedded_elliptic_curve_keys(
validator: SeraiAddress,
network: ExternalNetworkId,
) -> Option<EmbeddedEllipticCurveKeys> {
unimplemented!("runtime is only implemented when WASM")
}
}
}
}
#[cfg(not(target_family = "wasm"))]
pub use apis::RuntimeApi;
// If this isn't WASM, regardless of what it is, we include the WASM blob from the build script
#[cfg(all(not(target_family = "wasm"), debug_assertions))]
pub const WASM: &[u8] =
include_bytes!(concat!(env!("OUT_DIR"), "/target/wasm32v1-none/debug/serai_runtime.wasm"));
#[cfg(all(not(target_family = "wasm"), not(debug_assertions)))]
pub const WASM: &[u8] =
include_bytes!(concat!(env!("OUT_DIR"), "/target/wasm32v1-none/release/serai_runtime.wasm"));

View File

@@ -0,0 +1,174 @@
use alloc::borrow::Cow;
use serai_abi::{
primitives::{
crypto::{KeyPair, EmbeddedEllipticCurveKeys},
network_id::{ExternalNetworkId, NetworkId},
validator_sets::{Session, ExternalValidatorSet},
balance::Amount,
address::SeraiAddress,
},
SubstrateHeader as Header, SubstrateBlock as Block,
};
use super::*;
#[sp_version::runtime_version]
pub const VERSION: sp_version::RuntimeVersion = sp_version::RuntimeVersion {
spec_name: Cow::Borrowed("serai"),
impl_name: Cow::Borrowed("core"),
authoring_version: 0,
// Use the highest possible value so the node doesn't attempt to use this in place of the WASM
spec_version: 0xffffffff,
impl_version: 0,
apis: RUNTIME_API_VERSIONS,
transaction_version: 0,
system_version: 0,
};
/// A `struct` representing the runtime as necessary to define the available APIs.
pub struct Runtime;
sp_api::impl_runtime_apis! {
impl sp_api::Core<Block> for Runtime {
fn version() -> sp_version::RuntimeVersion {
VERSION
}
fn initialize_block(header: &Header) -> sp_runtime::ExtrinsicInclusionMode {
unimplemented!("runtime is only implemented when WASM")
}
fn execute_block(block: Block) {
unimplemented!("runtime is only implemented when WASM")
}
}
impl sp_block_builder::BlockBuilder<Block> for Runtime {
fn apply_extrinsic(
extrinsic: <Block as sp_runtime::traits::Block>::Extrinsic,
) -> sp_runtime::ApplyExtrinsicResult {
unimplemented!("runtime is only implemented when WASM")
}
fn finalize_block() -> Header {
unimplemented!("runtime is only implemented when WASM")
}
fn inherent_extrinsics(
data: sp_inherents::InherentData,
) -> Vec<<Block as sp_runtime::traits::Block>::Extrinsic> {
unimplemented!("runtime is only implemented when WASM")
}
fn check_inherents(
block: Block,
data: sp_inherents::InherentData,
) -> sp_inherents::CheckInherentsResult {
unimplemented!("runtime is only implemented when WASM")
}
}
impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
fn validate_transaction(
source: sp_runtime::transaction_validity::TransactionSource,
tx: <Block as sp_runtime::traits::Block>::Extrinsic,
block_hash: <Block as sp_runtime::traits::Block>::Hash,
) -> sp_runtime::transaction_validity::TransactionValidity {
unimplemented!("runtime is only implemented when WASM")
}
}
impl sp_consensus_babe::BabeApi<Block> for Runtime {
fn configuration() -> sp_consensus_babe::BabeConfiguration {
unimplemented!("runtime is only implemented when WASM")
}
fn current_epoch_start() -> sp_consensus_babe::Slot {
unimplemented!("runtime is only implemented when WASM")
}
fn current_epoch() -> sp_consensus_babe::Epoch {
unimplemented!("runtime is only implemented when WASM")
}
fn next_epoch() -> sp_consensus_babe::Epoch {
unimplemented!("runtime is only implemented when WASM")
}
fn generate_key_ownership_proof(
_slot: sp_consensus_babe::Slot,
_authority_id: sp_consensus_babe::AuthorityId,
) -> Option<sp_consensus_babe::OpaqueKeyOwnershipProof> {
unimplemented!("runtime is only implemented when WASM")
}
fn submit_report_equivocation_unsigned_extrinsic(
equivocation_proof: sp_consensus_babe::EquivocationProof<Header>,
_: sp_consensus_babe::OpaqueKeyOwnershipProof,
) -> Option<()> {
unimplemented!("runtime is only implemented when WASM")
}
}
impl sp_consensus_grandpa::GrandpaApi<Block> for Runtime {
fn grandpa_authorities() -> sp_consensus_grandpa::AuthorityList {
unimplemented!("runtime is only implemented when WASM")
}
fn current_set_id() -> sp_consensus_grandpa::SetId {
unimplemented!("runtime is only implemented when WASM")
}
fn generate_key_ownership_proof(
_set_id: sp_consensus_grandpa::SetId,
_authority_id: sp_consensus_grandpa::AuthorityId,
) -> Option<sp_consensus_grandpa::OpaqueKeyOwnershipProof> {
unimplemented!("runtime is only implemented when WASM")
}
fn submit_report_equivocation_unsigned_extrinsic(
equivocation_proof: sp_consensus_grandpa::EquivocationProof<
<Block as sp_runtime::traits::Block>::Hash,
u64,
>,
_: sp_consensus_grandpa::OpaqueKeyOwnershipProof,
) -> Option<()> {
unimplemented!("runtime is only implemented when WASM")
}
}
impl sp_authority_discovery::AuthorityDiscoveryApi<Block> for Runtime {
fn authorities() -> Vec<sp_authority_discovery::AuthorityId> {
unimplemented!("runtime is only implemented when WASM")
}
}
impl crate::SeraiApi<Block> for Runtime {
fn events() -> Vec<Vec<Vec<u8>>> {
unimplemented!("runtime is only implemented when WASM")
}
fn validators(
network: NetworkId
) -> Vec<serai_abi::primitives::crypto::Public> {
unimplemented!("runtime is only implemented when WASM")
}
fn current_session(network: NetworkId) -> Option<Session> {
unimplemented!("runtime is only implemented when WASM")
}
fn current_stake(network: NetworkId) -> Option<Amount> {
unimplemented!("runtime is only implemented when WASM")
}
fn keys(set: ExternalValidatorSet) -> Option<KeyPair> {
unimplemented!("runtime is only implemented when WASM")
}
fn current_validators(network: NetworkId) -> Option<Vec<SeraiAddress>> {
unimplemented!("runtime is only implemented when WASM")
}
fn pending_slash_report(network: ExternalNetworkId) -> bool {
unimplemented!("runtime is only implemented when WASM")
}
fn embedded_elliptic_curve_keys(
validator: SeraiAddress,
network: ExternalNetworkId,
) -> Option<EmbeddedEllipticCurveKeys> {
unimplemented!("runtime is only implemented when WASM")
}
}
}

View File

@@ -73,11 +73,10 @@ impl frame_system::Config for Runtime {
// We assume `serai-node` will be run using the RocksDB backend
type DbWeight = frame_support::weights::constants::RocksDbWeight;
/*
Serai does not expose `frame_system::Call` nor does it use transaction extensions. We
accordingly have no consequence to using the default weights for these accordingly.
Serai does not expose `frame_system::Call`. We accordingly have no consequence to using the
default weights for these accordingly.
*/
type SystemWeightInfo = ();
type ExtensionsWeightInfo = ();
// We also don't use `frame_system`'s account system at all, leaving us to bottom these out.
type AccountData = ();

View File

@@ -54,8 +54,9 @@ pub fn reproducibly_builds() {
.arg("--quiet")
.arg("--rm")
.arg(&image)
.arg("busybox")
.arg("sha256sum")
.arg("/serai/serai.wasm")
.arg("/serai.wasm")
.output(),
);
// Attempt to clean up the image