Skip to content

Merge v0.5.x hot fixes#114

Merged
bvscd merged 40 commits into
release/node/v0.6.0from
update
Apr 21, 2026
Merged

Merge v0.5.x hot fixes#114
bvscd merged 40 commits into
release/node/v0.6.0from
update

Conversation

@bvscd
Copy link
Copy Markdown
Collaborator

@bvscd bvscd commented Apr 21, 2026

No description provided.

Keshoid and others added 30 commits April 7, 2026 10:40
- Add AdaptiveSplit50 staking strategy that adapts stake amount based on current election state
- Emulate TON Elector's selection algorithm to compute minimum effective stake
- Split funds in half when viable, stake everything when half is below threshold
- Top-up stake when competitors raise theirs
Reserve the logical wallet name `master_wallet` in `nodectl`: operators cannot add a regular wallet with that name, and `config wallet rm` fails immediately with a clear error when that name is used.
* fix: max factor load from config

* fix: default factor func not pub

* fix: fix test

* fix: corrections according to comments

* fix: corrections according to comments

* fix(naming):validate_elections_max_factor_vs_chain → validate_max_factor

* fix(naming):max factor warning text

* fix: added tests,replaced code duplicationg
Add `nodectl vote` with subcommands to manage config proposal voting
…#86)

- Add REST API handlers for all `config ls` subcommands in the nodectl service
- Refactor `config`, `config bind/elections/log/node/pool/wallet`, and `master_wallet` CLI commands to call the REST API instead of touching files directly
- Use a fallback URL and default config path in commands
- `POST /v1/{nodes,wallets,pools,bindings}` and `DELETE /v1/{nodes,wallets,pools,bindings}/{name}`, all behind `require_operator`.
- Validation moved server-side.
- CLI `add`/`rm` become thin REST clients; `--url` / `--token` / `NODECTL_API_TOKEN` work the same as in SMA-19. Best-effort vault check kept in CLI for `node add` / `wallet add` until the key REST API lands.
## Summary

- Unified `POST /v1/elections/settings` replaces `/v1/stake_strategy`, individual tick-interval and max-factor endpoints. Accepts any combination of policy, tick_interval, max_factor in one request.
- Unified `POST /v1/ton-http-api` with `append` flag replaces separate set/add endpoints
- `POST /v1/log` for log settings mutation
- Removed `config stake-policy` CLI alias (use `config elections stake-policy`)

## Breaking changes

- `config ton-http-api`: renamed `--url` option to `--endpoint` (disambiguates from the root `config --url` option).
- Add support for the TON Core Nominator Pool alongside existing Single Nominator Pool
- Fixed calculation of the next elections range in `/v1/elections` response.
- bump nodectl version to 0.4.0
-  upd changelog for v0.4.0
- upd nodectl docs
#95)

- `config pool ls` and `GET /v1/pools` now render TONCore pools as a per-slot table with state (active / uninit / not deployed / error), balance, and on-chain pool params (validator share, max nominators, min stakes, nominators count, staked amount, pool state, last election id).
- added `POST /v1/pools/core` so `config pool add core` goes through REST like the rest of v0.4.0 entity CRUD instead of writing the local config file.
- ** run_singlehost_nodectl.py**: added scenarios - set of predefined env vars and parameters; two variants present - default + snp-toncore
- fixed race condition in force_reload()
Hot fix: Liteserver ListBlockTransactions
#99)

* Fix TONCore frozen stake accounting and singlehost election_id parsing

Only count frozen stake from past elections when the frozen entry wallet
matches the current staking address, so dual-pool TONCore nodes do not
double-count the other pool.

Update singlehost nodectl bootstrap to read election_id from nested API
result when present. Adjust runner test frozen_map wallet to pool address.

Made-with: Cursor

* fix: delete warning that not needed

* fix: copilot comments

* fix: rewrite log text
- **Bug**: `build_validators_snapshot` sourced `adnl`, `pubkey`, `key_id`, `key_election_id`, `key_expires_at`, `is_key_active`, and `stake` from elections/bid data instead of the active validator set — showing stale or incorrect values when a node is validating AND has submitted a new election bid
- **Fix**: All vset-related snapshot fields now come from the current validator set (p34) and `past_elections.frozen_map`. Extended `find_validator_entries` to return the matched `ValidatorEntry` from the node's config. Fields are `None` when the node is not in the validator set.
* feat(docs): update info about toncore pool

