Skip to content

Commit

Permalink
fixup! feat: add provider interface
Browse files Browse the repository at this point in the history
  • Loading branch information
AngelCastilloB committed Oct 4, 2024
1 parent 36d28fd commit 63b652d
Show file tree
Hide file tree
Showing 8 changed files with 557 additions and 53 deletions.
8 changes: 8 additions & 0 deletions doc/src/sections/api/witness_set/redeemer_list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ Redeemer List

------------

.. doxygenfunction:: cardano_redeemer_list_set_ex_units

------------

.. doxygenfunction:: cardano_redeemer_list_clone

------------

.. doxygenfunction:: cardano_redeemer_list_clear_cbor_cache

------------
Expand Down
60 changes: 41 additions & 19 deletions examples/provider_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,13 @@
#include "providers/provider_factory.h"

#include <cardano/cardano.h>
#include <json-c/json_object.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* MAIN **********************************************************************/
static const char* TX_CBOR = "84a50081825820caf96c148fe8f30127c83e41d105ae64d9bb83348596dfaa2f8964eb0631c24601018282583900df88a476cecb804e89f45b3600399f55eb2928065da76165cf6dd7c7a84bacc10de2203d30331255459b8e1736a22134cc554d1ed5789a721a0206cc8082583900df88a476cecb804e89f45b3600399f55eb2928065da76165cf6dd7c7a84bacc10de2203d30331255459b8e1736a22134cc554d1ed5789a72821a18e60dcfa1581c72716d7bced784a0f8b62657d5f945f2f3fc13f8a92b34ec62d55859a3474e46542d3030311887474e46542d30303218b8494e46542d66696c657318df021a0002a1fd031a044ddc71075820d36a2619a672494604e11bb447cbcf5231e9f2ba25c2169177edc941bd50ad6ca10081825820a28d88d86ec2dc9cbff74fa00d3b654cc04749d0d1e9be09447bf508aca3050058400af5c6bf83e0f21cea9cc6caa44b2f3d075ecdbb5019db31611b3b49f9bfae6ba78327047af050d0946e42884f38631e0fdb56d58905d4cadd91a6c264353802f5a0";

