darkfid: Add RPC endpoint to retrieve WASM bincode

Also updates the params.get() RPC code patterns.
This commit is contained in:
x
2026-01-01 14:38:01 +00:00
parent 9785777642
commit 0fd57636ea
4 changed files with 87 additions and 17 deletions

View File

@@ -40,6 +40,7 @@ pub enum RpcError {
ContractZkasDbNotFound = -32200,
ContractStateNotFound = -32201,
ContractStateKeyNotFound = -32202,
ContractWasmNotFound = -32203,
// Miner configuration errors
MinerInvalidWalletConfig = -32301,
@@ -108,6 +109,7 @@ fn to_tuple(e: RpcError) -> (i32, String) {
RpcError::ContractZkasDbNotFound => "zkas database not found for given contract",
RpcError::ContractStateNotFound => "Records not found for given contract state",
RpcError::ContractStateKeyNotFound => "Value not found for given contract state key",
RpcError::ContractWasmNotFound => "wasm bincode not found for given contract",
// Miner configuration errors
RpcError::MinerInvalidWalletConfig => "Request wallet configuration is invalid",

View File

@@ -96,7 +96,9 @@ impl DarkfiNode {
// --> {"jsonrpc": "2.0", "method": "blockchain.get_tx", "params": ["TxHash"], "id": 1}
// <-- {"jsonrpc": "2.0", "result": "base64encodedtx", "id": 1}
pub async fn blockchain_get_tx(&self, id: u16, params: JsonValue) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(InvalidParams, None, id).into()
};
if params.len() != 1 || !params[0].is_string() {
return JsonError::new(InvalidParams, None, id).into()
}
@@ -136,7 +138,9 @@ impl DarkfiNode {
// --> {"jsonrpc": "2.0", "method": "blockchain.last_confirmed_block", "params": [], "id": 1}
// <-- {"jsonrpc": "2.0", "result": [1234, "HeaderHash"], "id": 1}
pub async fn blockchain_last_confirmed_block(&self, id: u16, params: JsonValue) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(InvalidParams, None, id).into()
};
if !params.is_empty() {
return JsonError::new(InvalidParams, None, id).into()
}
@@ -171,7 +175,9 @@ impl DarkfiNode {
id: u16,
params: JsonValue,
) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(InvalidParams, None, id).into()
};
if !params.is_empty() {
return JsonError::new(InvalidParams, None, id).into()
}
@@ -195,7 +201,9 @@ impl DarkfiNode {
// --> {"jsonrpc": "2.0", "method": "blockchain.block_target", "params": [], "id": 1}
// <-- {"jsonrpc": "2.0", "result": 120, "id": 1}
pub async fn blockchain_block_target(&self, id: u16, params: JsonValue) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(InvalidParams, None, id).into()
};
if !params.is_empty() {
return JsonError::new(InvalidParams, None, id).into()
}
@@ -220,7 +228,9 @@ impl DarkfiNode {
// --> {"jsonrpc": "2.0", "method": "blockchain.subscribe_blocks", "params": [], "id": 1}
// <-- {"jsonrpc": "2.0", "method": "blockchain.subscribe_blocks", "params": ["base64encodedblock"]}
pub async fn blockchain_subscribe_blocks(&self, id: u16, params: JsonValue) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(InvalidParams, None, id).into()
};
if !params.is_empty() {
return JsonError::new(InvalidParams, None, id).into()
}
@@ -239,7 +249,9 @@ impl DarkfiNode {
// --> {"jsonrpc": "2.0", "method": "blockchain.subscribe_txs", "params": [], "id": 1}
// <-- {"jsonrpc": "2.0", "method": "blockchain.subscribe_txs", "params": ["tx_hash"]}
pub async fn blockchain_subscribe_txs(&self, id: u16, params: JsonValue) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(InvalidParams, None, id).into()
};
if !params.is_empty() {
return JsonError::new(InvalidParams, None, id).into()
}
@@ -260,7 +272,9 @@ impl DarkfiNode {
// --> {"jsonrpc": "2.0", "method": "blockchain.subscribe_proposals", "params": [], "id": 1}
// <-- {"jsonrpc": "2.0", "method": "blockchain.subscribe_proposals", "params": ["base64encodedblock"]}
pub async fn blockchain_subscribe_proposals(&self, id: u16, params: JsonValue) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(InvalidParams, None, id).into()
};
if !params.is_empty() {
return JsonError::new(InvalidParams, None, id).into()
}
@@ -286,7 +300,9 @@ impl DarkfiNode {
// --> {"jsonrpc": "2.0", "method": "blockchain.lookup_zkas", "params": ["BZHKGQ26bzmBithTQYTJtjo2QdCqpkR9tjSBopT4yf4o"], "id": 1}
// <-- {"jsonrpc": "2.0", "result": [["Foo", "ABCD..."], ["Bar", "EFGH..."]], "id": 1}
pub async fn blockchain_lookup_zkas(&self, id: u16, params: JsonValue) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(InvalidParams, None, id).into()
};
if params.len() != 1 || !params[0].is_string() {
return JsonError::new(InvalidParams, None, id).into()
}
@@ -337,6 +353,39 @@ impl DarkfiNode {
JsonResponse::new(JsonValue::Array(ret), id).into()
}
// RPCAPI:
// Perform a lookup of a WASM contract binary deployed on-chain and
// return the base64-encoded binary.
//
// **Params:**
// * `array[0]`: base58-encoded contract ID string
//
// **Returns:**
// * `String`: base64-encoded WASM binary
//
// --> {"jsonrpc": "2.0", "method": "blockchain.lookup_wasm", "params": ["BZHKGQ26bzmBithTQYTJtjo2QdCqpkR9tjSBopT4yf4o"], "id": 1}
// <-- ["jsonrpc": "2.0", "result": "ABCD...", "id": 1}
pub async fn blockchain_lookup_wasm(&self, id: u16, params: JsonValue) -> JsonResult {
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(InvalidParams, None, id).into()
};
if params.len() != 1 || !params[0].is_string() {
return JsonError::new(InvalidParams, None, id).into()
}
let contract_id = params[0].get::<String>().unwrap();
let Ok(contract_id) = ContractId::from_str(contract_id) else {
return server_error(RpcError::ParseError, id, None)
};
let Ok(bincode) = self.validator.blockchain.contracts.get(contract_id) else {
return server_error(RpcError::ContractWasmNotFound, id, None)
};
let encoded = base64::encode(&bincode);
JsonResponse::new(encoded.to_string().into(), id).into()
}
// RPCAPI:
// Queries the blockchain database for a given contract state records.
// Returns the records value raw bytes as a `BTreeMap`.
@@ -351,7 +400,9 @@ impl DarkfiNode {
// --> {"jsonrpc": "2.0", "method": "blockchain.get_contract_state", "params": ["BZHK...", "tree"], "id": 1}
// <-- {"jsonrpc": "2.0", "result": "ABCD...", "id": 1}
pub async fn blockchain_get_contract_state(&self, id: u16, params: JsonValue) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(InvalidParams, None, id).into()
};
if params.len() != 2 || !params[0].is_string() || !params[1].is_string() {
return JsonError::new(InvalidParams, None, id).into()
}
@@ -403,7 +454,9 @@ impl DarkfiNode {
id: u16,
params: JsonValue,
) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(InvalidParams, None, id).into()
};
if params.len() != 3 ||
!params[0].is_string() ||
!params[1].is_string() ||

