mirror of
https://gitlab.com/pezkuwichain/pezkuwi-sdk.git
synced 2026-10-20 18:56:23 +00:00
sync: mirror deployed github repo (chains + sanitized bridge), keep GitLab CI
Make this monorepo's tracked tree identical to the deployed github repo (github.com/pezkuwichain/pezkuwi-DKS): all RC/AH/People runtimes and framework carry the mainnet fixes (incl. U128CurrencyToVote everywhere, so the staking election stall cannot recur), and tools/usdt-bridge matches the current, public-safe custody tooling (real config/deploy units gitignored, secret-file locations and server IPs stripped, sanitized *.example templates committed). Only exception to the mirror: GitLab-native CI is preserved (.gitlab-ci.yml and .gitlab/), to be rebuilt to match the github CI pipeline in a follow-up.
This commit is contained in:
1 parent
82543bdfab
commit
d285d59108
736 files changed
+15082
-16359
No files matched your search
@@ -1 +1,12 @@
|
||||
secrets/
|
||||
# Real operational config & deploy units — NEVER commit. They expose chat IDs, auto-pay
|
||||
# thresholds, server paths/IPs and secret-file locations. Use the *.example templates and
|
||||
# provide real values only on the deployment host (env vars / EnvironmentFile / res dir).
|
||||
bridge_config.json
|
||||
pezbridge_bot_config.json
|
||||
deploy/*.service
|
||||
!deploy/*.service.example
|
||||
# Runtime data & any secret material that must never reach a repo
|
||||
bridge_db.json
|
||||
bridge_seed.json
|
||||
*_seed.json
|
||||
*.env
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"polkadot_rpc": "wss://<polkadot-asset-hub-rpc-endpoint>",
|
||||
"pezkuwi_rpc": "wss://<pezkuwi-asset-hub-rpc-endpoint>",
|
||||
"polkadot_usdt_asset_id": 1984,
|
||||
"pezkuwi_wusdt_asset_id": 1000,
|
||||
"min_deposit": 1000000,
|
||||
"min_withdraw": 1000000,
|
||||
"fee_basis_points": 10,
|
||||
"seed_path": "<PATH_TO_BRIDGE_SEED_JSON> // prefer the BRIDGE_SEED_MNEMONIC env var; the seed file is stale for custody ops (multisig owns wUSDT)",
|
||||
"db_path": "bridge_db.json",
|
||||
"custody_multisig_polkadot": "<POLKADOT_3OF5_MULTISIG_SS58>",
|
||||
"custody_multisig_pezkuwi": "<PEZKUWI_3OF5_MULTISIG_SS58>",
|
||||
"serok_chat_id": "<TELEGRAM_ADMIN_CHAT_ID>",
|
||||
"ops_chat_id": "<TELEGRAM_OPS_CHAT_ID>",
|
||||
"max_single_tx": 0,
|
||||
"auto_pay_daily_cap": 0,
|
||||
"circuit_breaker_window_minutes": 30,
|
||||
"circuit_breaker_fraction": 0.5
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
{
|
||||
"polkadot_rpc": "wss://polkadot-asset-hub-rpc.polkadot.io",
|
||||
"pezkuwi_rpc": "wss://asset-hub-rpc.pezkuwichain.io",
|
||||
"polkadot_usdt_asset_id": 1984,
|
||||
"pezkuwi_wusdt_asset_id": 1000,
|
||||
"min_deposit": 1000000,
|
||||
"min_withdraw": 1000000,
|
||||
"fee_basis_points": 10,
|
||||
"seed_path": "bridge_seed.json",
|
||||
"db_path": "bridge_db.json",
|
||||
"custody_multisig_polkadot": "15sF76THfpefUaKomHZSpssayRbsp6Yt6ESgMrLjzJCmpe66",
|
||||
"custody_multisig_pezkuwi": "5GvwxmCDp3PC33KHoeWSgj3S7ocE7nzk1jiCCZMPSDBFeNcj",
|
||||
"serok_chat_id": 5362991649,
|
||||
"ops_chat_id": -5420200114,
|
||||
"max_single_tx": 50000000000,
|
||||
"auto_pay_daily_cap": 200000000000,
|
||||
"circuit_breaker_window_minutes": 30,
|
||||
"circuit_breaker_fraction": 0.5,
|
||||
"_automation_2026-07-14": {
|
||||
"note": "Small/mid swaps auto-pay via the automation key's Assets.transfer_approved allowance - no per-transaction 3-of-5 wait. max_single_tx (50,000 USDT) caps any single auto-paid transaction; auto_pay_daily_cap (200,000 USDT) is a rolling 24h budget tracked separately per leg (deposit wUSDT payouts vs withdrawal USDT payouts), NOT a per-tx ceiling - many sub-50K swaps can clear same-day. circuit_breaker_fraction/circuit_breaker_window_minutes halt all auto-pay if the daily budget is consumed abnormally fast (>=50% within 30 min) until a human runs `reset-circuit-breaker`. Anything over max_single_tx, or that would exceed the remaining daily budget, or while the breaker is tripped, ALWAYS falls back to full manual 3-of-5 review via pwap-web - this never bypasses the multisig, it only decides whether a given event needs it. Requires AUTOMATION_KEY_MNEMONIC env var to be set (see res/bridge_automation_key.json) - if unset, behavior is 100% manual, unchanged from before this feature.",
|
||||
"requires_on_chain_action": "The automation key's actual Assets.approve_transfer allowance is renewed by PezbridgeBot's 3-of-5-signed renewal flow (pezbridge_bot_config.json's renewal_threshold/topup_amount) - those were bumped alongside this to top up to a size that supports the new daily cap. The NEXT renewal signers approve via pwap-web will lift the real on-chain ceiling; until then, auto-pay is bounded by whatever allowance already exists on-chain today, which is smaller. This is a fail-safe direction: if the on-chain allowance runs out, the system simply falls back to manual, never fails open."
|
||||
},
|
||||
"_custody_migration_2026-07-13": {
|
||||
"note": "Custody is no longer a single hot key. wUSDT (asset 1000) owner/issuer/admin/freezer on Pezkuwi Asset Hub is now the 3-of-5 multisig below - seed_path/BRIDGE_SEED_MNEMONIC in this file is stale and must not be used to mint/burn/transfer_ownership going forward. listen_deposits/listen_withdrawals in src/main.rs were updated the same day: they now only detect events and record status=pending_multisig_approval - actual mint/burn/release requires 3 of the 5 signatories to approve via pwap-web's multisig UI (shared/lib/multisig.ts, shared/lib/usdt.ts).",
|
||||
"multisig_threshold": 3,
|
||||
"multisig_signatories": 5,
|
||||
"multisig_account_pezkuwi_prefix42": "5GvwxmCDp3PC33KHoeWSgj3S7ocE7nzk1jiCCZMPSDBFeNcj",
|
||||
"multisig_account_polkadot_prefix0": "15sF76THfpefUaKomHZSpssayRbsp6Yt6ESgMrLjzJCmpe66",
|
||||
"pezkuwi_side_status": "live - owns wUSDT asset 1000, seeded with 1,000,000 wUSDT (tx 0xd5dc550c5cf04f323e5c1d9c13f2056acafc9f56404c657b9743c15ff3a3aacb)",
|
||||
"polkadot_side_status": "address computed, zero balance - no real USDT has ever been deposited by this ecosystem on Polkadot Asset Hub; needs at least existential DOT + real USDT deposits to become useful",
|
||||
"details_doc": "/home/myhez/res/validators-tiki.md"
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
[Unit]
|
||||
Description=PezbridgeBot - USDT bridge automation-key allowance renewal notifier (holds no key)
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=pezbridgebot
|
||||
Group=pezbridgebot
|
||||
WorkingDirectory=/opt/pezbridgebot/data
|
||||
ExecStart=/opt/pezbridgebot/bin/pezbridge-bot
|
||||
Environment=PEZBRIDGE_CONFIG=/opt/pezbridgebot/bin/pezbridge_bot_config.json
|
||||
Environment=RUST_LOG=info
|
||||
EnvironmentFile=/etc/pezbridgebot/telegram_token.env
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
# --- Hardening ---
|
||||
# Deployed 2026-07-13 on NEW-10 (89.116.25.180), simplified 2026-07-14: this process used to
|
||||
# also hold Noter's (Validator_04's) mnemonic via LoadCredential so it could automate 1-of-3
|
||||
# required signatures. That stopped being worth the risk once pwap-web shipped a real signing
|
||||
# UI (any of the 5 signers can now approve directly with their own wallet extension at
|
||||
# /multisig/pending) - the bot-held key only ever saved "2 humans click instead of 3", not
|
||||
# enough to justify a private key living on a server. Noter's mnemonic was removed from this
|
||||
# host entirely; this unit now only reads chain state and sends Telegram messages - it has no
|
||||
# LoadCredential, no signing capability, and nothing worth exfiltrating. The hardening below is
|
||||
# kept anyway as good baseline practice, not because there's a key to protect anymore.
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=strict
|
||||
ProtectHome=yes
|
||||
PrivateTmp=yes
|
||||
PrivateDevices=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelLogs=yes
|
||||
ProtectControlGroups=yes
|
||||
ProtectClock=yes
|
||||
ProtectHostname=yes
|
||||
RestrictSUIDSGID=yes
|
||||
RemoveIPC=yes
|
||||
LockPersonality=yes
|
||||
RestrictRealtime=yes
|
||||
RestrictNamespaces=yes
|
||||
MemoryDenyWriteExecute=yes
|
||||
SystemCallFilter=@system-service
|
||||
SystemCallArchitectures=native
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
ReadWritePaths=/opt/pezbridgebot/data
|
||||
UMask=0077
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,49 @@
|
||||
# PezbridgeBot — example systemd unit.
|
||||
# Read-only allowance-renewal notifier: reads chain state and sends Telegram alerts when the
|
||||
# automation-key allowance needs a 3-of-5-signed renewal. Holds NO signing key and cannot submit
|
||||
# anything. Copy to /etc/systemd/system/, fill in <PLACEHOLDERS>, provide the Telegram token
|
||||
# ONLY via the EnvironmentFile below (never in the repo).
|
||||
[Unit]
|
||||
Description=PezbridgeBot - allowance renewal notifier (holds no key)
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=<service-user>
|
||||
Group=<service-group>
|
||||
WorkingDirectory=<WORKDIR>
|
||||
ExecStart=<BIN_DIR>/pezbridge-bot
|
||||
Environment=PEZBRIDGE_CONFIG=<CONFIG_PATH>/pezbridge_bot_config.json
|
||||
Environment=RUST_LOG=info
|
||||
EnvironmentFile=<SECRETS_DIR>/telegram_token.env
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
# Hardening (recommended baseline)
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=strict
|
||||
ProtectHome=yes
|
||||
PrivateTmp=yes
|
||||
PrivateDevices=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelLogs=yes
|
||||
ProtectControlGroups=yes
|
||||
ProtectClock=yes
|
||||
ProtectHostname=yes
|
||||
RestrictSUIDSGID=yes
|
||||
RemoveIPC=yes
|
||||
LockPersonality=yes
|
||||
RestrictRealtime=yes
|
||||
RestrictNamespaces=yes
|
||||
MemoryDenyWriteExecute=yes
|
||||
SystemCallFilter=@system-service
|
||||
SystemCallArchitectures=native
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
ReadWritePaths=<WORKDIR>
|
||||
UMask=0077
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,60 +0,0 @@
|
||||
[Unit]
|
||||
Description=usdt-bridge listen-all - USDT/wUSDT listener; auto-pays sub-cap swaps via the bounded automation-key allowance, everything else queues for 3-of-5
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=usdtbridge
|
||||
Group=usdtbridge
|
||||
WorkingDirectory=/opt/usdtbridge/data
|
||||
ExecStart=/opt/usdtbridge/bin/usdt-bridge --config /opt/usdtbridge/bin/bridge_config.json listen-all
|
||||
Environment=RUST_LOG=info
|
||||
EnvironmentFile=/etc/pezbridgebot/telegram_token.env
|
||||
EnvironmentFile=-/etc/usdtbridge/automation_key.env
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
# --- Hardening ---
|
||||
# Deployed 2026-07-14 on NEW-10 (89.116.25.180), same UTIL bucket as pezbridge-bot (no
|
||||
# consensus/fund-critical services here - see dks-ci-runners/vps2-dev-decommission-status
|
||||
# memory for the placement convention). UPDATED 2026-07-14: this process now also loads the
|
||||
# automation key's mnemonic (from a separate, tighter-scoped EnvironmentFile than the Telegram
|
||||
# token) and can sign+submit Assets.transfer_approved on both chains - but ONLY within the
|
||||
# multisig's pre-approved delegated allowance, capped per-tx (max_single_tx) and per rolling 24h
|
||||
# window (auto_pay_daily_cap) with a circuit breaker on burst consumption. It can never mint,
|
||||
# burn, set_team, or transfer_ownership - those stay exclusively multisig (3-of-5), same as
|
||||
# before. Worst case of this key being compromised is bounded by whatever allowance + daily cap
|
||||
# remain at the time, not unbounded custody - a materially different (and much smaller) risk
|
||||
# tier than the legacy single-key bot this whole migration replaced. Hardening kept as-is; the
|
||||
# automation_key.env file itself is root:usdtbridge 0640, separate from the Telegram token file
|
||||
# so a Telegram-token leak alone can never expose the signing key. The leading "-" on that
|
||||
# EnvironmentFile line is required (not decorative): the file does not exist until an operator
|
||||
# deliberately provisions it, and the unit must still start cleanly without it, matching the
|
||||
# code's own AUTOMATION_KEY_MNEMONIC-unset fallback (100% manual, auto-pay simply inactive).
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=strict
|
||||
ProtectHome=yes
|
||||
PrivateTmp=yes
|
||||
PrivateDevices=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelLogs=yes
|
||||
ProtectControlGroups=yes
|
||||
ProtectClock=yes
|
||||
ProtectHostname=yes
|
||||
RestrictSUIDSGID=yes
|
||||
RemoveIPC=yes
|
||||
LockPersonality=yes
|
||||
RestrictRealtime=yes
|
||||
RestrictNamespaces=yes
|
||||
MemoryDenyWriteExecute=yes
|
||||
SystemCallFilter=@system-service
|
||||
SystemCallArchitectures=native
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
ReadWritePaths=/opt/usdtbridge/data
|
||||
UMask=0077
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,50 @@
|
||||
# usdt-bridge listener — example systemd unit.
|
||||
# Detects USDT/wUSDT deposit/withdrawal events; auto-pays only sub-cap swaps via a bounded,
|
||||
# multisig-delegated automation-key allowance, and queues everything else for 3-of-5 approval.
|
||||
# It can never mint/burn/set_team/transfer_ownership — those stay exclusively with the multisig.
|
||||
# Copy to /etc/systemd/system/, fill in <PLACEHOLDERS>, and provide secrets ONLY via the
|
||||
# EnvironmentFile(s) below (never in the repo): BRIDGE_SEED_MNEMONIC / AUTOMATION_KEY_MNEMONIC.
|
||||
[Unit]
|
||||
Description=usdt-bridge listener
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=<service-user>
|
||||
Group=<service-group>
|
||||
WorkingDirectory=<WORKDIR>
|
||||
ExecStart=<BIN_DIR>/usdt-bridge --config <CONFIG_PATH>/bridge_config.json listen-all
|
||||
Environment=RUST_LOG=info
|
||||
EnvironmentFile=<SECRETS_DIR>/telegram_token.env
|
||||
EnvironmentFile=-<SECRETS_DIR>/automation_key.env
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
# Hardening (recommended baseline)
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=strict
|
||||
ProtectHome=yes
|
||||
PrivateTmp=yes
|
||||
PrivateDevices=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectKernelLogs=yes
|
||||
ProtectControlGroups=yes
|
||||
ProtectClock=yes
|
||||
ProtectHostname=yes
|
||||
RestrictSUIDSGID=yes
|
||||
RemoveIPC=yes
|
||||
LockPersonality=yes
|
||||
RestrictRealtime=yes
|
||||
RestrictNamespaces=yes
|
||||
MemoryDenyWriteExecute=yes
|
||||
SystemCallFilter=@system-service
|
||||
SystemCallArchitectures=native
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
ReadWritePaths=<WORKDIR>
|
||||
UMask=0077
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -17,11 +17,11 @@ fn main() -> Result<()> {
|
||||
"scheme": "sr25519",
|
||||
"mnemonic": phrase,
|
||||
});
|
||||
std::fs::write("/home/myhez/res/bridge_automation_key.json", serde_json::to_string_pretty(&out)?)?;
|
||||
std::fs::write("bridge_automation_key.json", serde_json::to_string_pretty(&out)?)?;
|
||||
|
||||
println!("Generated automation key.");
|
||||
println!("Address (never the mnemonic): {}", ss58);
|
||||
println!("Saved to /home/myhez/res/bridge_automation_key.json");
|
||||
println!("Saved to bridge_automation_key.json");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -105,7 +105,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== GRANT XEZINEDAR + BERDEVK TIKI ===\n");
|
||||
|
||||
let relay_url =
|
||||
std::env::var("RPC_URL").unwrap_or_else(|_| "ws://217.77.6.126:9944".to_string());
|
||||
std::env::var("RPC_URL").unwrap_or_else(|_| "ws://127.0.0.1:9944".to_string());
|
||||
|
||||
let validator_01: AccountId32 = "5GipBJs2uNWTCazyZQ2vG3DEqLz4tXNmNZtBAT1Mtm1orZ5i".parse()?;
|
||||
let validator_02: AccountId32 = "5HWFZbhkZuTUySXu6ZXYKrTHBnWXHvWRKLozE22zhnwXGGxk".parse()?;
|
||||
@@ -121,7 +121,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&relay_url).await?;
|
||||
println!("Connected to {}! specVersion: {}\n", relay_url, api.runtime_version().spec_version);
|
||||
|
||||
let seed_content = std::fs::read_to_string("/home/myhez/res/sudo.json")?;
|
||||
let seed_content = std::fs::read_to_string("sudo.json")?;
|
||||
let seed_json: serde_json::Value = serde_json::from_str(&seed_content)?;
|
||||
let mnemonic_str = seed_json["mnemonic"].as_str().expect("mnemonic field present");
|
||||
let mnemonic = Mnemonic::from_str(mnemonic_str)?;
|
||||
|
||||
@@ -35,7 +35,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let api = OnlineClient::<PezkuwiConfig>::from_insecure_url(&rpc_url).await?;
|
||||
println!("Connected to {}! specVersion: {}\n", rpc_url, api.runtime_version().spec_version);
|
||||
|
||||
let seed_content = std::fs::read_to_string("/home/myhez/res/treasury.json")?;
|
||||
let seed_content = std::fs::read_to_string("treasury.json")?;
|
||||
let seed_json: serde_json::Value = serde_json::from_str(&seed_content)?;
|
||||
let mnemonic_str = seed_json["mnemonic"].as_str().expect("mnemonic field present");
|
||||
let mnemonic = Mnemonic::from_str(mnemonic_str)?;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"pezkuwi_rpc": "wss://<pezkuwi-asset-hub-rpc-endpoint>",
|
||||
"serok_chat_id": "<TELEGRAM_ADMIN_CHAT_ID>",
|
||||
"ops_chat_id": "<TELEGRAM_OPS_CHAT_ID>",
|
||||
"poll_interval_secs": 600,
|
||||
"renewal_threshold": 0,
|
||||
"topup_amount": 0,
|
||||
"state_path": "<PATH_TO_BOT_STATE_JSON>"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"pezkuwi_rpc": "wss://asset-hub-rpc.pezkuwichain.io",
|
||||
"serok_chat_id": 5362991649,
|
||||
"ops_chat_id": -5420200114,
|
||||
"poll_interval_secs": 600,
|
||||
"renewal_threshold": 40000000000,
|
||||
"topup_amount": 200000000000,
|
||||
"state_path": "/opt/pezbridgebot/data/pezbridge_bot_state.json"
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//! PezbridgeBot - notifies signers when the USDT bridge automation key's `Assets.approve_transfer`
|
||||
//! spending allowance needs renewal (see /home/myhez/res/validators-tiki.md and the
|
||||
//! spending allowance needs renewal (see the operator's custody notes and the
|
||||
//! usdt-bridge-multisig-migration memory for the full custody model).
|
||||
//!
|
||||
//! This process holds NO private key and cannot sign or submit anything. An earlier version of
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//! Backing:
|
||||
//! - 1:1 backed by real USDT on Polkadot Asset Hub
|
||||
//!
|
||||
//! Architecture (updated 2026-07-13 - see /home/myhez/res/validators-tiki.md for the full
|
||||
//! Architecture (updated 2026-07-13 - see the operator's custody notes for the full
|
||||
//! migration record):
|
||||
//! - Custody is a 3-of-5 multisig, NOT a single keypair. On Pezkuwi Asset Hub the multisig
|
||||
//! (5GvwxmCDp3PC33KHoeWSgj3S7ocE7nzk1jiCCZMPSDBFeNcj) now owns wUSDT (asset 1000) - it holds
|
||||
@@ -19,7 +19,7 @@
|
||||
//! submit mint/transfer calls automatically - no key this process holds has authority over
|
||||
//! the multisig account. They now only DETECT on-chain events and record them as
|
||||
//! pending_multisig_approval; an actual release requires 3 of the 5 signatories (Serok,
|
||||
//! SerokiMeclise, Xezinedar, Berdevk, Noter - see res/validators-tiki.md) to approve via
|
||||
//! SerokiMeclise, Xezinedar, Berdevk, Noter - see the operator's custody notes) to approve via
|
||||
//! `Multisig.approveAsMulti`/`asMulti`, which is expected to happen through pwap-web's
|
||||
//! existing multisig UI (shared/lib/multisig.ts, shared/lib/usdt.ts, MultisigMembers.tsx),
|
||||
//! not this relayer.
|
||||
@@ -67,7 +67,7 @@ const AUTOMATION_KEY_ADDRESS: &str = "5GQu4PFUb1f3MTJ7i7c1CtLgDk3TVvpSW1VbQCRmfk
|
||||
/// stream, the process just stops seeing new blocks forever - while staying up and logging
|
||||
/// nothing further ("Listening for deposits..." was the last line for 3+ hours while a real 1
|
||||
/// USDT deposit sat undetected at block #18250967, ~62 minutes into that silence - see
|
||||
/// res/validators-tiki.md 2026-07-15). Checkpoint + backfill only covers a gap across a
|
||||
/// the operator's custody notes 2026-07-15). Checkpoint + backfill only covers a gap across a
|
||||
/// *restart*; this covers a stall with no restart at all. If no new finalized block arrives
|
||||
/// within this window (Asset Hub blocks land every ~6-12s under normal conditions, so this is a
|
||||
/// wide margin, not a tight one), treat the subscription as stalled and force a full reconnect -
|
||||
@@ -1317,7 +1317,7 @@ async fn listen_deposits(config: &BridgeConfig, automation: &AutomationContext)
|
||||
// Checkpoint + backfill: a live block subscription alone is not a correctness guarantee - a
|
||||
// transient reconnect or subscription hiccup can silently skip blocks with zero logging (this
|
||||
// is exactly how a real user deposit went undetected in production - see
|
||||
// res/validators-tiki.md 2026-07-15). On every (re)start, explicitly scan any gap between
|
||||
// the operator's custody notes 2026-07-15). On every (re)start, explicitly scan any gap between
|
||||
// the last persisted checkpoint and the current chain head before relying on the live stream.
|
||||
let last_processed = { BridgeDatabase::load(&config.db_path)?.stats.last_polkadot_block };
|
||||
let head_hash = legacy_rpc.chain_get_finalized_head().await?;
|
||||
|
||||
Reference in new issue
Block a user