static const char* TX_CBOR = "84a700828258201d0733f74b07e8213ce64f4efc8f947929e52ab50e27d9309844e152b3da7a1001825820e74b3e4d42025748d882b24d5adc1644256baeffb1039702486c226f39f700ff000182a300581d700585892a51d5184081ba2e8ebb0ce36abae71acd5ef6688a02612938011a00958940028201d81858369fc250fff0000000000000000000000000000058200000000000000000000000000000000000000000000000000000000000000000ff8258390026048fcfcee71b108e4a4d2ed6a29b1ae792bdc92ef6371184476254ecf868fe6a630521eb6ae72f00394f63a44e4d668fc0d82d49ac8b001b000000024adb99e6021a001d6dad0b58203d97c7448af5ee2f7b373a303540fee3e07767dcb0af6e218566df57a774c5d90d818258201d0733f74b07e8213ce64f4efc8f947929e52ab50e27d9309844e152b3da7a1001108258390026048fcfcee71b108e4a4d2ed6a29b1ae792bdc92ef6371184476254ecf868fe6a630521eb6ae72f00394f63a44e4d668fc0d82d49ac8b001b000000024aa9af13128182582049dbd6b43d4924233bbf1ab6b4e9392df500169932ac39bc38a17d066dbd82fb00a20081825820efd07d558917c5429409ddc1e0b8028ed64c2b177e8cb2969e86a7a3b4bb5812584071b302b6711dafe5d907f2b69288228eaaa23e4ff0bc532f77b1de8ff6b763350d15d66172546675c1dc94fc61e121326e39b27db9ebb645c587374f931ec30705a1820001829f025820cbd1b768114a08a65e65218bc38623f619765731cf7b298b20909e997c281b6601187358200000000000000000000000000000000000000000000000000000000000000001582000000000000000000000000000000000000000000000000000000000000000025820d60d101c914f6a53fdff284558628266deb40190449873776b33476928733b455840db59abc3a4a87354679e1286187fb78913329bd2f7c6a2baefaf19f8547089e47903da2d895467823d8fac859179840aa00e65ccd40ce58692436572c51fa70558200000000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000000005820000000000000000000000000000000000000000000000000000000000000000058200000000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000000005820000000000000000000000000000000000000000000000000000000000000000058200000000000000000000000000000000000000000000000000000000000000000ff821a00059b641a05118e1ff5f6";
// static const char* TX_CBOR = "84a80082825820232c8e27c806a0eea8049a6b8217f4325a7348f38ed4913e7adb9d127261fe6d00825820232c8e27c806a0eea8049a6b8217f4325a7348f38ed4913e7adb9d127261fe6d030181825839006bd95fcacb2373d68ae094fdefcc4811358e11ca0306a9f4b3bcbbe866499a2e015b6b02a783f0c5c8af0a9506a648725c951f8d4e2ecbc61a6e2cf031021a0002ae820b5820d9f3a918ad71f3416d150c3cc2224c4d4e371abcd02afb699b94cf45e8748e340d81825820232c8e27c806a0eea8049a6b8217f4325a7348f38ed4913e7adb9d127261fe6d0310825839006bd95fcacb2373d68ae094fdefcc4811358e11ca0306a9f4b3bcbbe866499a2e015b6b02a783f0c5c8af0a9506a648725c951f8d4e2ecbc61a6dfdd230111a000405c31281825820232c8e27c806a0eea8049a6b8217f4325a7348f38ed4913e7adb9d127261fe6d01a300818258205bb407d6f3a428c1102b0daf423b093a2e0cbf51517c30e63f2f003d06dd763a5840472a7b08e6400601f4bb2d596b0b0fc9b8113e06f45a7d8b7235e670b81acd20b20017e7c9c0f6a5da5e5f213b51213e02cab57174bbe5194dd6b663e59f5a03049fd87980ff0581840000d879808219044c1a000382d4f5f6";
static const char* CBOR = "82825820bb217abaca60fc0ca68c1555eca6a96d2478547818ae76ce6836133f3cc546e001a200583900287a7e37219128cfb05322626daa8b19d1ad37c6779d21853f7b94177c16240714ea0e12b41a914f2945784ac494bb19573f0ca61a08afa801821af0078c21a2581c1ec85dcee27f2d90ec1f9a1e4ce74a667dc9be8b184463223f9c9601a14350584c05581c659f2917fb63f12b33667463ee575eeac1845bbc736b9c0bbc40ba82a14454534c410a";
static const char* CBOR_DIFFERENT_INPUT = "82825820bb217abaca60fc0ca78c1555eca6a96d2478547818ae76ce6836133f3cc546e001a200583900287a7e37219128cfb05322626daa8b19d1ad37c6779d21853f7b94177c16240714ea0e12b41a914f2945784ac494bb19573f0ca61a08afa801821af0078c21a2581c1ec85dcee27f2d90ec1f9a1e4ce74a667dc9be8b184463223f9c9601a14350584c05581c659f2917fb63f12b33667463ee575eeac1845bbc736b9c0bbc40ba82a14454534c410a";
static const char* CBOR_DIFFERENT_OUTPUT = "82825820bb217abaca60fc0ca68c1555eca6a96d2478547818ae76ce6836133f3cc546e001a200583900287a7e37219128cfb05322626daa8b19d1ad37c6779d21853f7b94177c16240714ea0e12b41a914f2945784ac494bb19573f0ca61a08afa801821af0078c21a2581c1ec85dcee27f2d90ec1f9a1e4ce74a667dc9be8b184463223f9c9601a14350584c05581c659f2917fb63f12b33667463ee575eeac1845bbc736b9c0bbc40ba82a14454534c420a";
Expand Down Expand Up @@ -301,22 +300,11 @@ main()
cardano_transaction_t* tx = NULL;
tx = get_transaction();

cardano_error_t result = cardano_evaluate_params_to_json(tx, listx, &json_obj_str, &json_obj_size);

if (result != CARDANO_SUCCESS)
{
printf("Failed to convert UTXOs to JSON: %s\n", cardano_error_to_string(result));
return 1;
}

printf("UTXOs: %s\n", json_obj_str);

free(json_obj_str);
cardano_utxo_list_unref(&listx);
// cardano_utxo_list_unref(&listx);

cardano_provider_t* provider = NULL;

result = create_blockfrost_provider(CARDANO_NETWORK_MAGIC_PREPROD, api_key, strlen(api_key), &provider);
cardano_error_t result = create_blockfrost_provider(CARDANO_NETWORK_MAGIC_PREPROD, api_key, strlen(api_key), &provider);

if (result != CARDANO_SUCCESS)
{
Expand Down Expand Up @@ -367,7 +355,40 @@ main()
return 1;
}

// result = cardano_provider_submit_transaction(provider, tx, &tx_id);
CARDANO_UNUSED(listx);
cardano_redeemer_list_t* redeemers = NULL;
result = cardano_provider_evaluate_transaction(provider, tx, listx, &redeemers);

CARDANO_UNUSED(result);