View File

@@ -75,6 +75,7 @@ impl RequestHandler<DefaultRpcHandler> for DarkfiNode {
"blockchain.last_confirmed_block" => self.blockchain_last_confirmed_block(req.id, req.params).await,
"blockchain.best_fork_next_block_height" => self.blockchain_best_fork_next_block_height(req.id, req.params).await,
"blockchain.block_target" => self.blockchain_block_target(req.id, req.params).await,
"blockchain.lookup_wasm" => self.blockchain_lookup_wasm(req.id, req.params).await,
"blockchain.lookup_zkas" => self.blockchain_lookup_zkas(req.id, req.params).await,
"blockchain.get_contract_state" => self.blockchain_get_contract_state(req.id, req.params).await,
"blockchain.get_contract_state_key" => self.blockchain_get_contract_state_key(req.id, req.params).await,
@@ -123,7 +124,9 @@ impl DarkfiNode {
// --> {"jsonrpc": "2.0", "method": "dnet.switch", "params": [true], "id": 1}
// <-- {"jsonrpc": "2.0", "result": true, "id": 1}
async fn dnet_switch(&self, id: u16, params: JsonValue) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(ErrorCode::InvalidParams, None, id).into()
};
if params.len() != 1 || !params[0].is_bool() {
return JsonError::new(ErrorCode::InvalidParams, None, id).into()
}
@@ -162,7 +165,9 @@ impl DarkfiNode {
// ]
// }
pub async fn dnet_subscribe_events(&self, id: u16, params: JsonValue) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(ErrorCode::InvalidParams, None, id).into()
};
if !params.is_empty() {
return JsonError::new(ErrorCode::InvalidParams, None, id).into()
}

View File

@@ -41,7 +41,9 @@ impl DarkfiNode {
// --> {"jsonrpc": "2.0", "method": "tx.simulate", "params": ["base64encodedTX"], "id": 1}
// <-- {"jsonrpc": "2.0", "result": true, "id": 1}
pub async fn tx_simulate(&self, id: u16, params: JsonValue) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(InvalidParams, None, id).into()
};
if params.len() != 1 || !params[0].is_string() {
return JsonError::new(InvalidParams, None, id).into()
}
@@ -92,7 +94,9 @@ impl DarkfiNode {
// --> {"jsonrpc": "2.0", "method": "tx.broadcast", "params": ["base64encodedTX"], "id": 1}
// <-- {"jsonrpc": "2.0", "result": "txID...", "id": 1}
pub async fn tx_broadcast(&self, id: u16, params: JsonValue) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(InvalidParams, None, id).into()
};
if params.len() != 1 || !params[0].is_string() {
return JsonError::new(InvalidParams, None, id).into()
}
@@ -142,7 +146,9 @@ impl DarkfiNode {
// --> {"jsonrpc": "2.0", "method": "tx.pending", "params": [], "id": 1}
// <-- {"jsonrpc": "2.0", "result": ["TxHash" , "..."], "id": 1}
pub async fn tx_pending(&self, id: u16, params: JsonValue) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(InvalidParams, None, id).into()
};
if !params.is_empty() {
return JsonError::new(InvalidParams, None, id).into()
}
@@ -173,7 +179,9 @@ impl DarkfiNode {
// --> {"jsonrpc": "2.0", "method": "tx.clean_pending", "params": [], "id": 1}
// <-- {"jsonrpc": "2.0", "result": ["TxHash", "..."], "id": 1}
pub async fn tx_clean_pending(&self, id: u16, params: JsonValue) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(InvalidParams, None, id).into()
};
if !params.is_empty() {
return JsonError::new(InvalidParams, None, id).into()
}
@@ -210,7 +218,9 @@ impl DarkfiNode {
// --> {"jsonrpc": "2.0", "method": "tx.calculate_fee", "params": ["base64encodedTX", "include_fee"], "id": 1}
// <-- {"jsonrpc": "2.0", "result": true, "id": 1}
pub async fn tx_calculate_fee(&self, id: u16, params: JsonValue) -> JsonResult {
let params = params.get::<Vec<JsonValue>>().unwrap();
let Some(params) = params.get::<Vec<JsonValue>>() else {
return JsonError::new(InvalidParams, None, id).into()
};
if params.len() != 2 || !params[0].is_string() || !params[1].is_bool() {
return JsonError::new(InvalidParams, None, id).into()
}