rust client libraries to deal with the current cardano mainnet (byron / cardano-sl)

Overview

Build Status Build status Gitter chat

Rust implementation of Cardano primitives, helpers, and related applications

Cardano Rust is a modular toolbox of Cardano’s cryptographic primitives, a library of wallet functions and a future alternative Cardano node implementation written in Rust. It can be used by any third-party to build wallet applications and interact with the Cardano blockchain.

Related repositories

Installation

If this is a new installation: install rust's toolchain.

We support the following states; stable, unstable and nightly.

We also support the wasm32 target.

Building the Library

To build the library, use:

cargo build

Running the tests

To run the tests, use:

cargo test

How to integrate the Rust library in your project

Information will be available soon on crates.io

In the mean time, it is possible to add the project using git submodules:

git submodule add https://github.com/input-output-hk/rust-cardano cardano-deps

And then by adding the following to your Cargo.toml:

[dependencies]
cardano = { path = "cardano-deps/cardano" }
Comments
  • Made block streaming interruptible

    Made block streaming interruptible

    Added internal functionality that allows to interrupt block-streaming when necessary. But it's not used for now. Required for later rollback processing.

    Part of https://github.com/input-output-hk/rust-cardano/pull/693#issuecomment-494574901

    opened by vsubhuman 20
  • `change_value` is calculated wrong

    `change_value` is calculated wrong

    Hello!

    This line of code: https://github.com/input-output-hk/rust-cardano/blob/master/cardano/src/input_selection.rs#L124

    Calculates change_value as (output_value - input_value - estimated_fee). This is wrong, since if my transaction contains 5 coins of inputs, 2 coins of outputs, and fee of 0.17 - then change will be calculated as (2 - 5 - 0.17) = -3.17.

    It should be (input_value - output_value - estimated_fee), so then if will be calculated as (5 - 2 - 0.17) = 2.83 which is the change.

    Currently change does not work, and it's confirmed in this thread: https://forum.cardano.org/t/rust-code-cardano-cli-change-address-fees-not-working-as-expected/15897

    B - Bug D - medium P - high 
    opened by vsubhuman 11
  • Duplication?

    Duplication?

    Hi, there seems to be duplication in the cardano/ code, there is an HDWallet.rs file and also a wallet/ dir containing similar code. Is there a different purpose? Which should one use?

    X - question 
    opened by prographo 9
  • send transaction err: Blockchain protocol error

    send transaction err: Blockchain protocol error

    i got some ada here, and want to send a transaction from code below.

    extern crate cardano;
    extern crate cbor_event;
    extern crate exe_common;
    extern crate rand;
    
    use cardano::address::ExtendedAddr;
    use cardano::bip::bip44::AddrType;
    use cardano::config::ProtocolMagic;
    use cardano::coin;
    use cardano::hdwallet::{DerivationScheme, XPrv};
    use cardano::util::hex;
    use cardano::wallet;
    use cardano::tx::{self, TxoPointer, TxOut, TxInWitness};
    use cardano::{fee::LinearFee, txbuild::{self, TxBuilder, TxFinalized}};
    use cardano::txutils::OutputPolicy;
    use exe_common::network::api::Api;
    use rand::{Rng, os::OsRng};
    
    use std::{collections::BTreeSet, error, fmt, str::FromStr};
    
    fn test_transaction() {
        let addr_1_private_key_hex = "some_hex_private_key";
        let _addr_2_private_key_hex = "some_hex_private_key";
        let _addr_3_private_key_hex = "some_hex_private_key";
        let _addr_1 = "Ae2tdPwUPEZ5zKCZR29WGLMb1hWQPg1mf7RiDrxGbqs89dMMjWd6os74JXR";
        let addr_2 = "Ae2tdPwUPEZL2ibp8BXpn5xuewkbxSPpaw6WccAZBtrZRWX2u6mwBuQkyCi";
        let addr_3 = "Ae2tdPwUPEZ8Nc35XganVXMQR8gQbBrxehGrNJsXQDjPxCdEciYCopcWmiu";
    
    
        let mut peer = get_peer();
    
        let tx_id_str = "4da9c0eced358c4a2e6dc588b821d19e871f817eb05ea35882bf228bb2fb0248";
        let vout_index: u32 = 1;
        let tx_id: tx::TxId = match FromStr::from_str(tx_id_str) {
            Ok(i) => i,
            Err(e) => {
                println!("get txid from string err: {}", e);
                return;
            }
        };
        let input_amount = coin::Coin::new(20000000).unwrap();
    
        let private_key = get_private_key_from_hex(addr_1_private_key_hex);
    
    
        let mut builder = TxBuilder::new();
        let ptr = TxoPointer { id: tx_id, index: vout_index };
        builder.add_input(&ptr, input_amount);
    
        let out_address: ExtendedAddr = FromStr::from_str(addr_2).unwrap();
        let out_amount = coin::Coin::new(10000000).unwrap();
        let out = TxOut { address: out_address, value: out_amount };
        builder.add_output_value(&out);
    
        let fee_algorithm = LinearFee::default();
        let change_address: ExtendedAddr = FromStr::from_str(addr_3).unwrap();
        let _result = builder.add_output_policy(&fee_algorithm, &OutputPolicy::One(change_address)).map_err(Error::ErrorWhenApplyingOutputPolicy);
    
        let tx = builder.make_tx().map_err(Error::CannotBuildTxFromBuilder).unwrap();
        let mut finalized = TxFinalized::new(tx.clone());
    
        let txid = tx.id();
        let witness = TxInWitness::new(ProtocolMagic::default(), &private_key, &txid);
        match finalized.add_witness(witness) {
            Ok(_) => {}
            Err(e) => {
                println!("add witness err: {}", e);
                return;
            }
        }
    
        let tx_aux = finalized.make_txaux().unwrap();
        println!("{}", tx_aux);
    
        match verify(tx_aux.clone(), ProtocolMagic::default()) {
            Ok(_) => {}
            Err(e) => {
                println!("verify transaction err: {}", e);
                return;
            }
        };
    
        println!("sending transaction {}", tx_aux.tx.id());
    
    
        match peer.send_transaction(tx_aux) {
            Ok(r) => println!("{:?}", r),
            Err(e) => {
                println!("send transaction err: {}", e);
                return;
            }
        };
    }
    
    #[allow(dead_code)]
    fn verify(tx_aux: cardano::tx::TxAux, protocol_magic: ProtocolMagic) -> Result<(), cardano::block::verify::Error>
    {
        // check that there are inputs
        if tx_aux.tx.inputs.is_empty() {
            return Err(cardano::block::verify::Error::NoInputs);
        }
    
        // check that there are outputs
        if tx_aux.tx.outputs.is_empty() {
            return Err(cardano::block::verify::Error::NoOutputs);
        }
    
        // check that there are no duplicate inputs
        let mut inputs = BTreeSet::new();
        if !tx_aux.tx.inputs.iter().all(|x| inputs.insert(x)) {
            return Err(cardano::block::verify::Error::DuplicateInputs);
        }
    
        // check that all outputs have a non-zero amount
        if !tx_aux.tx.outputs.iter().all(|x| x.value > coin::Coin::zero()) {
            return Err(cardano::block::verify::Error::ZeroCoin);
        }
    
        // Note: we don't need to check against MAX_COIN because Coin's
        // constructor already has.
    
        // check that none of the outputs are redeem addresses
        if tx_aux.tx.outputs.iter().any(|x| x.address.addr_type == cardano::address::AddrType::ATRedeem) {
            return Err(cardano::block::verify::Error::RedeemOutput);
        }
    
        // TODO: check address attributes?
    
        // verify transaction witnesses
        if tx_aux.tx.inputs.len() < tx_aux.witness.len() {
            return Err(cardano::block::verify::Error::UnexpectedWitnesses);
        }
    
        if tx_aux.tx.inputs.len() > tx_aux.witness.len() {
            return Err(cardano::block::verify::Error::MissingWitnesses);
        }
    
        tx_aux.witness.iter().try_for_each(|in_witness| {
            if !in_witness.verify_tx(protocol_magic, &tx_aux.tx) {
                return Err(cardano::block::verify::Error::BadTxWitness);
            }
            Ok(())
        })?;
    
        // verify that txids of redeem inputs correspond to the redeem pubkey
        for (txin, in_witness) in tx_aux.tx.inputs.iter().zip(tx_aux.witness.iter()) {
            if let tx::TxInWitness::RedeemWitness(pubkey, _) = in_witness {
                if tx::redeem_pubkey_to_txid(&pubkey).0 != txin.id {
                    return Err(cardano::block::verify::Error::WrongRedeemTxId);
                }
            }
        }
    
        Ok(())
    }
    
    fn get_peer() -> exe_common::network::Peer {
        let native_peer = exe_common::config::net::Peer::native("relays.cardano-mainnet.iohk.io:3000".to_string());
        assert!(native_peer.is_native());
        exe_common::network::Peer::new("mainnet".to_string(), "iohk-hosts".to_string(), native_peer, ProtocolMagic::default()).unwrap()
    }
    
    #[derive(Debug)]
    pub enum Error {
        /// happened user attempts to finalize a transaction already
        /// in a finalizing state
        CannotFinalizeAFinalizedTransaction,
    
        CannotAddWitnessesToAnOpenedTransaction,
    
        CannotAddMoreWitnessesThanInputs,
    
        CannotAddInputsToAFinalizedTransaction,
    
        CannotAddOutputToAFinalizedTransaction,
    
        CannotAddChangeToAFinalizedTransaction,
    
        TransactionNotFinalized,
    
        /// when input is duplicated in the transaction
        DoubleSpend,
    
        CannotRemoveInputInputNotFound,
        CannotRemoveOutput,
        CannotRemoveChangeChangeNotFound,
    
        /// TODO: this is temporary only until we can support selection
        /// policy with multiple change addresses.
        ///
        /// In the mean time we need to ask users to remove the previous output
        /// or to keep the current one.
        MoreThanOneChangeAddressIsNotSupportedYet,
    
        ErrorWhenApplyingOutputPolicy(txbuild::Error),
    
        CannotBuildTxFromBuilder(txbuild::Error),
    }
    
    impl fmt::Display for Error {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            match self {
                Error::CannotFinalizeAFinalizedTransaction => write!(f, "Transaction is already in a finalized state"),
                Error::CannotAddWitnessesToAnOpenedTransaction => write!(f, "Transaction is not finalized, finalize the transaction before adding witnesses"),
                Error::CannotAddMoreWitnessesThanInputs => write!(f, "There is already enough witness for the transaction, cannot add more witnesses than inputs."),
                Error::CannotAddInputsToAFinalizedTransaction => write!(f, "Transaction is in a finalized state, cannot add more inputs"),
                Error::CannotAddOutputToAFinalizedTransaction => write!(f, "Transaction is in a finalized state, cannot add more outputs"),
                Error::CannotAddChangeToAFinalizedTransaction => write!(f, "Transaction is in a finalized state, cannot add more change addresses"),
                Error::TransactionNotFinalized => write!(f, "Transaction is not finalized, finalize it first"),
                Error::DoubleSpend => write!(f, "Input already used in the transaction"),
                Error::CannotRemoveInputInputNotFound => write!(f, "Cannot remove input, input not found"),
                Error::CannotRemoveOutput => write!(f, "Cannot remove output, output not found"),
                Error::CannotRemoveChangeChangeNotFound => write!(f, "Cannot remove change, change address not found"),
                Error::MoreThanOneChangeAddressIsNotSupportedYet => write!(f, "Cannot add more than one output address for now, this feature is not yet supported"),
                Error::ErrorWhenApplyingOutputPolicy(_) => write!(f, "Error when applying the output policy utilising the changes"),
                Error::CannotBuildTxFromBuilder(_) => write!(f, "Error when constructing the Tx, invalid data."),
            }
        }
    }
    
    impl error::Error for Error {
        fn cause(&self) -> Option<&error::Error> {
            match self {
                Error::CannotFinalizeAFinalizedTransaction => None,
                Error::CannotAddWitnessesToAnOpenedTransaction => None,
                Error::CannotAddMoreWitnessesThanInputs => None,
                Error::CannotAddInputsToAFinalizedTransaction => None,
                Error::CannotAddOutputToAFinalizedTransaction => None,
                Error::CannotAddChangeToAFinalizedTransaction => None,
                Error::TransactionNotFinalized => None,
                Error::DoubleSpend => None,
                Error::CannotRemoveInputInputNotFound => None,
                Error::CannotRemoveOutput => None,
                Error::CannotRemoveChangeChangeNotFound => None,
                Error::MoreThanOneChangeAddressIsNotSupportedYet => None,
                Error::ErrorWhenApplyingOutputPolicy(ref err) => Some(err),
                Error::CannotBuildTxFromBuilder(ref err) => Some(err),
            }
        }
    }
    
    

    but i got this:

    Tx:
    -> 4da9c0eced358c4a2e6dc588b821d19e871f817eb05ea35882bf228bb2fb0248@0
       Ae2tdPwUPEZL2ibp8BXpn5xuewkbxSPpaw6WccAZBtrZRWX2u6mwBuQkyCi -> 10.000000 ->
       Ae2tdPwUPEZ8Nc35XganVXMQR8gQbBrxehGrNJsXQDjPxCdEciYCopcWmiu -> 9.832006 ->
    
    witnesses: TxWitness([PkWitness(e03ce300a9420757ef52119f957b368eb82557c71133ca366ad70118e7ef5b40410dd5d59e4e3a1e0938d022788024ce2cd2893b18bb7cfd3ecf2b48a87c6619, 1dae87de5890a8fe4372949df93683f1175dfaedbb46942230581d69a7906293bf4f96693da9f30e87c5a1abca9b72c1c99d347fe41c3e1fd9ccb91041120400)])
    
    
    sending transaction eaf96ec8143e787e2f16f0c4fb3e9e69438a2ae90e6ed7b5d513ba4716f79c2f
    send transaction err: Blockchain protocol error
    

    so what's wrong with my code?

    X - help wanted X - question 
    opened by LukeEuler 8
  • cardano-cli uses a fork of dialoguer

    cardano-cli uses a fork of dialoguer

    This is needed since #214 as we needed to allow empty passwords. We can start reusing mainstream dialoguer as soon as mitsuhiko/dialoguer#6 is merged and released.

    P - low 
    opened by NicolasDP 8
  • Upstreaming OBFT stuff

    Upstreaming OBFT stuff

    Upstreaming all the changes we have done in the fork. Includes:

    1. OBFT processing (does not include OBFT signature validation)
    2. Rollback handling
    3. Special new index for epoch-lengths and loose blocks
    4. Changes in epoch pack files to include epoch length and flags for whether it's an EBB epoch or not
    5. Changes in storage to support block-by-height and status endpoints in the bridge ("status" returns information about currently known local and network tips)
    opened by vsubhuman 7
  • Support testnet

    Support testnet

    This updates the genesis hashes and adds support for non-AVVM balances and the NetworkMagic field in addresses.

    It also improves get_block error handling a bit.

    D - medium P - high 
    opened by edolstra 7
  • How to build on mobile for both iOS and Android?

    How to build on mobile for both iOS and Android?

    Hi everyone, Currently we are developing a mobile wallet using React Native for iOS and Android. And we really love to support Cardano in our wallet. Please let us know which is the better way:

    1. Run cardano wasm binding for JavaScript on React Native. (We tried and failed to build, any suggestion?)
    2. Compile rust cardano to native library (iOS and Android); then write bridges of them for React Native.

    Your help is much appreciated, Best regards.

    X - help wanted X - question 
    opened by thangchq-ibl 7
  • More pretty printer features

    More pretty printer features

    implementing aux requests noted in a comment in #90; also see commit messages

    • [x] add color to previous_hash (field of BlockHeader)
    • [x] add color to block_signature (field of Consensus)
    • [x] extend the AST to allow Val::List<Vec<Value>>, use it for lists like transactions and the long list in genesisblocks
    • [x] implement Pretty for genesis blocks (use same approach as blockchain::normal::Block implementations)

    main block

    image

    genesis block

    image

    opened by ghost 7
  • chain-storage: Get rid of excessive boxing and dynamism

    chain-storage: Get rid of excessive boxing and dynamism

    Remove the boxed closures and dynamic trait objects. The BlockStore trait loses object safety, but it should never have required it.

    get_path_to_nth_accessor is removed from the trait methods and turned into a free helper fn for_path_to_nth_accessor.

    opened by mzabaluev 6
  • Utxo storage

    Utxo storage

    net_sync() now verifies blocks and writes the utxo state at the end of each epoch to disk to epoch/<N>/utxos. Rather than storing a full dump of the utxo state at the start of each epoch, we store deltas relative to some parent epoch, where the parent is selected such that each full chain has O(lg epoch) deltas. This reduces storage from 5.1 GiB to 356 MiB for the current mainnet (73 epochs).

    I moved the genesis data from cardano-cli to exe-common, since cardano-http-bridge now needs it to sync.

    opened by edolstra 6
