diff --git a/Cargo.lock b/Cargo.lock index 9686ce4b68..e74f3d4287 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5695,6 +5695,7 @@ name = "test-rpc-functions" version = "0.1.0" dependencies = [ "async-trait", + "chainstate", "chainstate-types", "common", "crypto", diff --git a/node-lib/src/runner.rs b/node-lib/src/runner.rs index c940409d71..0432921336 100644 --- a/node-lib/src/runner.rs +++ b/node-lib/src/runner.rs @@ -136,7 +136,10 @@ async fn initialize( // RPC Functions for tests let rpc_test_functions = if chain_config.chain_type() == &ChainType::Regtest { // We add the test rpc functions only if we are in regtest mode - manager.add_subsystem("rpc_test_functions", make_rpc_test_functions()) + manager.add_subsystem( + "rpc_test_functions", + make_rpc_test_functions(Arc::clone(&chain_config)), + ) } else { // Otherwise we add empty rpc functions manager.add_subsystem("rpc_test_functions", make_empty_rpc_test_functions()) diff --git a/test-rpc-functions/Cargo.toml b/test-rpc-functions/Cargo.toml index 4f7e2c63ba..c2bc0aaf21 100644 --- a/test-rpc-functions/Cargo.toml +++ b/test-rpc-functions/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] chainstate-types = { path = "../chainstate/types" } +chainstate = { path = "../chainstate/" } common = { path = "../common/" } crypto = { path = "../crypto/" } rpc = { path = "../rpc/" } diff --git a/test-rpc-functions/src/empty.rs b/test-rpc-functions/src/empty.rs index e1ab429434..b0a6d33de4 100644 --- a/test-rpc-functions/src/empty.rs +++ b/test-rpc-functions/src/empty.rs @@ -13,7 +13,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::sync::Arc; + use crate::interface::rpc_test_interface::RpcTestFunctionsInterface; +use common::chain::ChainConfig; // Empty implementation to exclude test functions under certain conditions, such as mainnet pub struct EmptyRpcTestFunctionsRpc; @@ -34,4 +37,8 @@ pub fn make_empty_rpc_test_functions() -> Box { Box::new(EmptyRpcTestFunctionsRpc::new()) } -impl RpcTestFunctionsInterface for EmptyRpcTestFunctionsRpc {} +impl RpcTestFunctionsInterface for EmptyRpcTestFunctionsRpc { + fn get_chain_config(&self) -> Option> { + None + } +} diff --git a/test-rpc-functions/src/interface/rpc_test_interface.rs b/test-rpc-functions/src/interface/rpc_test_interface.rs index 60181ed0e3..5e49ddfd30 100644 --- a/test-rpc-functions/src/interface/rpc_test_interface.rs +++ b/test-rpc-functions/src/interface/rpc_test_interface.rs @@ -13,5 +13,11 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::sync::Arc; + +use common::chain::ChainConfig; + #[async_trait::async_trait] -pub trait RpcTestFunctionsInterface: Send {} +pub trait RpcTestFunctionsInterface: Send { + fn get_chain_config(&self) -> Option>; +} diff --git a/test-rpc-functions/src/interface/rpc_test_interface_impl.rs b/test-rpc-functions/src/interface/rpc_test_interface_impl.rs index 4d6c12bd73..6f97b914ae 100644 --- a/test-rpc-functions/src/interface/rpc_test_interface_impl.rs +++ b/test-rpc-functions/src/interface/rpc_test_interface_impl.rs @@ -13,9 +13,26 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::sync::Arc; + use crate::RpcTestFunctions; +use common::chain::ChainConfig; use super::rpc_test_interface::RpcTestFunctionsInterface; +pub struct RpcTestFunctionsImpl { + rpc_test_functions: RpcTestFunctions, +} + +impl RpcTestFunctionsImpl { + pub fn new(rpc_test_functions: RpcTestFunctions) -> Self { + Self { rpc_test_functions } + } +} + #[async_trait::async_trait] -impl RpcTestFunctionsInterface for RpcTestFunctions {} +impl RpcTestFunctionsInterface for RpcTestFunctionsImpl { + fn get_chain_config(&self) -> Option> { + Some(Arc::clone(&self.rpc_test_functions.chain_config)) + } +} diff --git a/test-rpc-functions/src/lib.rs b/test-rpc-functions/src/lib.rs index c0232409b9..8bba0cd6f8 100644 --- a/test-rpc-functions/src/lib.rs +++ b/test-rpc-functions/src/lib.rs @@ -13,9 +13,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::sync::Arc; + use chainstate_types::vrf_tools::ProofOfStakeVRFError; +use common::chain::ChainConfig; use crypto::key::SignatureError; -use interface::rpc_test_interface::RpcTestFunctionsInterface; +use interface::{ + rpc_test_interface::RpcTestFunctionsInterface, rpc_test_interface_impl::RpcTestFunctionsImpl, +}; use subsystem::subsystem::CallError; pub mod empty; @@ -32,11 +37,13 @@ pub enum RpcTestFunctionsError { ProofOfStakeVRFError(#[from] ProofOfStakeVRFError), } -pub struct RpcTestFunctions {} +pub struct RpcTestFunctions { + chain_config: Arc, +} impl RpcTestFunctions { - pub fn new() -> Self { - Self {} + pub fn new(chain_config: Arc) -> Self { + Self { chain_config } } } @@ -44,6 +51,10 @@ pub type RpcTestFunctionsHandle = subsystem::Handle {} -pub fn make_rpc_test_functions() -> Box { - Box::new(RpcTestFunctions::new()) +pub fn make_rpc_test_functions( + chain_config: Arc, +) -> Box { + let rpc_test_functions = RpcTestFunctions::new(chain_config); + let rpc_test_functions_interface = RpcTestFunctionsImpl::new(rpc_test_functions); + Box::new(rpc_test_functions_interface) } diff --git a/test-rpc-functions/src/rpc.rs b/test-rpc-functions/src/rpc.rs index 2654d059d8..f4ca5f8104 100644 --- a/test-rpc-functions/src/rpc.rs +++ b/test-rpc-functions/src/rpc.rs @@ -17,16 +17,35 @@ use chainstate_types::vrf_tools::{construct_transcript, verify_vrf_and_get_vrf_output}; use common::{ - chain::{block::timestamp::BlockTimestamp, config::EpochIndex}, + chain::config::regtest_genesis_values, + chain::{ + block::timestamp::BlockTimestamp, config::EpochIndex, stakelock::StakePoolData, PoolId, + TxOutput, + }, primitives::H256, }; use crypto::key::Signature; use serialization::{hex::HexDecode, hex::HexEncode}; -use crate::RpcTestFunctionsError; +use crate::{RpcTestFunctionsError, RpcTestFunctionsHandle}; #[rpc::rpc(server, namespace = "test_functions")] trait RpcTestFunctionsRpc { + #[method(name = "genesis_pool_id")] + async fn genesis_pool_id(&self) -> rpc::Result>; + + #[method(name = "genesis_private_key")] + async fn genesis_private_key(&self) -> rpc::Result>; + + #[method(name = "genesis_public_key")] + async fn genesis_public_key(&self) -> rpc::Result>; + + #[method(name = "genesis_vrf_private_key")] + async fn genesis_vrf_private_key(&self) -> rpc::Result>; + + #[method(name = "genesis_vrf_public_key")] + async fn genesis_vrf_public_key(&self) -> rpc::Result>; + #[method(name = "new_private_key")] async fn new_private_key(&self) -> rpc::Result; @@ -77,6 +96,60 @@ trait RpcTestFunctionsRpc { #[async_trait::async_trait] impl RpcTestFunctionsRpcServer for super::RpcTestFunctionsHandle { + async fn genesis_pool_id(&self) -> rpc::Result> { + let (genesis_pool_id, genesis_stake_pool_data, _, _, _, _) = regtest_genesis_values(); + + Ok( + assert_genesis_values(self, genesis_pool_id, genesis_stake_pool_data) + .await + .then_some(genesis_pool_id.hex_encode()), + ) + } + + async fn genesis_private_key(&self) -> rpc::Result> { + let (genesis_pool_id, genesis_stake_pool_data, genesis_stake_private_key, _, _, _) = + regtest_genesis_values(); + + Ok( + assert_genesis_values(self, genesis_pool_id, genesis_stake_pool_data) + .await + .then_some(genesis_stake_private_key.hex_encode()), + ) + } + + async fn genesis_public_key(&self) -> rpc::Result> { + let (genesis_pool_id, genesis_stake_pool_data, _, genesis_stake_public_key, _, _) = + regtest_genesis_values(); + + Ok( + assert_genesis_values(self, genesis_pool_id, genesis_stake_pool_data) + .await + .then_some(genesis_stake_public_key.hex_encode()), + ) + } + + async fn genesis_vrf_private_key(&self) -> rpc::Result> { + let (genesis_pool_id, genesis_stake_pool_data, _, _, genesis_vrf_private_key, _) = + regtest_genesis_values(); + + Ok( + assert_genesis_values(self, genesis_pool_id, genesis_stake_pool_data) + .await + .then_some(genesis_vrf_private_key.hex_encode()), + ) + } + + async fn genesis_vrf_public_key(&self) -> rpc::Result> { + let (genesis_pool_id, genesis_stake_pool_data, _, _, _, genesis_vrf_public_key) = + regtest_genesis_values(); + + Ok( + assert_genesis_values(self, genesis_pool_id, genesis_stake_pool_data) + .await + .then_some(genesis_vrf_public_key.hex_encode()), + ) + } + async fn new_private_key(&self) -> rpc::Result { let keys = crypto::key::PrivateKey::new_from_entropy(crypto::key::KeyKind::Secp256k1Schnorr); @@ -194,3 +267,28 @@ impl RpcTestFunctionsRpcServer for super::RpcTestFunctionsHandle { Ok(vrf_output.hex_encode()) } } + +async fn assert_genesis_values( + handle: &RpcTestFunctionsHandle, + genesis_pool_id: PoolId, + genesis_stake_pool_data: Box, +) -> bool { + let expected_genesis_pool_txoutput = + TxOutput::CreateStakePool(genesis_pool_id, genesis_stake_pool_data); + + let current_create_genesis_pool_txoutput = handle + .call(|this| { + this.get_chain_config() + .and_then(|chain| chain.genesis_block().utxos().get(1).map(|u| u.hex_encode())) + }) + .await + .expect("Subsystem call ok"); + + match current_create_genesis_pool_txoutput { + None => false, + Some(txoutput) => { + assert!(txoutput == expected_genesis_pool_txoutput.hex_encode()); + true + } + } +}