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 CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ find contracts/ unittests/test-contracts/ -name "*.actions.cpp" -o -name "*.disp
After building contracts, you MUST copy the compiled `.wasm` and `.abi` files from the build directory back to the source tree. This is required before generating system contract types and before testing.

```bash
for c in epoch opreg msgch uwrit chalg authex; do
for c in epoch opreg msgch chalg authex synd bond; do
cp "$BUILD_DIR/contracts/sysio.$c/sysio.$c.wasm" "contracts/sysio.$c/" 2>/dev/null
cp "$BUILD_DIR/contracts/sysio.$c/sysio.$c.abi" "contracts/sysio.$c/" 2>/dev/null
done
Expand Down
124 changes: 70 additions & 54 deletions OVERVIEW.md

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions PLUGINS.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,14 @@ documents what it does, how it works, and how to configure it. The plugin lifecy
| `query_engine_plugin` | Opt-in SQL queries over the node's current chain state, answered by an in-process C++ service and, when HTTP is enabled, `POST /v1/query/execute`; runs only on a non-producing node in head or irreversible read mode | [README](plugins/query_engine_plugin/README.md) |
| `resource_monitor_plugin` | Watches free space on every file system nodeop writes to and gracefully shuts the node down before it runs out | [README](plugins/resource_monitor_plugin/README.md) |
| `signature_provider_kms_plugin` | Adds the `KMS:` signature-provider scheme, signing Ethereum keys remotely through AWS KMS so the key never leaves AWS | [README](plugins/signature_provider_kms_plugin/README.md) |
| `signature_provider_manager_plugin` | Owns every signing key the node uses, parsing each `--signature-provider` spec and publishing the providers to the chain, producer, net, outpost, and underwriter plugins | [README](plugins/signature_provider_manager_plugin/README.md) |
| `signature_provider_manager_plugin` | Owns every signing key the node uses, parsing each `--signature-provider` spec and publishing the providers to the chain, producer, net, and outpost plugins | [README](plugins/signature_provider_manager_plugin/README.md) |
| `signature_provider_ssm_plugin` | Adds the `SSM:` signature-provider scheme, fetching a private key once from an AWS SSM Parameter Store SecureString and signing locally thereafter | [README](plugins/signature_provider_ssm_plugin/README.md) |
| `snapshot_api_plugin` | Public, read-only HTTP endpoints for snapshot discovery and download, so nodes can bootstrap from each other | [README](plugins/snapshot_api_plugin/README.md) |
| `state_history_plugin` | Records per-block traces, chain-state deltas, and finality data to append-only logs and streams them to clients over a binary websocket protocol | [README](plugins/state_history_plugin/README.md) |
| `status_monitor_plugin` | Ships one `/v1/chain/get_info` snapshot per irreversible block to an OpenSearch/Elasticsearch `_bulk` endpoint, rendered through an operator JSON template | [README](plugins/status_monitor_plugin/README.md) |
| `test_control_api_plugin` | HTTP surface for `test_control_plugin`, registering the `/v1/test_control/*` write endpoints in their own `test_control` API category | [README](plugins/test_control_api_plugin/README.md) |
| `test_control_plugin` | Test-only plugin that arms deliberate node misbehavior: shut down inside a named producer's round, throw from a controller signal handler, or republish the next block with one action swapped | [README](plugins/test_control_plugin/README.md) |
| `trace_api_plugin` | Full-history action trace store with HTTP endpoints for querying traces, transactions, actions, and token transfers | [trace_api_plugin.md](plugins/trace_api_plugin/trace_api_plugin.md) |
| `underwriter_plugin` | Autonomous underwriter daemon that polls pending swaps and submits signed underwrite-intent commits for the outpost legs that still lack one | [README](plugins/underwriter_plugin/README.md) |
| `wallet_api_plugin` | Publishes the `kiod` key store as the `/v1/wallet/*` HTTP endpoints that `clio` and a `KIOD:` signature provider call. Linked and initialized by `kiod`, not `nodeop` | [README](plugins/wallet_api_plugin/README.md) |
| `wallet_plugin` | The `kiod` key store: a locked directory of AES-encrypted wallet files with inactivity auto-lock and transaction and digest signing. Linked and initialized by `kiod`, not `nodeop` | [README](plugins/wallet_plugin/README.md) |

Expand Down
1 change: 0 additions & 1 deletion cmake/chain-tools.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ macro(chain_target TARGET)
PRIVATE
batch_operator_plugin
external_debugging_plugin
underwriter_plugin
chain_api_plugin
db_size_api_plugin
net_api_plugin
Expand Down
5 changes: 3 additions & 2 deletions contracts/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,15 @@ add_subdirectory(sysio.tokens)
add_subdirectory(sysio.epoch)
add_subdirectory(sysio.opreg)
add_subdirectory(sysio.msgch)
add_subdirectory(sysio.uwrit)
add_subdirectory(sysio.chalg)
add_subdirectory(sysio.councl)
add_subdirectory(sysio.reserv)
add_subdirectory(sysio.dclaim)

add_subdirectory(sysio.andon)
add_subdirectory(sysio.token)
add_subdirectory(sysio.wrap)
add_subdirectory(sysio.swap)
add_subdirectory(sysio.liq)
add_subdirectory(sysio.bond)
add_subdirectory(sysio.synd)
add_subdirectory(test_contracts)
6 changes: 6 additions & 0 deletions contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ The collection of system contracts consists of the following individual contract
* [multisig contract](contracts/sysio.msig/include/sysio.msig/sysio.msig.hpp): A contract that enables proposing transactions on the blockchain, collecting authorization approvals for many accounts, and then executing the actions within the transaction after authorization requirements of the transaction have been reached. (Note: this contract must be deployed to a privileged account.)
* [wrap contract](contracts/sysio.wrap/include/sysio.wrap/sysio.wrap.hpp): A contract that wraps around any transaction and allows for executing its actions without needing to satisfy the authorization requirements of the transaction. If used, the permissions of the account hosting this contract should be configured to only allow highly trusted parties (e.g. the operators of the blockchain) to have the ability to execute its actions. (Note: this contract must be deployed to a privileged account.)

## Depot flow tests

See [Depot flow coverage](tests/DEPOT_FLOW_TESTING.md) for the native mirrors of
all enabled cluster flows, the generic external-chain simulator, deterministic
action sequences, and focused/full validation commands.

## Branches

The `master` branch contains the latest stable branch
Expand Down
34 changes: 34 additions & 0 deletions contracts/sysio.andon/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
set(contract_name sysio.andon)
bootstrap_contract(${contract_name})

if(BUILD_SYSTEM_CONTRACTS)
file(GLOB_RECURSE SOURCES src/*.cpp)
file(GLOB_RECURSE HEADERS include/*.hpp)
add_contract(${contract_name} ${contract_name} ${SOURCES})
set(targets ${contract_name})

if("native-module" IN_LIST SYSIO_WASM_RUNTIMES)
list(APPEND targets ${contract_name}_native)
add_native_contract(
TARGET ${contract_name}_native
SOURCES ${SOURCES}
INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include
CONTRACT_CLASS "sysio::andon"
HEADERS ${HEADERS}
ABI_FILE ${CMAKE_BINARY_DIR}/contracts/${contract_name}/${contract_name}.abi
)
endif()

foreach(target ${targets})
if(NOT TARGET ${target})
message(WARNING "Target ${target} not found, skipping include directory setup")
continue()
endif()

target_include_directories(${target}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)

endforeach()
endif()
56 changes: 56 additions & 0 deletions contracts/sysio.andon/include/sysio.andon/sysio.andon.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#pragma once
/**
* @file sysio.andon.hpp
* @brief Depot emergency stop, authorized through native account permissions.
*
* Bootstrap links pull and clear to sysio.andon permissions whose authorities
* delegate to governance and the panic account. Readers gate custody exits;
* intake and OPP consensus continue. Privileged sysio.synd pulls automatically
* on a custody shortfall with sysio.andon@active authorization.
*/
#include <sysio/sysio.hpp>
#include <sysio/kv_global.hpp>
#include <sysio/time.hpp>
#include <algorithm>
#include <array>
#include <string>