* fix(docs): add info about distinct addresses

* fix: set right value for min validator stake param
## Summary

- Add `elections.static_adnls` config map to store pre-generated ADNL addresses per node (base64)
- Add `generate_adnl_addr()` and `register_adnl_addr()` to `ElectionsProvider` trait
- Runner reuses stored ADNL address via `register_adnl_addr()` instead of generating a new one each cycle
- New `POST /v1/elections/static-adnl` endpoint: generates ADNL key on the validator node and saves it to config
- New CLI command: `nodectl config elections static-adnl --node <name>`
Merge master to release/nodectl/v0.4.0
* test: enhance create-proposal.ts script

* refactor(contracts): actualize comment to NominatorWrapper trait

* fix: after review

* fmt: make fmt
Copilot AI review requested due to automatic review settings April 21, 2026 12:14
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR merges hotfixes and feature work across the TON node and node-control (“nodectl”) tooling, including QUIC fast-sync overlay improvements, TONCore nominator pool support, and a shift to REST-based config mutations.

Changes:

  • Node networking: extend semiprivate overlays with separate ADNL IDs/public keys, add two-step broadcast, and optimize LiteServer transaction traversal/proof handling.
  • Nodectl/service: add TONCore pool support, unified elections settings endpoints, and atomic config update+persist flow with cache rebuild notifications.
  • Tooling/docs/CI: add new load-net scripts, update Helm chart/app versions, and introduce a nodectl E2E GitHub workflow.

Reviewed changes

