Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ jobs:
GIT_SHORT_HASH: ${{ steps.vars.outputs.short_hash }}

- name: Trivy vulnerability scan
uses: aquasecurity/trivy-action@97e0b3872f55f89b95b2f65b3dbab56962816478 # v0.34.2
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0
with:
input: /tmp/image
format: sarif
Expand Down
19 changes: 11 additions & 8 deletions arcup/arcup
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ YELLOW='\033[1;33m'
NC='\033[0m' # No Color

info() {
echo -e "${GREEN}info${NC}: $1"
echo -e "${GREEN}info${NC}: $1" >&2
}

warn() {
echo -e "${YELLOW}warn${NC}: $1"
echo -e "${YELLOW}warn${NC}: $1" >&2
}

error() {
echo -e "${RED}error${NC}: $1"
echo -e "${RED}error${NC}: $1" >&2
exit 1
}

Expand Down Expand Up @@ -130,7 +130,7 @@ update_arcup() {
trap "rm -f $tmp_file" EXIT

info "Downloading latest arcup..."
if ! curl -fsSL "$ARCUP_BIN_URL" -o "$tmp_file" 2>/dev/null; then
if ! curl -fsSL "$ARCUP_BIN_URL" -o "$tmp_file"; then
error "Failed to download arcup update"
fi

Expand Down Expand Up @@ -271,12 +271,16 @@ get_latest_version() {
fi

local api_url="https://api.github.com/repos/$REPO/releases/latest"
local response
if ! response=$(curl -fsSL "$api_url" 2>&1); then
error "Failed to fetch latest version from GitHub: $response"
fi

local version
version=$(curl -sSL "$api_url" 2>/dev/null | \
grep '"tag_name":' | head -n 1 | sed 's/.*"tag_name": *"\([^"]*\)".*/\1/')
version=$(echo "$response" | grep '"tag_name":' | head -n 1 | sed 's/.*"tag_name": *"\([^"]*\)".*/\1/')

if [[ -z "$version" ]]; then
error "Failed to fetch latest version from GitHub"
error "Failed to parse version from GitHub API response"
fi

echo "$version"
Expand Down Expand Up @@ -331,7 +335,6 @@ main() {
fi

VERSION_TAG="$VERSION"
VERSION_NUMBER="${VERSION#v}"

info "Installing arc-node $VERSION_TAG"

Expand Down
14 changes: 7 additions & 7 deletions arcup/install
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ YELLOW='\033[1;33m'
NC='\033[0m'

info() {
echo -e "${GREEN}info${NC}: $1"
echo -e "${GREEN}info${NC}: $1" >&2
}

warn() {
echo -e "${YELLOW}warn${NC}: $1"
echo -e "${YELLOW}warn${NC}: $1" >&2
}

# Install a file to BIN_DIR, using sudo if necessary
Expand Down Expand Up @@ -53,7 +53,7 @@ main() {

info "Downloading arcup script..."
if command -v curl >/dev/null 2>&1; then
curl -# -L "$ARCUP_URL" -o "$tmp_file"
curl -#fL "$ARCUP_URL" -o "$tmp_file"
elif command -v wget >/dev/null 2>&1; then
wget --show-progress -q -O "$tmp_file" "$ARCUP_URL"
else
Expand All @@ -66,15 +66,15 @@ main() {
info "Arcup installed to $BIN_DIR/arcup"

# Create env file that can be sourced to set PATH (POSIX shells)
cat > "$ENV_FILE" <<'ENVEOF'
cat > "$ENV_FILE" <<ENVEOF
# arc shell setup
export PATH="$HOME/.arc/bin:$PATH"
export PATH="$BIN_DIR:\$PATH"
ENVEOF

# Create env file for fish shell
cat > "$ENV_FILE.fish" <<'ENVEOF'
cat > "$ENV_FILE.fish" <<ENVEOF
# arc shell setup
fish_add_path -g $HOME/.arc/bin
fish_add_path -g $BIN_DIR
ENVEOF

# Add BIN_DIR to PATH for current session
Expand Down
10 changes: 3 additions & 7 deletions crates/evm/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ where
let tx_kind = tx.kind();
let tx_value = tx.value();

if !self.can_load_account(evm, NATIVE_COIN_CONTROL_ADDRESS) {
return self.mainnet.pre_execution(evm);
}
evm.ctx_mut()
.journal_mut()
.load_account(NATIVE_COIN_CONTROL_ADDRESS)?;
self.check_blocklist(evm, caller, &tx_kind, tx_value)?;

self.mainnet.pre_execution(evm)
Expand Down Expand Up @@ -174,10 +174,6 @@ where
>,
ERROR: EvmTrError<EVM>,
{
fn can_load_account(&self, evm: &mut EVM, address: Address) -> bool {
evm.ctx_mut().journal_mut().load_account(address).is_ok()
}

fn check_blocklist(
&self,
evm: &mut EVM,
Expand Down
87 changes: 85 additions & 2 deletions crates/malachite-app/src/handlers/process_synced_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub async fn handle(
value_bytes: Bytes,
reply: Reply<Option<ProposedValue<ArcContext>>>,
) -> Result<(), eyre::Error> {
let proposal = on_process_synced_value(
let proposal = match on_process_synced_value(
EnginePayloadValidator::new(engine, state.metrics()),
state.store(),
state.store(),
Expand All @@ -61,7 +61,17 @@ pub async fn handle(
proposer,
value_bytes,
)
.await?;
.await
{
Ok(proposal) => proposal,
Err(e) => {
error!(%height, %round, %proposer, "ProcessSyncedValue failed: {e:#}");
if let Err(send_err) = reply.send(None) {
error!("🔴 ProcessSyncedValue: Failed to send error reply: {send_err:?}");
}
return Err(e);
}
};

// Mark this height as synced for proposal monitoring
if let Some(p) = &proposal
Expand Down Expand Up @@ -278,6 +288,79 @@ mod tests {
assert!(proposal.is_none());
}

// These two tests cover error paths in `on_process_synced_value` that were
// previously untested. They do NOT directly test the CCHAIN-1498 fix in
// `handle()`, which requires `State` and `Engine` — concrete types with no
// test builder. A `State` test harness would benefit all handler tests but
// is out of scope here.
#[tokio::test]
async fn on_process_synced_value_engine_validation_error() {
let mut u = Unstructured::new(&[0u8; 512]);

let height = Height::new(1);
let round = Round::new(0);
let proposer = Address::new([0u8; 20]);
let payload = ExecutionPayloadV3::arbitrary(&mut u).unwrap();
let value_bytes = Bytes::from(payload.as_ssz_bytes());

let mut engine = MockPayloadValidator::new();
engine
.expect_validate_payload()
.returning(|_| Err(io::Error::other("Simulated engine error").into()));

let mut undecided = MockUndecidedBlocksRepository::new();
undecided.expect_store().times(0);

let mut invalid = MockInvalidPayloadsRepository::new();
invalid.expect_append().times(0);

let result = on_process_synced_value(
engine,
undecided,
invalid,
height,
round,
proposer,
value_bytes,
)
.await;

assert!(result.is_err());
}

#[tokio::test]
async fn on_process_synced_value_invalid_payload_store_fails() {
let height = Height::new(1);
let round = Round::new(0);
let proposer = Address::new([0u8; 20]);
let value_bytes = Bytes::from(vec![0u8; 10]); // garbage bytes trigger SSZ decode failure

let mut engine = MockPayloadValidator::new();
engine.expect_validate_payload().times(0);

let mut undecided = MockUndecidedBlocksRepository::new();
undecided.expect_store().times(0);

let mut invalid = MockInvalidPayloadsRepository::new();
invalid
.expect_append()
.times(1)
.returning(|_| Err(io::Error::other("Simulated invalid payload store error")));

let result = on_process_synced_value(
engine,
undecided,
invalid,
height,
round,
proposer,
value_bytes,
)
.await;

assert!(result.is_err());
}

#[tokio::test]
async fn test_on_process_synced_value_store_error() {
let mut u = Unstructured::new(&[0u8; 512]);
Expand Down
12 changes: 12 additions & 0 deletions crates/quake/src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,16 @@ pub struct ElEngineConfig {
pub cross_block_cache_size: Option<u64>,
pub persistence_threshold: u64,
pub memory_block_buffer_target: u64,
pub legacy_state_root: Option<bool>,
}

/// Execution layer (Reth) storage configuration overrides.
///
/// Fields mirror reth's storage CLI flags and correspond to `--storage.*` flags.
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Default)]
#[serde(deny_unknown_fields, default)]
pub struct ElStorageConfig {
pub v2: Option<bool>,
}

/// Execution layer (Reth) gas price oracle configuration overrides.
Expand Down Expand Up @@ -383,6 +393,7 @@ pub struct ElConfigOverride {
pub tx_propagation_policy: Option<String>,
pub arc: ElArcConfig,
pub prune: ElPruneConfig,
pub storage: ElStorageConfig,
}

impl Default for ElConfigOverride {
Expand All @@ -403,6 +414,7 @@ impl Default for ElConfigOverride {
tx_propagation_policy: Option::default(),
arc: ElArcConfig::default(),
prune: ElPruneConfig::default(),
storage: ElStorageConfig::default(),
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions crates/quake/src/manifest/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ impl Manifest {
engine: ElEngineConfig {
disable_state_cache: Some(rng.gen_bool(0.1)),
cross_block_cache_size: Some(rng.gen_range(2048..=8192)),
legacy_state_root: Some(rng.gen_bool(0.1)),
..ElEngineConfig::default()
},
..ElConfigOverride::default()
Expand Down Expand Up @@ -959,6 +960,7 @@ mod tests {
(2048..=8192).contains(&cache),
"cross-block-cache-size = {cache}"
);
assert!(g.engine.legacy_state_root.is_some());
}
}

Expand Down
8 changes: 5 additions & 3 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,12 @@ git checkout v0.6.0

**3. Build and install:**

By default, `cargo install` places binaries in `~/.cargo/bin`, which is added to `PATH` by the Rust installer. Pass `--root <dir>` to install into `<dir>/bin` instead (e.g. `--root /usr/local`).

```sh
cargo install --path crates/node --root /usr/local
cargo install --path crates/malachite-app --root /usr/local
cargo install --path crates/snapshots --root /usr/local
cargo install --path crates/node
cargo install --path crates/malachite-app
cargo install --path crates/snapshots
```

Verify:
Expand Down