namespace sysio {
class [[sysio::contract("sysio.andon")]] andon : public contract {
public:
using contract::contract;
/// Deployment account shared by every freeze reader.
static constexpr name ANDON_ACCOUNT = "sysio.andon"_n;
/// Governance pays for this privileged contract's singleton.
static constexpr name SYSTEM_ACCOUNT = "sysio"_n;
/// Custody destinations remain available for deposits during a freeze.
static constexpr std::array<name, 3> CUSTODY_ACCOUNTS{"sysio.bond"_n, "sysio.synd"_n, "sysio.opreg"_n};
/// Maximum stored reason/note length in bytes.
static constexpr uint32_t MAX_TEXT_BYTES = 256;
/// Whether an account may receive a custody deposit while frozen.
static constexpr bool is_custody(name account) {
return std::find(CUSTODY_ACCOUNTS.begin(), CUSTODY_ACCOUNTS.end(), account) != CUSTODY_ACCOUNTS.end();
}
/// Pull the cord; repeated pulls preserve the first reason and timestamp. Auth=get_self().
[[sysio::action]] void pull(std::string reason);
/// Clear the cord; repeated clears are no-ops. Auth=get_self().
[[sysio::action]] void clear(std::string note);
/// Shared layout: redeploy Andon and its readers together on a fresh deployment.
struct [[sysio::table("cord")]] cord_state {
bool pulled = false; ///< Whether custody exits are stopped.
time_point when{}; ///< Time of the last state transition.
std::string reason; ///< Reason or recovery note of that transition.
SYSLIB_SERIALIZE(cord_state, (pulled)(when)(reason))
};
/// Depot emergency-stop singleton.
using cord_t = kv::global<"cord"_n, cord_state>;
/// An absent row reads as clear.
static cord_state cord_of(name account) { return cord_t(account).get_or_default(cord_state{}); }
/// The common freeze check used by custody readers.
static bool pulled(name account) { return cord_of(account).pulled; }
/// Refusal returned by signed actions that would move funds out of custody.
static constexpr const char* FROZEN_MESSAGE = "the andon cord is pulled: funds cannot leave custody";
/// Refuse a custody exit while the cord is pulled.
static void check_clear(name account) { check(!pulled(account), FROZEN_MESSAGE); }
};
} // namespace sysio
27 changes: 27 additions & 0 deletions contracts/sysio.andon/src/sysio.andon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <sysio.andon/sysio.andon.hpp>
#include <sysio/print.hpp>
#include <sysio/system.hpp>

