NavioBlsct
  • API Reference
  • Installation
  • Memory Management
  • Return Value Layout
  • navio-core ↗
Search Results for

    Memory Management

    NavioBlsct is a SWIG binding over libblsct. The native library allocates memory for opaque handles it returns. That memory is not managed by the .NET garbage collector.

    Rule: match the helper

    Every native handle must be released with the matching helper. Most BlsctRetVal.value handles use blsct.free_obj(val), while BlsctCTxRetVal and BlsctAmountsRetVal have dedicated release functions.

    Use blsct.free_obj(val) for heap-allocated opaque objects:

    var rv = blsct.gen_scalar(12345);
    var scalar = blsct.cast_to_scalar(rv.value);
    // ... use scalar ...
    blsct.free_obj(rv.value);
    

    Typed delete helpers

    Some aggregate objects have dedicated delete calls — use these instead of free_obj:

    Object type Free call
    uint64 vector blsct.delete_uint64_vec(vec)
    Range proof vector blsct.delete_range_proof_vec(vec)
    Amount recovery req vec blsct.delete_amount_recovery_req_vec(vec)
    String map blsct.delete_string_map(map)
    Token info blsct.delete_token_info(val)
    Unsigned input blsct.delete_unsigned_input(val)
    Unsigned output blsct.delete_unsigned_output(val)
    Unsigned transaction blsct.delete_unsigned_transaction(tx)
    Signed transaction (CTx) blsct.delete_ctx(val)
    Tx hex vector blsct.delete_tx_hex_vec(vec)
    AmountsRetVal blsct.free_amounts_ret_val(rv)

    delete_unsigned_input and delete_unsigned_output are for standalone objects. When an input or output is added to an unsigned transaction via add_unsigned_transaction_input/output, the data is copied. The original unsIn/unsOut must still be freed by the caller, and the transaction itself must be freed via delete_unsigned_transaction.

    Pattern: try/finally

    var rvSeed = blsct.gen_scalar(12345);
    try
    {
        var seed = blsct.cast_to_scalar(rvSeed.value);
        var childKey = blsct.from_seed_to_child_key(seed);
        // ... use childKey (scalars derived from childKey share its lifetime) ...
    }
    finally
    {
        blsct.free_obj(rvSeed.value);
    }
    

    Safe no-op

    Passing null or a zero-handle to free_obj is always safe.

    Values that do NOT need freeing

    Cast wrappers

    cast_to_* methods return a typed wrapper that points to the same native pointer as the original RetVal.value. Freeing both causes a double-free.

    var rv = blsct.gen_random_point();
    var point = blsct.cast_to_point(rv.value);  // same native pointer
    // ... use point ...
    blsct.free_obj(rv.value);  // correct — frees the native object
    // DO NOT call blsct.free_obj(point) — double-free
    

    Apply this rule to all cast_to_* variants: cast_to_scalar, cast_to_point, cast_to_pub_key, cast_to_tx_in, cast_to_tx_out, cast_to_token_id, cast_to_sub_addr, cast_to_dpk, cast_to_signature, cast_to_script, cast_to_out_point, cast_to_sub_addr_id, cast_to_key_id, cast_to_range_proof, cast_to_vector_predicate, cast_to_uint256, cast_to_cscript, cast_to_const_char_ptr, etc.

    Rule: free the RetVal.value once. Never free the cast wrapper.

    Derived scalars from the same source

    Scalars derived from a BlsctRetVal.value via cast_to_scalar share the same native allocation:

    var rvDestPk = blsct.gen_scalar(92);
    var destPkScalar = blsct.cast_to_scalar(rvDestPk.value);  // same pointer
    var destPk = blsct.scalar_to_pub_key(destPkScalar);       // NEW allocation — must free
    blsct.free_obj(rvDestPk.value);  // frees destPkScalar's native memory too
    blsct.free_obj(destPk);          // correct — destPk is a separate allocation
    

    Ownership notes

    sign_unsigned_transaction reads the unsigned transaction but does not delete it. The caller must still call delete_unsigned_transaction(unsTx) after signing.

    add_unsigned_transaction_input/output copy the input/output into the transaction. The original unsIn/unsOut must still be freed by the caller (via delete_unsigned_input/delete_unsigned_output).

    Function Ownership Caller cleanup
    sign_unsigned_transaction reads, no transfer delete_unsigned_transaction(unsTx)
    add_unsigned_transaction_input copies unsIn delete_unsigned_input(unsIn)
    add_unsigned_transaction_output copies unsOut delete_unsigned_output(unsOut)

    Returned string pointers

    Functions like serialize_*, buf_to_malloced_hex_c_str, and cast_to_const_char_ptr return heap-allocated char* strings. Free them with blsct.free_obj(val):

    var rvSigned = blsct.sign_unsigned_transaction(unsTx);
    var signedHex = blsct.cast_to_const_char_ptr(rvSigned.value);
    // ... use signedHex ...
    blsct.free_obj(rvSigned.value);  // frees the char*
    
    • Edit this page
    In this article
    Back to top NavioBlsct — C# Bindings for libblsct. Copyright The Navio Developers.