9 Commits

Author SHA1 Message Date
Luke Parker
c98d757c0f Ensure the signed arithmetic won't overflow, expand shells tested with (#701)
* Normalize naming for the stack size CI file

* Extend stack size CI with `posh` and `lksh`

`posh` is a derivative of `pdksh` explicitly intended for ensuring
Debian-policy-compliance.

`lksh` is more-POSIX-esque, legacy shell included along-side `mksh`.

* Ensure a signed long overflow won't occur

Also fixes `write_bytes` when the written bytes have alphabetical digits when
encoded as hexadecimal.

* Improve sh semantics in stack-size workflow
2025-12-09 04:03:24 -05:00
Luke Parker
6603100c7e Add a CI for increase_default_stack_size.sh
This runs whenever the script is modified, or weekly to ensure the CI doesn't
inadvertently decay (due to using the latest packages for a variety of shells).

This runs with `sh` (presumably `dash`), `ksh`, `bash`, `dash` (explicitly),
`zsh`, `ash` (Busybox), `hush` (Busybox), `mksh`, `yash`, and `brush`. While
none of these guarantee this script is POSIX-compliant, as a fully and
explicitly-only POSIX-compliant environment is not constructed, this does
reasonably test the script itself to be POSIX-compliant. The tools called have
been reviewed for being used to the POSIX standard (although not audited to
that degree).

The script itself is modified with the following changes for compliance with
POSIX:
1) `hexdump` is replaced with `od` (`od` suggested by @PlasmaPower)
2) `printf \xFF` replaced with octal escapes, as `\x` is not part of POSIX
3) `head -c` is replaced with `cut`, as the `-c` option is not standardized
   under POSIX (despite it being present for `tail`). This was identified by
   @PlasmaPower. As we used `head -c-2` to truncate the last two characters of
   a string, we now use `wc -c` for a `strlen` to enable the necessary
   arithmetic to calculate what two bytes in from the end of the string is.

This entire effort can be argued pointless, as we could simply run `monerod` on
Debian. This script is useful, the journey down the rabbithole of POSIX
compliance fascinating, and the methodology applicable to other potential
futures though (whether running binaries on Alpine or testing other `sh`
scripts for their portability). As part of this effort overall, our CI was
extended with `shellcheck` for all `sh` scripts in-tree, including all of our
existing `sh` scripts. That there is an actual, direct benefit past this
specific effort.
2025-12-09 00:57:26 -05:00
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
41 changed files with 791 additions and 377 deletions

View File

@@ -62,7 +62,7 @@ runs:
docker system prune -a --volumes
sudo apt remove -y *docker*
# Install uidmap which will be required for the explicitly installed Docker
sudo apt install uidmap
sudo apt install -y uidmap
if: runner.os == 'Linux'
- name: Update system dependencies

View File

@@ -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 -y shellcheck
find . -iname "*.sh" | while read -r script; do
shellcheck --enable=all --shell=sh --severity=info $script
done

93
.github/workflows/stack-size.yml vendored Normal file
View File