namespace sysio {
void andon::pull(std::string reason) {
require_auth(get_self());
cord_t cord(get_self());
if (cord.get_or_default(cord_state{}).pulled) {
print("sysio.andon::pull: the cord is already pulled; nothing changes\n");
return;
}
reason.resize(std::min(reason.size(), size_t{MAX_TEXT_BYTES}));
cord.set(cord_state{true, current_time_point(), std::move(reason)}, SYSTEM_ACCOUNT);
}

void andon::clear(std::string note) {
require_auth(get_self());
cord_t cord(get_self());
if (!cord.get_or_default(cord_state{}).pulled) {
print("sysio.andon::clear: the cord is not pulled; nothing changes\n");
return;
}
note.resize(std::min(note.size(), size_t{MAX_TEXT_BYTES}));
cord.set(cord_state{false, current_time_point(), std::move(note)}, SYSTEM_ACCOUNT);
}
} // namespace sysio
70 changes: 70 additions & 0 deletions contracts/sysio.andon/sysio.andon.abi
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"____comment": "This file was generated with sysio-abigen. DO NOT EDIT ",
"version": "sysio::abi/1.2",
"types": [],
"structs": [
{
"name": "clear",
"base": "",
"fields": [
{
"name": "note",
"type": "string"
}
]
},
{
"name": "cord_state",
"base": "",
"fields": [
{
"name": "pulled",
"type": "bool"
},
{
"name": "when",
"type": "time_point"
},
{
"name": "reason",
"type": "string"
}
]
},
{
"name": "pull",
"base": "",
"fields": [
{
"name": "reason",
"type": "string"
}
]
}
],
"actions": [
{
"name": "clear",
"type": "clear",
"ricardian_contract": ""
},
{
"name": "pull",
"type": "pull",
"ricardian_contract": ""
}
],
"tables": [
{
"name": "cord",
"type": "cord_state",
"index_type": "i64",
"key_names": ["name"],
"key_types": ["name"],
"table_id": 28648
}
],
"ricardian_clauses": [],
"variants": [],
"action_results": []
}
Binary file added contracts/sysio.andon/sysio.andon.wasm
Binary file not shown.
18 changes: 9 additions & 9 deletions contracts/sysio.authex/src/sysio.authex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ using namespace sysio;
// sysio funds the RAM for every link row (system-paid) -- createlink and recordlink alike.
constexpr name link_row_payer = "sysio"_n;
constexpr name dclaim_account = "sysio.dclaim"_n;
constexpr name liq_account = "sysio.liq"_n;
constexpr name synd_account = "sysio.synd"_n;
constexpr name linkswept_action = "linkswept"_n;
constexpr auto dclaim_not_ready_message =
"sysio.dclaim must be deployed and privileged before creating a link";
Expand Down Expand Up @@ -67,24 +67,24 @@ void try_send_linked_rewards_sweep(const name self, const name account,
if (dclaim_ready()) send_linked_rewards_sweep(self, account, chain_kind, native_address);
}