Owner
Input Output
Input Output
Cardano Command Line Interface (CLI) (Deprecated)

Deprecated Note: This repository implements supports for Cardano Byron, and will not be updated to works on Cardano Shelley and further. cardano-cli T

Input Output 87 Oct 9, 2022
Coinbase pro client for Rust

Coinbase pro client for Rust Supports SYNC/ASYNC/Websocket-feed data support Features private and public API sync and async support websocket-feed sup

null 126 Dec 30, 2022
Rust Ethereum 2.0 Client

Lighthouse: Ethereum 2.0 An open-source Ethereum 2.0 client, written in Rust and maintained by Sigma Prime. Documentation Overview Lighthouse is: Read

Sigma Prime 2.1k Jan 1, 2023
Reference client for NEAR Protocol

Reference implementation of NEAR Protocol About NEAR NEAR's purpose is to enable community-driven innovation to benefit people around the world. To ac

NEAR 2k Dec 29, 2022
The Parity Bitcoin client

The Parity Bitcoin client. Gitter Installing from source Installing the snap Running tests Going online Importing bitcoind database Command line inter

Parity Technologies 714 Dec 21, 2022
A Rust library for working with Bitcoin SV

Rust-SV A library to build Bitcoin SV applications in Rust. Documentation Features P2P protocol messages (construction and serialization) Address enco