Copilot reviewed 89 out of 95 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/node/tests/test_run_net_py/requirements.txt Adds Python dependency for singlehost/e2e tooling.
src/node/tests/test_load_net/scripts/withdraw-nominators-from-pool.ts New TONCore withdrawal load-test script.
src/node/tests/test_load_net/scripts/topup.ts Adds polling to await balance updates after transfers.
src/node/tests/test_load_net/scripts/toncore_pool_info.ts Adds TONCore pool introspection helpers.
src/node/tests/test_load_net/scripts/create-proposal.ts Updates proposal tooling (tx parsing + configurable endpoints).
src/node/tests/test_load_net/scripts/add-nominators-to-pool.ts New TONCore nominator deposit/load script.
src/node/tests/test_load_net/package.json Exposes new scripts via npm/bun commands.
src/node/src/rpc_server/token.rs Fixes address parsing for TVM stack slices.
src/node/src/network/overlay_client.rs Updates semiprivate overlay creation + adds two-step broadcast API.
src/node/src/network/liteserver.rs Optimizes listBlockTransactions traversal and proof generation flow.
src/node/src/network/full_node_overlays.rs Expands validator set handling and enables two-step broadcasts for fast sync.
src/node/src/network/fast_sync_overlay_client.rs Adds root public keys and QUIC/two-step broadcast support.
src/node/Cargo.toml Bumps node crate version to 0.5.1.
src/node-control/ton-http-api-client/Cargo.toml Bumps ton-http-api-client version.
src/node-control/service/src/voting/voting_task.rs Skips voting on non-validators and updates config contract address API usage.
src/node-control/service/src/task/task_manager.rs Updates RuntimeConfig trait usage in tests.
src/node-control/service/src/service_main_task.rs Adds config mutation notifications for cache rebuild + task restart.
src/node-control/service/src/runtime_config.rs Adds atomic update+persist, cache reload paths, and TONCore pool wiring.
src/node-control/service/src/http/mod.rs Splits config-related handlers into a module + adds tests module.
src/node-control/service/src/http/http_server_task.rs Adds REST config CRUD endpoints and updates OpenAPI wiring.
src/node-control/service/src/http/auth_tests.rs Updates auth tests to the new endpoints.
src/node-control/service/src/contracts/contracts_task.rs Adds TONCore pool validator-set update and multi-pool deploy support.
src/node-control/service/src/auth/user_store.rs Switches to atomic update+persist for auth user mutations.
src/node-control/service/Cargo.toml Bumps service version.
src/node-control/nodectl/Cargo.toml Bumps nodectl version.
src/node-control/elections/src/providers/traits.rs Extends provider trait with config params + ADNL management APIs.
src/node-control/elections/src/providers/default.rs Implements new provider methods via control-client.
src/node-control/elections/src/lib.rs Exposes new internal modules.
src/node-control/elections/Cargo.toml Bumps elections crate version.
src/node-control/docs/staking-strategies.md Adds detailed staking strategies documentation (incl. adaptive_split50).
src/node-control/docs/nodectl-security.md Updates operator capabilities list for new endpoints.
src/node-control/control-client/src/config_params.rs Adds parsing for config params 16/17.
src/node-control/control-client/Cargo.toml Bumps control-client version.
src/node-control/contracts/src/wallet/wallet_contract.rs Makes SmartContract::address async and updates callers.
src/node-control/contracts/src/smart_contract.rs Changes SmartContract::address signature to async.
src/node-control/contracts/src/nominator/wrapper.rs Expands nominator abstraction (kind, reserves, inner pools).
src/node-control/contracts/src/nominator/ton_core_nominator_router.rs Adds TONCore dual-pool router wrapper.
src/node-control/contracts/src/nominator/single_nominator.rs Renames wrapper and adds address+state calc helper.
src/node-control/contracts/src/nominator/messages.rs Adds TONCore pool message builders and tests.
src/node-control/contracts/src/nominator.rs Wires new nominator modules and exports.
src/node-control/contracts/src/lib.rs Re-exports new nominator types and helpers.
src/node-control/contracts/src/elector/elector_impl.rs Updates SmartContract::address to async.
src/node-control/contracts/src/config_contract/config_impl.rs Updates SmartContract::address to async + fixes tests accordingly.
src/node-control/contracts/Cargo.toml Bumps contracts version.
src/node-control/common/src/ton_utils.rs Adds max_factor extraction and TON address normalization helpers.
src/node-control/common/src/serde_utils.rs Adjusts derive usage in serde tests.
src/node-control/common/src/app_config.rs Adds TONCore pool config, adaptive policy, elections timing/static_adnls.
src/node-control/common/Cargo.toml Bumps common version.
src/node-control/commands/src/commands/nodectl/utils.rs Adds service API helpers + TONCore pool address resolution helpers.
src/node-control/commands/src/commands/nodectl/service_api_cmd.rs Updates REST endpoints and adds adaptive_split50 flag.
src/node-control/commands/src/commands/nodectl/mod.rs Adds vote_cmd module export.
src/node-control/commands/src/commands/nodectl/master_wallet_cmd.rs Switches master wallet info to REST-based retrieval.
src/node-control/commands/src/commands/nodectl/deploy_cmd.rs Adds TONCore pool deploy targets and binding-based deploy flow.
src/node-control/commands/src/commands/nodectl/config_wallet_cmd.rs Moves wallet CRUD to REST and updates staking max_factor validation.
src/node-control/commands/src/commands/nodectl/config_ton_http_api_cmd.rs Switches TON HTTP API config to unified REST endpoint.
src/node-control/commands/src/commands/nodectl/config_node_cmd.rs Moves node CRUD/list to REST.
src/node-control/commands/src/commands/nodectl/config_log_cmd.rs Moves log config to REST endpoints.
src/node-control/commands/src/commands/nodectl/config_cmd.rs Adds global REST URL/token flags and removes local stake-policy alias.
src/node-control/commands/src/commands/nodectl/config_bind_cmd.rs Moves bindings CRUD/list to REST.
src/node-control/commands/src/commands/nodectl/auth_cmd.rs Adds password stdin option for non-interactive user creation.
src/node-control/commands/src/commands/cli_cmd.rs Adds vote command entry point.
src/node-control/commands/src/command_manager.rs Routes vote command execution.
src/node-control/commands/Cargo.toml Adds hex dep and bumps commands version.
src/node-control/Makefile Adds singlehost e2e targets and venv bootstrap.
src/node-control/CHANGELOG.md Documents nodectl v0.4.0 changes and breaking changes.
src/adnl/tests/test_overlay.rs Updates semiprivate overlay test for new API signature.
src/adnl/src/overlay/mod.rs Adds CertifiedMembers roots by ADNL/public keys + QUIC/twostep behavior changes.
helm/nodectl/values.yaml Bumps default image tag to v0.4.0.
helm/nodectl/docs/setup.md Documents TONCore pools and new CLI flows.
helm/nodectl/docs/elections.md Updates elections docs for new policies/pools.
helm/nodectl/README.md Updates chart README for TONCore pool support.
helm/nodectl/Chart.yaml Bumps chart/app versions.
helm/nodectl/CHANGELOG.md Adds chart changelog entry for v0.4.0 appVersion.
CHANGELOG.md Documents node v0.5.2/v0.5.1 entries.
.github/workflows/nodectl-e2e.yml Adds PR-triggered nodectl e2e workflow.
.github/workflows/ci.yml Ignores docs-only changes for CI runs.
Comments suppressed due to low confidence (1)