@@ -0,0 +1,93 @@
name: Check Update Default Stack Size
on:
push:
paths:
- "orchestration/increase_default_stack_size.sh"
pull_request:
paths:
- "orchestration/increase_default_stack_size.sh"
workflow_dispatch:
# Also run weekly to ensure this doesn't inadvertently decay
schedule:
- cron: "0 0 * * 1"
jobs:
stack_size:
strategy:
matrix:
os: [ubuntu-latest, ubuntu-24.04, ubuntu-22.04]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # 6.0.0
- name: Download Monero
uses: ./.github/actions/monero
- name: Verify expected behavior
shell: bash
run: |
cp /usr/bin/monerod monerod
STACK=$((8 * 1024 * 1024))
cp monerod monerod-chelf
git clone https://github.com/Gottox/chelf
cd chelf
git checkout b2994186cea7b7d61a588fd06c1cc1ae75bcc21a
make
./chelf -s "$STACK" ../monerod-chelf
cd ..
cp monerod monerod-muslstack
GOBIN=$(pwd) go install github.com/yaegashi/muslstack@d19cc5866abce3ca59dfc1666df7cc97097d0933
./muslstack -s "$STACK" ./monerod-muslstack
sudo apt update -y
sudo apt install -y ksh bash dash zsh busybox mksh posh yash
sudo ln -s "$(which busybox)" /usr/bin/ash
sudo ln -s "$(which busybox)" /usr/bin/hush
cargo install brush-shell
for shell in sh ksh bash dash zsh ash hush mksh lksh posh yash brush; do
cp monerod monerod-idss-$shell
ln -s "$(which $shell)" sh
./sh ./orchestration/increase_default_stack_size.sh monerod-idss-$shell
rm ./sh
done
sha256() {
sha256sum "$1" | cut -d' ' -f1
}
CHELF=$(sha256 monerod-chelf)
find . -iname "monerod-*" | while read -r bin; do
BIN=$(sha256 "$bin")
if [ ! "$CHELF" = "$BIN" ]; then
echo "Different artifact between monerod-chelf ($CHELF) and $bin ($BIN)"
exit 1
fi
done
read_stack() {
STACK_INFO=$(readelf "$1" -l | grep STACK -A1)
MEMSZ=$(printf "%s\n" "$STACK_INFO" | tail -n1 | sed -E s/^[[:space:]]*//g | cut -f2 -d' ')
printf "%i" $((MEMSZ))
}
INITIAL_STACK=$(read_stack monerod)
if [ "$INITIAL_STACK" -ne "0" ]; then
echo "Initial \`PT_GNU_STACK\` wasn't 0"
exit 2
fi
UPDATED_STACK=$(read_stack monerod-chelf)
if [ "$UPDATED_STACK" -ne "$STACK" ]; then
echo "Updated \`PT_GNU_STACK\` ($UPDATED_STACK) wasn't 8 MB ($STACK)"
exit 3
fi
# Only one byte should be different due to the bit pattern of 8 MB
BYTES_DIFFERENT=$(cmp -l monerod monerod-chelf | wc -l || true)
if [ "$BYTES_DIFFERENT" -ne 1 ]; then
echo "More than one byte was different between the two binaries"
exit 4
fi

434
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -184,7 +184,11 @@ 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
]

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,194 @@
#!/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
}
hex_to_octal() {
HEX=$(printf "%s" "$1" | tr "[:lower:]" "[:upper:]")
printf "ibase=16; obase=8; %s\n" "$HEX" | bc
}
write_bytes() {
POS=$1
BYTES=$2
while [ ! "$BYTES" = "" ]; do
NEXT=$(printf "%s" "$BYTES" | cut -c-2)
# Advance to the third byte, as in, after the first two bytes
BYTES=$(printf "%s" "$BYTES" | tail -c+3)
NEXT=$(hex_to_octal "$NEXT")
# shellcheck disable=SC2059
printf \\"$NEXT" | dd conv=notrunc bs=1 seek="$POS" of="$ELF" 2> /dev/null
POS=$((POS + 1))
done
}
# Magic
MAGIC=$(read_bytes 0 4)
# shellcheck disable=SC2059
EXPECTED_MAGIC=$(printf \\"$(hex_to_octal 7f)"ELF | 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")
BYTES=$(printf "%s" "$BYTES" | tr "[:lower:]" "[:upper:]")
LESS_THAN_SANITY=$(printf "ibase=16; if(%s < 6FFFFFFF)1;\n" "$BYTES" | bc)
if [ ! "$LESS_THAN_SANITY" = "1" ]; then
echo "Integer value is approximate to 2**31, risking a signed long overflow"
exit 4
fi
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 5
;;
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 :; do
printf "%s" "$BYTES" | tail -c2
NEW_LENGTH=$(( $(printf "%s" "$BYTES" | wc -c) - 2 ))
if [ "$NEW_LENGTH" -eq 0 ]; then
break
fi
BYTES=$(printf "%s" "$BYTES" | cut -c-$NEW_LENGTH)
done
}
ELF_VERSION=$(read_bytes 6 1)
if [ ! "$ELF_VERSION" = "01" ]; then
echo "Unknown ELF Version ($ELF_VERSION)"
exit 6
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 7
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 8
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" | cut -c-8)
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
# This line is the only line really risking an arithmetic overflow, yet the bound on the start of
# the section, combined with a maximum section length of `0xffff * 0x38`, makes this fit
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 9
fi
echo "All instances of \`PT_GNU_STACK\` patched to be at least 8 MB"
exit 0

View File

@@ -37,6 +37,6 @@ COPY --from=builder /bin/busybox /bin/
ENV LD_LIBRARY_PATH=/lib/
ENV PATH=/bin
# Copy the artifact itself
COPY --from=builder /serai/target/release/wbuild/serai-runtime/serai_runtime.wasm /serai.wasm
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

@@ -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

@@ -70,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",

View File

@@ -1,4 +1,101 @@
fn main() {
#[cfg(not(target_family = "wasm"))]
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

@@ -20,5 +20,9 @@ mod std_runtime_api;
pub use std_runtime_api::RuntimeApi;
// If this isn't WASM, regardless of what it is, we include the WASM blob from the build script
#[cfg(not(target_family = "wasm"))]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
#[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

@@ -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 = ();