/** Return whether the shadow-liq ledger can receive a system-paid link sweep. */
[[nodiscard]] bool liq_ready() {
return is_account(liq_account) && is_privileged(liq_account);
/** Return whether the syndication contract can receive a system-paid link sweep. */
[[nodiscard]] bool synd_ready() {
return is_account(synd_account) && is_privileged(synd_account);
}

/**
* Best-effort sweep of the shadow liq parked against a user-created link's key.
*
* sysio.liq parks by the key bytes an outpost reports (the 33-byte EM key or the 32-byte ED
* sysio.synd parks by the key bytes an outpost reports (the 33-byte EM key or the 32-byte ED
* key), so it receives the verified key, not the derived address the DClaim sweep takes. The
* sweep is optional by design: nothing is parked before sysio.liq exists, and a link created
* while it was absent is served by the permissionless `sysio.liq::sweep`.
* sweep is optional by design: nothing is parked before sysio.synd exists, and a link created
* while it was absent is served by the permissionless `sysio.synd::sweep`.
*/
void try_send_parked_liq_sweep(const name self, const name account,
const opp::types::ChainKind chain_kind,
const std::vector<char>& pubkey) {
if (!liq_ready()) return;
action(permission_level{self, "active"_n}, liq_account, linkswept_action,
if (!synd_ready()) return;
action(permission_level{self, "active"_n}, synd_account, linkswept_action,
std::make_tuple(account, chain_kind, pubkey)).send();
}

Expand Down
Binary file modified contracts/sysio.authex/sysio.authex.wasm
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
set(contract_name sysio.reserv)
set(contract_name sysio.bond)
bootstrap_contract(${contract_name})

if(BUILD_SYSTEM_CONTRACTS)
Expand All @@ -14,7 +14,7 @@ if(BUILD_SYSTEM_CONTRACTS)
TARGET ${contract_name}_native
SOURCES ${SOURCES}
INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include
CONTRACT_CLASS "sysio::reserve"
CONTRACT_CLASS "sysio::bond"
HEADERS ${HEADERS}
ABI_FILE ${CMAKE_BINARY_DIR}/contracts/${contract_name}/${contract_name}.abi
)
Expand All @@ -31,12 +31,12 @@ if(BUILD_SYSTEM_CONTRACTS)
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/../../libraries/opp/generated-cdt>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../libraries/libfc-lite/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../sysio.epoch/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../sysio.msgch/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../sysio.authex/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../sysio.andon/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../sysio.chains/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../sysio.liq/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../sysio.token/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../sysio.tokens/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../sysio.opp.common/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../sysio.uwrit/include>
)

target_link_libraries(${target}
Expand Down
Loading
Loading