src/node-control/CHANGELOG.md:1

  • The PR title suggests this is a merge of v0.5.x hot fixes, but the diff includes a substantial nodectl v0.4.0 feature release (new REST config API, TONCore pools, new staking strategy, new CLI commands, Helm/app version bumps). Consider updating the PR title (or splitting) so reviewers can accurately scope changes and risk.
# Changelog

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

lt, hash,
});
for (const tx of transactions) {
const transactions = await getTransactions(configAddress, 10, parseInt(lt), hash);
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parsing lt with parseInt(lt) is unsafe because transaction LTs can exceed JS Number.MAX_SAFE_INTEGER, leading to precision loss and incorrect pagination/lookup. Pass lt through as a string (as returned by the node) or use BigInt, and update getTransactions to serialize it accordingly.

Suggested change
const transactions = await getTransactions(configAddress, 10, parseInt(lt), hash);
const transactions = await getTransactions(configAddress, 10, lt, hash);

Copilot uses AI. Check for mistakes.
Comment on lines +210 to 232
async function getTransactions(address: Address, limit: number, lt: number, hash: string) {
const result = await fetch(`${getBaseUrl()}jsonRPC`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
jsonrpc: '2.0',
method: 'getTransactions',
params: {
address: address.toString(),
limit,
lt,
hash,
},
}),
});
const data = await result.json();
if (!data.ok) {
throw new Error(`Failed to get config: ${data.error}`);
throw new Error(`Failed to get transactions: ${data.error}`);
}
return Cell.fromBase64(data.result.config.bytes as string);
return data.result;
}
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getTransactions is using a JSON-RPC endpoint but checks data.ok, which is not part of standard JSON-RPC responses. This will falsely throw (or miss errors) depending on the server. Handle JSON-RPC by checking data.error (and optionally result) and include an id field in the request body.

Copilot uses AI. Check for mistakes.
Comment on lines +366 to +415
let mut deploy_targets: Vec<(MsgAddressInt, ton_block::StateInit)> = match pool_cfg {
PoolConfig::TONCore { pools } => {
let mut targets = Vec::new();
for slot in pools.iter() {
let Some(cfg) = slot else { continue };
match (&cfg.address, &cfg.params) {
(_, Some(params)) => {
let resolved = resolve_toncore_pool(
&wallet_address,
cfg.address.as_deref(),
params.clone(),
)
.map_err(set_err)?;
targets.push((resolved.address, resolved.state_init));
}
(Some(address), None) => {
return Err(set_err(anyhow::anyhow!(
"TONCore pool slot has address '{}' but no deploy params",
address
)));
}
(None, None) => {}
}
}
targets
}
PoolConfig::SNP { .. } => {
let owner = self.owner.as_ref().ok_or_else(|| {
set_err(anyhow::anyhow!(
"SNP deploy requires --owner (use TONCore pool for deploy without --owner)"
))
})?;
let (pool_address, state_init) =
SingleNominatorWrapper::calculate_address_and_state(-1, owner, &wallet_address)
.map_err(set_err)?;
vec![(pool_address, state_init)]
}
};

if matches!(pool_cfg, PoolConfig::TONCore { pools } if pools[1].is_some()) {
let slot = toncore_pool_slot_from_cli_flags(self.pool_even, self.pool_odd);
let one = deploy_targets
.get(slot)
.cloned()
.ok_or_else(|| {
anyhow::anyhow!("TONCore nominator deploy: invalid pool slot {}", slot)
})
.map_err(set_err)?;
res.borrow_mut().address = pool_address.to_string();
deploy_targets = vec![one];
}
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TONCore deploy target selection is index-based after filtering out None slots, so deploy_targets[1] is not guaranteed to correspond to the odd slot (e.g., if only slot 1 is configured, it becomes index 0 and --pool-odd fails). Preserve the slot index when building targets (e.g., build [Option<(addr, state_init)>; 2] or push (slot_index, addr, state_init)), then select by slot index.