cardano_witness_set_t* witness = cardano_transaction_get_witness_set(tx);
cardano_witness_set_unref(&witness);

result = cardano_witness_set_set_redeemers(witness, redeemers);
CARDANO_UNUSED(result);

if (result == CARDANO_SUCCESS)
{
cardano_cbor_writer_t* writer = cardano_cbor_writer_new();

result = cardano_transaction_to_cbor(tx, writer);
CARDANO_UNUSED(result);

size_t cbor_size = cardano_cbor_writer_get_hex_size(writer);
char* cbor_hex = malloc(cbor_size);

result = cardano_cbor_writer_encode_hex(writer, cbor_hex, cbor_size);
CARDANO_UNUSED(result);

printf("TX: %s\n", cbor_hex);

free(cbor_hex);
cardano_cbor_writer_unref(&writer);
}

cardano_redeemer_list_unref(&redeemers);
cardano_utxo_list_unref(&listx);
result = cardano_provider_submit_transaction(provider, tx, &tx_id);
/*
if (result != CARDANO_SUCCESS)
{
Expand All @@ -389,17 +410,18 @@ main()

if (result != CARDANO_SUCCESS)
{
printf("Failed to confirm transaction: %s\n", cardano_provider_get_last_error(provider));

cardano_provider_unref(&provider);
cardano_address_unref(&address);
cardano_asset_id_unref(&asset_id);

printf("Failed to confirm transaction: %s\n", cardano_provider_get_last_error(provider));
return 1;
}

printf("Transaction confirmed: %s\n", confirmed ? "true" : "false");

result = cardano_provider_resolve_datum(provider, hash, &datum);
// result = cardano_provider_resolve_datum(provider, hash, &datum);

if (result == CARDANO_SUCCESS)
{
Expand Down
87 changes: 81 additions & 6 deletions examples/providers/blockfrost/blockfrost_provider.c
Original file line number Diff line number Diff line change
Expand Up @@ -948,20 +948,95 @@ post_transaction_to_chain(
return result;
}

/**
* \brief Evaluates a transaction using the specified provider and updates redeemer execution units.
*
* This function evaluates a transaction in the context of a set of additional UTXOs. It communicates with the provider
* to evaluate the transaction and updates the redeemer list with execution units based on the result.
*
* \param[in] provider_impl A pointer to an initialized \ref cardano_provider_impl_t object representing the provider. This must not be NULL.
* \param[in] tx A pointer to an initialized \ref cardano_transaction_t object representing the transaction to be evaluated. This must not be NULL.
* \param[in] additional_utxos A pointer to an initialized \ref cardano_utxo_list_t object representing the additional UTXOs. This parameter can be NULL
* if no additional UTXOs are needed for the evaluation.
* \param[out] redeemers On success, this will point to a newly created \ref cardano_redeemer_list_t object containing the redeemers
* with updated execution units based on the evaluation result. The caller is responsible for managing the lifecycle
* of this object, including calling \ref cardano_redeemer_list_unref when it is no longer needed.
*
* \return \ref cardano_error_t indicating the outcome of the operation. Returns \ref CARDANO_SUCCESS if the transaction was successfully evaluated,
* or an appropriate error code such as \ref CARDANO_POINTER_IS_NULL if any required input pointer is NULL, or a specific error from the provider.
*
* \note The caller is responsible for releasing the memory of the \p redeemers object when it is no longer needed.
*/
static cardano_error_t
evaluate_transaction(
cardano_provider_impl_t* provider_impl,
cardano_transaction_t* tx,
cardano_utxo_list_t* additional_utxos,
cardano_redeemer_list_t** redeemers)
{
CARDANO_UNUSED(provider_impl);
CARDANO_UNUSED(tx);
CARDANO_UNUSED(additional_utxos);
CARDANO_UNUSED(redeemers);
// const size_t additional_utxos_len = cardano_utxo_list_get_length(additional_utxos);
blockfrost_context_t* context = (blockfrost_context_t*)provider_impl->context;
char* base_path = cardano_blockfrost_get_endpoint_url(context->network, "/utils/txs/evaluate/utxos");
cardano_buffer_t* response_buffer = NULL;
uint64_t response_code = 0;

char* json_payload = NULL;
size_t json_size = 0;
cardano_error_t result = cardano_evaluate_params_to_json(tx, additional_utxos, &json_payload, &json_size);

if (result != CARDANO_SUCCESS)
{
free(base_path);

return CARDANO_ERROR_NOT_IMPLEMENTED;
return result;
}

result = cardano_blockfrost_http_post(
provider_impl,
base_path,
strlen(base_path),
(byte_t*)json_payload,
json_size,
CARDANO_BLOCKFROST_CONTENT_TYPE_JSON,
&response_code,
&response_buffer);

free(base_path);
free(json_payload);

if (response_code != 200 || result != CARDANO_SUCCESS)
{
cardano_blockfrost_parse_error(provider_impl, response_buffer);

cardano_buffer_unref(&response_buffer);

return CARDANO_ERROR_INVALID_HTTP_REQUEST;
}

cardano_witness_set_t* witness_set = cardano_transaction_get_witness_set(tx);
cardano_witness_set_unref(&witness_set);

if (witness_set == NULL)
{
cardano_buffer_unref(&response_buffer);

return CARDANO_ERROR_INVALID_ARGUMENT;
}

cardano_redeemer_list_t* original_redeemers = cardano_witness_set_get_redeemers(witness_set);
cardano_redeemer_list_unref(&original_redeemers);

if (original_redeemers == NULL)
{
cardano_buffer_unref(&response_buffer);

return CARDANO_ERROR_INVALID_ARGUMENT;
}

result = cardano_blockfrost_parse_tx_eval_response(provider_impl, (char*)cardano_buffer_get_data(response_buffer), cardano_buffer_get_size(response_buffer), original_redeemers, redeemers);

cardano_buffer_unref(&response_buffer);

return result;
}

/* DEFINITIONS ****************************************************************/
Expand Down
53 changes: 53 additions & 0 deletions examples/providers/blockfrost/parsers/blockfrost_parsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,59 @@ cardano_blockfrost_parse_datum(
size_t size,
cardano_plutus_data_t** datum);

/**
* \brief Serializes transaction evaluation parameters and UTXOs to a JSON string.
*
* This function serializes the provided transaction evaluation parameters, including the transaction itself and associated UTXO list, into a JSON string.
*
* \param[in] transaction A pointer to an initialized \ref cardano_transaction_t object representing the transaction to be evaluated.
* This parameter must not be NULL.
* \param[in] utxos A pointer to an initialized \ref cardano_utxo_list_t object representing the UTXOs associated with the transaction.
* This parameter must not be NULL.
* \param[out] json_main_obj_str On success, this will point to the allocated JSON string that contains the serialized data.
* The caller is responsible for freeing this string using `free()` when no longer needed.
* \param[out] json_main_obj_size On success, this will be set to the size of the allocated JSON string, including the null terminator.
*
* \return \ref cardano_error_t indicating the outcome of the operation.
*
* \note The caller must ensure to free the memory allocated for the JSON string when it is no longer needed.
*/
cardano_error_t
cardano_evaluate_params_to_json(
cardano_transaction_t* transaction,
cardano_utxo_list_t* utxos,
char** json_main_obj_str,
size_t* json_main_obj_size);

/**
* \brief Parses a transaction evaluation response from Blockfrost and updates redeemer execution units.
*
* This function parses the JSON response returned by Blockfrost after evaluating a transaction and extracts the updated redeemer execution units.
*
* \param[in] provider A pointer to an initialized \ref cardano_provider_impl_t object representing the Blockfrost provider.
* This parameter must not be NULL.
* \param[in] json A pointer to the JSON string containing the Blockfrost response for the transaction evaluation. This must be a valid JSON string.
* \param[in] size The size of the JSON string, in bytes.
* \param[in] original_redeemers A pointer to an initialized \ref cardano_redeemer_list_t object representing the original redeemers.
* This parameter must not be NULL.
* \param[out] redeemers On success, this will point to a newly created \ref cardano_redeemer_list_t object containing the updated redeemers
* with the applied execution units from the Blockfrost response. The caller is responsible for managing the lifecycle of
* this object, including calling \ref cardano_redeemer_list_unref when it is no longer needed.
*
* \return \ref cardano_error_t indicating the outcome of the operation. Returns \ref CARDANO_SUCCESS if the redeemers were successfully updated,
* or an appropriate error code such as \ref CARDANO_POINTER_IS_NULL if any of the input pointers are NULL, or \ref CARDANO_ERROR_JSON_PARSE
* if the JSON parsing fails.
*
* \note The caller must manage the memory of the \p redeemers object, ensuring it is properly released when no longer needed.
*/
cardano_error_t
cardano_blockfrost_parse_tx_eval_response(
cardano_provider_impl_t* provider,
const char* json,
size_t size,
cardano_redeemer_list_t* original_redeemers,
cardano_redeemer_list_t** redeemers);

#ifdef __cplusplus
}
#endif /* __cplusplus */
Expand Down
Loading

0 comments on commit 63b652d

Please sign in to comment.