Brenton Gunning 51 Oct 13, 2022
Custom Ethereum vanity address generator made in Rust

ethaddrgen Custom Ethereum address generator Get a shiny ethereum address and stand out from the crowd! Disclaimer: Do not use the private key shown i

Jakub Hlusička 153 Dec 27, 2022
The new, performant, and simplified version of Holochain on Rust (sometimes called Holochain RSM for Refactored State Model)

Holochain License: This repository contains the core Holochain libraries and binaries. This is the most recent and well maintained version of Holochai

Holochain 737 Dec 28, 2022
DEPRECATED. The Holochain framework implemented in rust with a redux style internal state-model.

Holochain-rust Travis: Circle CI: Codecov: License: This code is loosely based on the previous Golang prototype. Code Status: This Rust version is alp

Holochain 1k Jan 3, 2023
IBC modules and relayer - Formal specifications and Rust implementation

ibc-rs Rust implementation of the Inter-Blockchain Communication (IBC) protocol. This project comprises primarily four crates: The ibc crate defines t

Informal Systems 296 Jan 4, 2023
A Rust implementation of BIP-0039

bip39-rs A Rust implementation of BIP0039 Changes See the changelog file, or the Github releases for specific tags. Documentation Add bip39 to your Ca

Infincia LLC 49 Dec 9, 2022
Official Rust implementation of the Nimiq protocol