Copilot uses AI. Check for mistakes.
tokio::task::spawn_blocking(move || {
let root = read_single_root_boc(&raw)?;
let usage = UsageTree::with_params(root.clone(), true);
let usage = UsageTree::with_params(root.clone(), false);
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This path constructs UsageTree with the second parameter set to false, but later potentially derives a Merkle proof via MerkleProof::create_by_usage_tree(&root, &usage) (when WANT_PROOF is set). If false disables usage tracking, the generated proof can be incomplete/invalid. Consider enabling usage tracking when WANT_PROOF is requested (or always, if proof correctness relies on it).

Suggested change
let usage = UsageTree::with_params(root.clone(), false);
let track_usage = mode & WANT_PROOF != 0;
let usage = UsageTree::with_params(root.clone(), track_usage);

Copilot uses AI. Check for mistakes.
Comment on lines +147 to +157
let parse_coins = |key: &str| -> anyhow::Result<Coins> {
let val = p17.get(key).ok_or_else(|| anyhow::anyhow!("{} not found", key))?;
// It can be a string (decimal) or a number
if let Some(s) = val.as_str() {
Ok(Coins::from(u64::from_str_radix(s, 10).context(format!("parse {} as u64", key))?))
} else if let Some(n) = val.as_u64() {
Ok(Coins::from(n))
} else {
anyhow::bail!("{} is not a valid coins value", key)
}
};
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coins can represent values larger than u64, but the string parsing path forces u64, which can fail or truncate on larger networks/fields. Parse decimal strings as u128 (or use Coins::from_str / ton_block-provided parsing) and only downcast if you explicitly want to cap the value.

Copilot uses AI. Check for mistakes.
endpoint: process.env.API_ENDPOINTS!.split(",")[0] + "jsonRPC",
});
const master = tonClient.open(masterWallet);
const balanceBefore = await tonClient.getBalance(address);
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On success, the function returns without confirming completion (and without printing the updated balance), which makes CLI behavior less clear compared to the previous log message. Consider logging a success message (optionally including fromNano(balance)) before returning.

Copilot uses AI. Check for mistakes.
sendMode: SendMode.PAY_GAS_SEPARATELY,
});
console.log(`Topped up ${address} with ${fromNano(amount)} TON`);
console.log(`Sent ${fromNano(amount)} TON to ${address}, waiting for balance update...`);
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On success, the function returns without confirming completion (and without printing the updated balance), which makes CLI behavior less clear compared to the previous log message. Consider logging a success message (optionally including fromNano(balance)) before returning.

Copilot uses AI. Check for mistakes.
Comment on lines +65 to +72
while (Date.now() - start < timeout) {
const balance = await tonClient.getBalance(address);
if (balance > balanceBefore) {
return;
}
await new Promise((r) => setTimeout(r, poll));
}
throw new Error(`Timed out waiting for balance update after ${timeout / 1000}s`);
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On success, the function returns without confirming completion (and without printing the updated balance), which makes CLI behavior less clear compared to the previous log message. Consider logging a success message (optionally including fromNano(balance)) before returning.

Copilot uses AI. Check for mistakes.
Comment on lines +30 to +35
### Breaking Changes

- **Removed `POST /v1/stake_strategy`** — use `POST /v1/elections/settings` with `{"policy": ...}`.
- **Removed `config stake-policy` top-level alias** — use `config elections stake-policy`.
- **`config ton-http-api set --url` → `--endpoint`** — the flag was renamed (short form `-e`) to disambiguate from the root `--url` service-URL flag introduced for REST client commands. Update any scripts invoking `nodectl config ton-http-api --url ...`.
- **Configuration mutations require a running service** — `config {node,wallet,pool,bind,elections,log,ton-http-api,master-wallet}` subcommands are now REST clients and need the service to be running with an operator user. Only `config generate` still writes to disk directly.
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR title suggests this is a merge of v0.5.x hot fixes, but the diff includes a substantial nodectl v0.4.0 feature release (new REST config API, TONCore pools, new staking strategy, new CLI commands, Helm/app version bumps). Consider updating the PR title (or splitting) so reviewers can accurately scope changes and risk.

Copilot uses AI. Check for mistakes.
@bvscd bvscd merged commit e98f162 into release/node/v0.6.0 Apr 21, 2026
6 checks passed
@bvscd bvscd deleted the update branch April 21, 2026 12:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants