mirror of
https://github.com/logos-blockchain/logos-blockchain-module.git
synced 2026-07-13 18:49:31 +00:00
feat(commands): Expose commands to module (#33)
* Expose commands to module * Add missing tests stubs
This commit is contained in:
parent
f3558372fd
commit
bcd885c09f
15
flake.lock
generated
15
flake.lock
generated
@ -24,16 +24,16 @@
|
|||||||
"rust-rapidsnark": "rust-rapidsnark"
|
"rust-rapidsnark": "rust-rapidsnark"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1781108021,
|
"lastModified": 1781288172,
|
||||||
"narHash": "sha256-YOJR3TMNHgQedoN7ftga+EP3VzWkCVMW59xYTAMF/pU=",
|
"narHash": "sha256-4anGBb7slL6WfMCGlI4BmLAjim7kQOMD/qv4FCPJwII=",
|
||||||
"owner": "logos-blockchain",
|
"owner": "logos-blockchain",
|
||||||
"repo": "logos-blockchain",
|
"repo": "logos-blockchain",
|
||||||
"rev": "feddb4616512bf7954b503d8de4287d2ed59c4ba",
|
"rev": "86e24cfd985b6341e96bba76ecad36ff379bd243",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "logos-blockchain",
|
"owner": "logos-blockchain",
|
||||||
"ref": "feddb4616512bf7954b503d8de4287d2ed59c4ba",
|
"ref": "86e24cfd985b6341e96bba76ecad36ff379bd243",
|
||||||
"repo": "logos-blockchain",
|
"repo": "logos-blockchain",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
@ -53,6 +53,7 @@
|
|||||||
"original": {
|
"original": {
|
||||||
"owner": "logos-blockchain",
|
"owner": "logos-blockchain",
|
||||||
"repo": "logos-blockchain-circuits",
|
"repo": "logos-blockchain-circuits",
|
||||||
|
"rev": "2846ee7a4cfa24458bb8063412ab2e753b344d2f",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -6313,11 +6314,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1780749050,
|
"lastModified": 1781074563,
|
||||||
"narHash": "sha256-3av0pIjlOWQ6rDbNOmpUSvbNnJkGORQKKjb4LtCZsIY=",
|
"narHash": "sha256-md8WlXOlfnIeHeOScMTTHFyf2d6iaTwPl2apR5EQ3P4=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "a799d3e3886da994fa307f817a6bc705ae538eeb",
|
"rev": "9ae611a455b90cf061d8f332b977e387bda8e1ca",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
logos-module-builder.url = "github:logos-co/logos-module-builder";
|
logos-module-builder.url = "github:logos-co/logos-module-builder";
|
||||||
logos-blockchain.url = "github:logos-blockchain/logos-blockchain?ref=feddb4616512bf7954b503d8de4287d2ed59c4ba"; # v0.1.3-rc.10-compatible + rust-rapidsnark nix fixes
|
# v0.1.3-rc.10-compatible + rust-rapidsnark nix fixes + cli commands
|
||||||
|
logos-blockchain.url = "github:logos-blockchain/logos-blockchain?ref=86e24cfd985b6341e96bba76ecad36ff379bd243";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = inputs@{ logos-module-builder, ... }:
|
outputs = inputs@{ logos-module-builder, ... }:
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
#include "logos_blockchain_module.h"
|
#include "logos_blockchain_module.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <boost/algorithm/hex.hpp>
|
#include <boost/algorithm/hex.hpp>
|
||||||
#include <boost/algorithm/string/trim.hpp>
|
#include <boost/algorithm/string/trim.hpp>
|
||||||
|
#include <cctype>
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
@ -52,6 +54,23 @@ namespace {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Map a "ed25519" / "zk" string (case-insensitive) to the C KeyType enum.
|
||||||
|
bool parse_key_type(const std::string& s, KeyType& out) {
|
||||||
|
std::string lower = s;
|
||||||
|
boost::algorithm::trim(lower);
|
||||||
|
std::transform(lower.begin(), lower.end(), lower.begin(),
|
||||||
|
[](unsigned char c) { return std::tolower(c); });
|
||||||
|
if (lower == "ed25519") {
|
||||||
|
out = KeyType::Ed25519;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (lower == "zk") {
|
||||||
|
out = KeyType::Zk;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Wrapper that owns data and provides GenerateConfigArgs
|
// Wrapper that owns data and provides GenerateConfigArgs
|
||||||
struct OwnedGenerateConfigArgs {
|
struct OwnedGenerateConfigArgs {
|
||||||
std::vector<std::string> initial_peers_data;
|
std::vector<std::string> initial_peers_data;
|
||||||
@ -323,6 +342,162 @@ int LogosBlockchainModule::stop() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Config management
|
||||||
|
|
||||||
|
int LogosBlockchainModule::update_user_config(const std::string& user_config_path, const std::string& keystore_path) {
|
||||||
|
const std::string config = localPathFromFileUrl(user_config_path);
|
||||||
|
const std::string keystore = localPathFromFileUrl(keystore_path);
|
||||||
|
|
||||||
|
const OperationStatus status = ::update_user_config(config.c_str(), keystore.c_str());
|
||||||
|
if (!is_ok(&status)) {
|
||||||
|
fprintf(stderr, "Failed to update user config. Error: %d\n", status);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LogosBlockchainModule::migrate_user_config(const std::string& output_path, const std::string& keystore_path) {
|
||||||
|
const std::string output = localPathFromFileUrl(output_path);
|
||||||
|
const std::string keystore = localPathFromFileUrl(keystore_path);
|
||||||
|
|
||||||
|
const OperationStatus status = ::migrate_user_config(output.c_str(), keystore.c_str());
|
||||||
|
if (!is_ok(&status)) {
|
||||||
|
fprintf(stderr, "Failed to migrate user config. Error: %d\n", status);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LogosBlockchainModule::migrate_user_config_0_1_2(
|
||||||
|
const std::string& new_config_path,
|
||||||
|
const std::string& old_config_path,
|
||||||
|
const std::string& keystore_path
|
||||||
|
) {
|
||||||
|
const std::string new_config = localPathFromFileUrl(new_config_path);
|
||||||
|
const std::string old_config = localPathFromFileUrl(old_config_path);
|
||||||
|
const std::string keystore = localPathFromFileUrl(keystore_path);
|
||||||
|
|
||||||
|
const OperationStatus status =
|
||||||
|
::migrate_user_config_0_1_2(new_config.c_str(), old_config.c_str(), keystore.c_str());
|
||||||
|
if (!is_ok(&status)) {
|
||||||
|
fprintf(stderr, "Failed to migrate 0.1.2 config. Error: %d\n", status);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LogosBlockchainModule::participate(
|
||||||
|
const std::string& config_path,
|
||||||
|
const std::string& keystore_path,
|
||||||
|
const std::string& output_dir,
|
||||||
|
const std::string& external_address
|
||||||
|
) {
|
||||||
|
const std::string config = localPathFromFileUrl(config_path);
|
||||||
|
const std::string keystore = localPathFromFileUrl(keystore_path);
|
||||||
|
const std::string output = localPathFromFileUrl(output_dir);
|
||||||
|
const char* external_address_ptr = external_address.empty() ? nullptr : external_address.c_str();
|
||||||
|
|
||||||
|
const OperationStatus status =
|
||||||
|
::participate(config.c_str(), keystore.c_str(), output.c_str(), external_address_ptr);
|
||||||
|
if (!is_ok(&status)) {
|
||||||
|
fprintf(stderr, "Failed to generate participation data. Error: %d\n", status);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keystore
|
||||||
|
|
||||||
|
std::string LogosBlockchainModule::generate_key(
|
||||||
|
const std::string& user_config_path,
|
||||||
|
const std::string& keystore_path,
|
||||||
|
const std::string& key_type,
|
||||||
|
const std::string& key_title
|
||||||
|
) {
|
||||||
|
KeyType type{};
|
||||||
|
if (!parse_key_type(key_type, type)) {
|
||||||
|
return "Error: Invalid key_type (expected \"ed25519\" or \"zk\").";
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string config = localPathFromFileUrl(user_config_path);
|
||||||
|
const std::string keystore = localPathFromFileUrl(keystore_path);
|
||||||
|
const char* key_title_ptr = key_title.empty() ? nullptr : key_title.c_str();
|
||||||
|
|
||||||
|
auto [value, error] = ::generate_key(config.c_str(), keystore.c_str(), type, key_title_ptr);
|
||||||
|
if (!is_ok(&error)) {
|
||||||
|
fprintf(stderr, "Failed to generate key. Error: %d\n", error);
|
||||||
|
return "Error: Failed to generate key: " + std::to_string(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string result(value);
|
||||||
|
const OperationStatus free_status = free_cstring(value);
|
||||||
|
if (!is_ok(&free_status)) {
|
||||||
|
fprintf(stderr, "Failed to free key id string. Error: %d\n", free_status);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LogosBlockchainModule::add_key(
|
||||||
|
const std::string& user_config_path,
|
||||||
|
const std::string& keystore_path,
|
||||||
|
const std::string& key_type,
|
||||||
|
const std::string& key_hex,
|
||||||
|
const std::string& key_title
|
||||||
|
) {
|
||||||
|
KeyType type{};
|
||||||
|
if (!parse_key_type(key_type, type)) {
|
||||||
|
fprintf(stderr, "Invalid key_type (expected \"ed25519\" or \"zk\").\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string config = localPathFromFileUrl(user_config_path);
|
||||||
|
const std::string keystore = localPathFromFileUrl(keystore_path);
|
||||||
|
const char* key_title_ptr = key_title.empty() ? nullptr : key_title.c_str();
|
||||||
|
|
||||||
|
const OperationStatus status =
|
||||||
|
::add_key(config.c_str(), keystore.c_str(), type, key_hex.c_str(), key_title_ptr);
|
||||||
|
if (!is_ok(&status)) {
|
||||||
|
fprintf(stderr, "Failed to add key. Error: %d\n", status);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LogosBlockchainModule::remove_key(
|
||||||
|
const std::string& user_config_path,
|
||||||
|
const std::string& keystore_path,
|
||||||
|
const std::string& key_title
|
||||||
|
) {
|
||||||
|
const std::string config = localPathFromFileUrl(user_config_path);
|
||||||
|
const std::string keystore = localPathFromFileUrl(keystore_path);
|
||||||
|
|
||||||
|
const OperationStatus status = ::remove_key(config.c_str(), keystore.c_str(), key_title.c_str());
|
||||||
|
if (!is_ok(&status)) {
|
||||||
|
fprintf(stderr, "Failed to remove key. Error: %d\n", status);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identity
|
||||||
|
|
||||||
|
std::string LogosBlockchainModule::get_peer_id(const std::string& config_path) {
|
||||||
|
const std::string config = localPathFromFileUrl(config_path);
|
||||||
|
|
||||||
|
auto [value, error] = ::get_peer_id(config.c_str());
|
||||||
|
if (!is_ok(&error)) {
|
||||||
|
fprintf(stderr, "Failed to get peer id. Error: %d\n", error);
|
||||||
|
return "Error: Failed to get peer id: " + std::to_string(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string result(value);
|
||||||
|
const OperationStatus free_status = free_cstring(value);
|
||||||
|
if (!is_ok(&free_status)) {
|
||||||
|
fprintf(stderr, "Failed to free peer id string. Error: %d\n", free_status);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Wallet
|
// Wallet
|
||||||
|
|
||||||
std::string LogosBlockchainModule::wallet_get_balance(const std::string& address_hex) {
|
std::string LogosBlockchainModule::wallet_get_balance(const std::string& address_hex) {
|
||||||
|
|||||||
@ -26,6 +26,45 @@ public:
|
|||||||
int start(const std::string& config_path, const std::string& deployment);
|
int start(const std::string& config_path, const std::string& deployment);
|
||||||
int stop();
|
int stop();
|
||||||
|
|
||||||
|
// Config management
|
||||||
|
int update_user_config(const std::string& user_config_path, const std::string& keystore_path);
|
||||||
|
int migrate_user_config(const std::string& output_path, const std::string& keystore_path);
|
||||||
|
int migrate_user_config_0_1_2(
|
||||||
|
const std::string& new_config_path,
|
||||||
|
const std::string& old_config_path,
|
||||||
|
const std::string& keystore_path
|
||||||
|
);
|
||||||
|
int participate(
|
||||||
|
const std::string& config_path,
|
||||||
|
const std::string& keystore_path,
|
||||||
|
const std::string& output_dir,
|
||||||
|
const std::string& external_address
|
||||||
|
);
|
||||||
|
|
||||||
|
// Keystore
|
||||||
|
// key_type is "ed25519" or "zk". key_title may be empty (auto-generated).
|
||||||
|
std::string generate_key(
|
||||||
|
const std::string& user_config_path,
|
||||||
|
const std::string& keystore_path,
|
||||||
|
const std::string& key_type,
|
||||||
|
const std::string& key_title
|
||||||
|
);
|
||||||
|
int add_key(
|
||||||
|
const std::string& user_config_path,
|
||||||
|
const std::string& keystore_path,
|
||||||
|
const std::string& key_type,
|
||||||
|
const std::string& key_hex,
|
||||||
|
const std::string& key_title
|
||||||
|
);
|
||||||
|
int remove_key(
|
||||||
|
const std::string& user_config_path,
|
||||||
|
const std::string& keystore_path,
|
||||||
|
const std::string& key_title
|
||||||
|
);
|
||||||
|
|
||||||
|
// Identity
|
||||||
|
std::string get_peer_id(const std::string& config_path);
|
||||||
|
|
||||||
// Wallet
|
// Wallet
|
||||||
std::string wallet_get_balance(const std::string& address_hex);
|
std::string wallet_get_balance(const std::string& address_hex);
|
||||||
std::string wallet_transfer_funds(
|
std::string wallet_transfer_funds(
|
||||||
|
|||||||
@ -12,6 +12,7 @@ logos_test(
|
|||||||
TEST_SOURCES
|
TEST_SOURCES
|
||||||
main.cpp
|
main.cpp
|
||||||
test_blockchain.cpp
|
test_blockchain.cpp
|
||||||
|
event_stubs.cpp
|
||||||
MOCK_C_SOURCES
|
MOCK_C_SOURCES
|
||||||
mocks/mock_logos_blockchain.cpp
|
mocks/mock_logos_blockchain.cpp
|
||||||
EXTRA_INCLUDES
|
EXTRA_INCLUDES
|
||||||
@ -35,6 +36,7 @@ if(LIBLOGOS_BLOCKCHAIN_PATH)
|
|||||||
TEST_SOURCES
|
TEST_SOURCES
|
||||||
main.cpp
|
main.cpp
|
||||||
test_blockchain.cpp
|
test_blockchain.cpp
|
||||||
|
event_stubs.cpp
|
||||||
EXTRA_INCLUDES
|
EXTRA_INCLUDES
|
||||||
../lib
|
../lib
|
||||||
EXTRA_LINK_LIBS
|
EXTRA_LINK_LIBS
|
||||||
|
|||||||
17
tests/event_stubs.cpp
Normal file
17
tests/event_stubs.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Test-only definitions for `logos_events:` methods.
|
||||||
|
//
|
||||||
|
// In a real build the cpp-generator emits the bodies of every `logos_events:`
|
||||||
|
// method into a sidecar `<name>_events.cpp` (each forwards through
|
||||||
|
// `emitEventImpl_`). The unit/integration test targets compile the module
|
||||||
|
// source directly without running codegen, so those bodies are absent and the
|
||||||
|
// link fails on `on_new_block_callback`'s reference to `newBlock`.
|
||||||
|
//
|
||||||
|
// `emitEventImpl_` is a no-op outside a framework-provisioned context (no emit
|
||||||
|
// callback is installed in tests), so forwarding here mirrors production
|
||||||
|
// behaviour while keeping the test build link-complete.
|
||||||
|
|
||||||
|
#include "logos_blockchain_module.h"
|
||||||
|
|
||||||
|
void LogosBlockchainModule::newBlock(const std::string& blockJson) {
|
||||||
|
emitEventImpl_("newBlock", nullptr);
|
||||||
|
}
|
||||||
@ -42,6 +42,78 @@ OperationStatus stop_node(LogosBlockchainNode* node) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OperationStatus update_user_config(const char* user_config_path, const char* keystore_path) {
|
||||||
|
LOGOS_CMOCK_RECORD("update_user_config");
|
||||||
|
return LOGOS_CMOCK_RETURN(int, "update_user_config");
|
||||||
|
}
|
||||||
|
|
||||||
|
OperationStatus migrate_user_config(const char* output_path, const char* keystore_path) {
|
||||||
|
LOGOS_CMOCK_RECORD("migrate_user_config");
|
||||||
|
return LOGOS_CMOCK_RETURN(int, "migrate_user_config");
|
||||||
|
}
|
||||||
|
|
||||||
|
OperationStatus migrate_user_config_0_1_2(
|
||||||
|
const char* new_config_path,
|
||||||
|
const char* old_config_path,
|
||||||
|
const char* keystore_path)
|
||||||
|
{
|
||||||
|
LOGOS_CMOCK_RECORD("migrate_user_config_0_1_2");
|
||||||
|
return LOGOS_CMOCK_RETURN(int, "migrate_user_config_0_1_2");
|
||||||
|
}
|
||||||
|
|
||||||
|
OperationStatus participate(
|
||||||
|
const char* config_path,
|
||||||
|
const char* keystore_path,
|
||||||
|
const char* output_dir,
|
||||||
|
const char* external_address)
|
||||||
|
{
|
||||||
|
LOGOS_CMOCK_RECORD("participate");
|
||||||
|
return LOGOS_CMOCK_RETURN(int, "participate");
|
||||||
|
}
|
||||||
|
|
||||||
|
StringResult generate_key(
|
||||||
|
const char* user_config_path,
|
||||||
|
const char* keystore_path,
|
||||||
|
KeyType key_type,
|
||||||
|
const char* key_title)
|
||||||
|
{
|
||||||
|
LOGOS_CMOCK_RECORD("generate_key");
|
||||||
|
StringResult result;
|
||||||
|
const char* id = LOGOS_CMOCK_RETURN_STRING("generate_key");
|
||||||
|
result.value = id ? strdup(id) : nullptr;
|
||||||
|
result.error = LOGOS_CMOCK_RETURN(int, "generate_key_error");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
OperationStatus add_key(
|
||||||
|
const char* user_config_path,
|
||||||
|
const char* keystore_path,
|
||||||
|
KeyType key_type,
|
||||||
|
const char* key_hex,
|
||||||
|
const char* key_title)
|
||||||
|
{
|
||||||
|
LOGOS_CMOCK_RECORD("add_key");
|
||||||
|
return LOGOS_CMOCK_RETURN(int, "add_key");
|
||||||
|
}
|
||||||
|
|
||||||
|
OperationStatus remove_key(
|
||||||
|
const char* user_config_path,
|
||||||
|
const char* keystore_path,
|
||||||
|
const char* key_title)
|
||||||
|
{
|
||||||
|
LOGOS_CMOCK_RECORD("remove_key");
|
||||||
|
return LOGOS_CMOCK_RETURN(int, "remove_key");
|
||||||
|
}
|
||||||
|
|
||||||
|
StringResult get_peer_id(const char* config_path) {
|
||||||
|
LOGOS_CMOCK_RECORD("get_peer_id");
|
||||||
|
StringResult result;
|
||||||
|
const char* id = LOGOS_CMOCK_RETURN_STRING("get_peer_id");
|
||||||
|
result.value = id ? strdup(id) : nullptr;
|
||||||
|
result.error = LOGOS_CMOCK_RETURN(int, "get_peer_id_error");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
OperationStatus subscribe_to_new_blocks(LogosBlockchainNode* node, BlockCallback callback) {
|
OperationStatus subscribe_to_new_blocks(LogosBlockchainNode* node, BlockCallback callback) {
|
||||||
LOGOS_CMOCK_RECORD("subscribe_to_new_blocks");
|
LOGOS_CMOCK_RECORD("subscribe_to_new_blocks");
|
||||||
return LOGOS_CMOCK_RETURN(int, "subscribe_to_new_blocks");
|
return LOGOS_CMOCK_RETURN(int, "subscribe_to_new_blocks");
|
||||||
|
|||||||
@ -30,6 +30,9 @@ typedef enum { Devnet } WellKnownDeployment;
|
|||||||
// Consensus state enum
|
// Consensus state enum
|
||||||
typedef enum { Bootstrapping, Online } State;
|
typedef enum { Bootstrapping, Online } State;
|
||||||
|
|
||||||
|
// Key type for generate_key / add_key
|
||||||
|
typedef enum { Ed25519, Zk } KeyType;
|
||||||
|
|
||||||
// Deployment configuration
|
// Deployment configuration
|
||||||
typedef struct {
|
typedef struct {
|
||||||
DeploymentType deployment_type;
|
DeploymentType deployment_type;
|
||||||
@ -97,6 +100,39 @@ NodeResult start_lb_node(const char* config_path, const char* deployment);
|
|||||||
OperationStatus stop_node(LogosBlockchainNode* node);
|
OperationStatus stop_node(LogosBlockchainNode* node);
|
||||||
OperationStatus subscribe_to_new_blocks(LogosBlockchainNode* node, BlockCallback callback);
|
OperationStatus subscribe_to_new_blocks(LogosBlockchainNode* node, BlockCallback callback);
|
||||||
|
|
||||||
|
// Config management
|
||||||
|
OperationStatus update_user_config(const char* user_config_path, const char* keystore_path);
|
||||||
|
OperationStatus migrate_user_config(const char* output_path, const char* keystore_path);
|
||||||
|
OperationStatus migrate_user_config_0_1_2(
|
||||||
|
const char* new_config_path,
|
||||||
|
const char* old_config_path,
|
||||||
|
const char* keystore_path);
|
||||||
|
OperationStatus participate(
|
||||||
|
const char* config_path,
|
||||||
|
const char* keystore_path,
|
||||||
|
const char* output_dir,
|
||||||
|
const char* external_address);
|
||||||
|
|
||||||
|
// Keystore
|
||||||
|
StringResult generate_key(
|
||||||
|
const char* user_config_path,
|
||||||
|
const char* keystore_path,
|
||||||
|
KeyType key_type,
|
||||||
|
const char* key_title);
|
||||||
|
OperationStatus add_key(
|
||||||
|
const char* user_config_path,
|
||||||
|
const char* keystore_path,
|
||||||
|
KeyType key_type,
|
||||||
|
const char* key_hex,
|
||||||
|
const char* key_title);
|
||||||
|
OperationStatus remove_key(
|
||||||
|
const char* user_config_path,
|
||||||
|
const char* keystore_path,
|
||||||
|
const char* key_title);
|
||||||
|
|
||||||
|
// Identity
|
||||||
|
StringResult get_peer_id(const char* config_path);
|
||||||
|
|
||||||
// Wallet
|
// Wallet
|
||||||
BalanceResult get_balance(LogosBlockchainNode* node, const uint8_t* address, const void* reserved);
|
BalanceResult get_balance(LogosBlockchainNode* node, const uint8_t* address, const void* reserved);
|
||||||
TransferHashResult transfer_funds(LogosBlockchainNode* node, const TransferFundsArguments* args);
|
TransferHashResult transfer_funds(LogosBlockchainNode* node, const TransferFundsArguments* args);
|
||||||
|
|||||||
@ -727,3 +727,204 @@ LOGOS_TEST(get_cryptarchia_info_returns_error_on_ffi_failure) {
|
|||||||
LOGOS_ASSERT_TRUE(starts_with(module->get_cryptarchia_info(), "Error:"));
|
LOGOS_ASSERT_TRUE(starts_with(module->get_cryptarchia_info(), "Error:"));
|
||||||
delete module;
|
delete module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Config management (operate on file paths, no running node required)
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
LOGOS_TEST(update_user_config_returns_0_on_success) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
t.mockCFunction("update_user_config").returns(0);
|
||||||
|
|
||||||
|
LOGOS_ASSERT_EQ(module.update_user_config("/tmp/config.yaml", "/tmp/keystore.yaml"), 0);
|
||||||
|
LOGOS_ASSERT(t.cFunctionCalled("update_user_config"));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGOS_TEST(update_user_config_returns_1_on_failure) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
t.mockCFunction("update_user_config").returns(1);
|
||||||
|
|
||||||
|
LOGOS_ASSERT_EQ(module.update_user_config("/tmp/config.yaml", "/tmp/keystore.yaml"), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGOS_TEST(migrate_user_config_returns_0_on_success) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
t.mockCFunction("migrate_user_config").returns(0);
|
||||||
|
|
||||||
|
LOGOS_ASSERT_EQ(module.migrate_user_config("/tmp/out.yaml", "/tmp/keystore.yaml"), 0);
|
||||||
|
LOGOS_ASSERT(t.cFunctionCalled("migrate_user_config"));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGOS_TEST(migrate_user_config_returns_1_on_failure) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
t.mockCFunction("migrate_user_config").returns(1);
|
||||||
|
|
||||||
|
LOGOS_ASSERT_EQ(module.migrate_user_config("/tmp/out.yaml", "/tmp/keystore.yaml"), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGOS_TEST(migrate_user_config_0_1_2_returns_0_on_success) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
t.mockCFunction("migrate_user_config_0_1_2").returns(0);
|
||||||
|
|
||||||
|
LOGOS_ASSERT_EQ(module.migrate_user_config_0_1_2("/tmp/new.yaml", "/tmp/old.yaml", "/tmp/keystore.yaml"), 0);
|
||||||
|
LOGOS_ASSERT(t.cFunctionCalled("migrate_user_config_0_1_2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGOS_TEST(migrate_user_config_0_1_2_returns_1_on_failure) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
t.mockCFunction("migrate_user_config_0_1_2").returns(1);
|
||||||
|
|
||||||
|
LOGOS_ASSERT_EQ(module.migrate_user_config_0_1_2("/tmp/new.yaml", "/tmp/old.yaml", "/tmp/keystore.yaml"), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGOS_TEST(participate_returns_0_on_success) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
t.mockCFunction("participate").returns(0);
|
||||||
|
|
||||||
|
LOGOS_ASSERT_EQ(module.participate("/tmp/config.yaml", "/tmp/keystore.yaml", "/tmp/out", ""), 0);
|
||||||
|
LOGOS_ASSERT(t.cFunctionCalled("participate"));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGOS_TEST(participate_returns_1_on_failure) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
t.mockCFunction("participate").returns(1);
|
||||||
|
|
||||||
|
LOGOS_ASSERT_EQ(module.participate("/tmp/config.yaml", "/tmp/keystore.yaml", "/tmp/out", "1.2.3.4"), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Keystore (generate_key / add_key / remove_key)
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
LOGOS_TEST(generate_key_returns_id_on_success) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
t.mockCFunction("generate_key").returns("key-abc123");
|
||||||
|
t.mockCFunction("generate_key_error").returns(0);
|
||||||
|
|
||||||
|
std::string result = module.generate_key("/tmp/config.yaml", "/tmp/keystore.yaml", "ed25519", "");
|
||||||
|
LOGOS_ASSERT_EQ(result, std::string("key-abc123"));
|
||||||
|
LOGOS_ASSERT(t.cFunctionCalled("generate_key"));
|
||||||
|
LOGOS_ASSERT(t.cFunctionCalled("free_cstring"));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGOS_TEST(generate_key_accepts_zk_type) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
t.mockCFunction("generate_key").returns("zk-key");
|
||||||
|
t.mockCFunction("generate_key_error").returns(0);
|
||||||
|
|
||||||
|
std::string result = module.generate_key("/tmp/config.yaml", "/tmp/keystore.yaml", "ZK", "my-title");
|
||||||
|
LOGOS_ASSERT_EQ(result, std::string("zk-key"));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGOS_TEST(generate_key_rejects_invalid_key_type) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
std::string result = module.generate_key("/tmp/config.yaml", "/tmp/keystore.yaml", "rsa", "");
|
||||||
|
LOGOS_ASSERT_TRUE(starts_with(result, "Error:"));
|
||||||
|
LOGOS_ASSERT_TRUE(contains(result, "key_type"));
|
||||||
|
LOGOS_ASSERT_FALSE(t.cFunctionCalled("generate_key"));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGOS_TEST(generate_key_returns_error_on_ffi_failure) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
t.mockCFunction("generate_key_error").returns(1);
|
||||||
|
|
||||||
|
std::string result = module.generate_key("/tmp/config.yaml", "/tmp/keystore.yaml", "ed25519", "");
|
||||||
|
LOGOS_ASSERT_TRUE(starts_with(result, "Error:"));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGOS_TEST(add_key_returns_0_on_success) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
t.mockCFunction("add_key").returns(0);
|
||||||
|
|
||||||
|
LOGOS_ASSERT_EQ(module.add_key("/tmp/config.yaml", "/tmp/keystore.yaml", "ed25519", VALID_HEX, ""), 0);
|
||||||
|
LOGOS_ASSERT(t.cFunctionCalled("add_key"));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGOS_TEST(add_key_rejects_invalid_key_type) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
LOGOS_ASSERT_EQ(module.add_key("/tmp/config.yaml", "/tmp/keystore.yaml", "bogus", VALID_HEX, ""), 1);
|
||||||
|
LOGOS_ASSERT_FALSE(t.cFunctionCalled("add_key"));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGOS_TEST(add_key_returns_1_on_failure) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
t.mockCFunction("add_key").returns(1);
|
||||||
|
|
||||||
|
LOGOS_ASSERT_EQ(module.add_key("/tmp/config.yaml", "/tmp/keystore.yaml", "zk", VALID_HEX, "title"), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGOS_TEST(remove_key_returns_0_on_success) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
t.mockCFunction("remove_key").returns(0);
|
||||||
|
|
||||||
|
LOGOS_ASSERT_EQ(module.remove_key("/tmp/config.yaml", "/tmp/keystore.yaml", "my-key"), 0);
|
||||||
|
LOGOS_ASSERT(t.cFunctionCalled("remove_key"));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGOS_TEST(remove_key_returns_1_on_failure) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
t.mockCFunction("remove_key").returns(1);
|
||||||
|
|
||||||
|
LOGOS_ASSERT_EQ(module.remove_key("/tmp/config.yaml", "/tmp/keystore.yaml", "my-key"), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Identity (get_peer_id)
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
LOGOS_TEST(get_peer_id_returns_id_on_success) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
t.mockCFunction("get_peer_id").returns("12D3KooWPeerId");
|
||||||
|
t.mockCFunction("get_peer_id_error").returns(0);
|
||||||
|
|
||||||
|
std::string result = module.get_peer_id("/tmp/config.yaml");
|
||||||
|
LOGOS_ASSERT_EQ(result, std::string("12D3KooWPeerId"));
|
||||||
|
LOGOS_ASSERT(t.cFunctionCalled("get_peer_id"));
|
||||||
|
LOGOS_ASSERT(t.cFunctionCalled("free_cstring"));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGOS_TEST(get_peer_id_returns_error_on_ffi_failure) {
|
||||||
|
auto t = LogosTestContext("blockchain_module");
|
||||||
|
LogosBlockchainModule module;
|
||||||
|
|
||||||
|
t.mockCFunction("get_peer_id_error").returns(1);
|
||||||
|
|
||||||
|
std::string result = module.get_peer_id("/tmp/config.yaml");
|
||||||
|
LOGOS_ASSERT_TRUE(starts_with(result, "Error:"));
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user