Nimiq Core implementation in Rust (core-rs) Rust implementation of the Nimiq Blockchain Core Nimiq is a frictionless payment protocol for the web. Thi

Nimiq 72 Sep 23, 2022
Rust implementation of Zcash protocol

The Parity Zcash client. Gitter Blog: Parity teams up with Zcash Foundation for Parity Zcash client Installing from source Installing the snap Running

Parity Technologies 183 Sep 8, 2022
Tendermint in Rust!

tendermint.rs Tendermint in Rust with TLA+ specifications. Tendermint is a high-performance blockchain consensus engine for Byzantine fault tolerant a

Informal Systems 439 Jan 1, 2023
A Rust library for generating cryptocurrency wallets

Table of Contents 1. Overview 2. Build Guide 2.1 Install Rust 2.2a Build from Homebrew 2.2b Build from Crates.io 2.2c Build from Source Code 3. Usage

Aleo 554 Dec 31, 2022
Rust port of the Terry Davis' (RIP) "god says" program

RIP Terry A. Davis 1969-2018 god says Rust port of the programmer Terry Davis' "god says" (AKA GodSpeaks) program. Terrence Andrew Davis (December 15,

Orhun Parmaksız 54 Dec 26, 2022
Implementation of the Kademlia DHT protocol in Rust

kademlia-dht Simple implementation of the Kademlia DHT protocol in Rust with state dumping features for educational purposes (not production-ready). T

Leonardo Folgoni 18 Sep 24, 2022
Collection of Key Derivation Functions written in pure Rust

RustCrypto: Key Derivation Functions Collection of Key Derivation Functions (KDF) written in pure Rust. Supported Algorithms Algorithm Crate Crates.io

Rust Crypto 44 Dec 25, 2022
Cryptocurrencies trend-following trading bot sandbox written in Rust.

Trend trading bot Experiments repo about (crypto) trend trading. By "trend" I mean trading following the trend using technical indicators (vs other ki

Julien 6 Oct 2, 2022