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
Ethereum key tool - Lightweight CLI tool to deal with ETH keys written in rust

ekt - Etherum Key Tool ekt is a lightweight tool to generate ethereum keys and addresses. Installation Either clone it and run it with cargo or instal

null 5 May 8, 2023
Marinde Anchor-Based, first on mainnet, liquid-staking-program and mSOL->SOL swap pool

marinade-anchor Marinade-finance liquid staking program for the Solana blockchain Audits & Code Review Kudelski Security: https://marinade.finance/Kud

Marinade.Finance 42 Dec 11, 2022
Rust-native building blocks for the Cardano blockchain ecosystem

Pallas Rust-native building blocks for the Cardano blockchain ecosystem. Introduction Pallas is an expanding collection of modules that re-implements

null 78 Dec 6, 2022
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
rust-native-tls — Bindings for native TLS libraries

rust-native-tls Documentation An abstraction over platform-specific TLS implementations. Specifically, this crate uses SChannel on Windows (via the sc

Steven Fackler 371 Jan 8, 2023
Collect libraries and packages about cryptography in Rust.

Awesome Cryptography Rust Collect libraries and packages about cryptography in Rust. Collection Library Symmetric Public-key / Asymmetric One-way Hash

Rust Cryptography Community 282 Dec 25, 2022
Rust starter project for building CLI and libraries, with great CI

Using the starter project: find where bumblefoot is and replace it with the name of your project. $ rg bumblefoot This is a dual library and binary pr

Rusty Ferris Club 19 Nov 19, 2022
Automated security testing for open source libraries and applications.

autovet continuously searches for security breaches in open source libraries and applications. Recently processed packages package version channel las

null 5 Aug 23, 2022
A collection of libraries to be implemented for Automated Market Makers built in Sway.

?? ?? Executor AMM ?? ?? The Executor AMM is a reference implementation of Concentrated Liquidity in Sway. To run on the FuelVM many modifications had

Sway Libraries 54 Dec 21, 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 6, 2023
Rust client to Opensea's APIs and Ethereum smart contracts

opensea.rs Rust bindings & CLI to the Opensea API and Contracts CLI Usage Run cargo r -- --help to get the top level help menu: opensea-cli 0.1.0 Choo

Georgios Konstantopoulos 226 Dec 27, 2022
Simple template for building smart contract(Rust) and RPC Client(web3.js) on Solana (WIP) ⛏👷🚧⚠️

Solana BPF Boilerplate Simple template for building smart contract(Rust) and RPC Client(web3.js) on Solana This boilerplate provides the following. Si

ono 6 Jan 30, 2022
An encrypted multi client messaging system written in pure Rust

?? Preamble This is a pure Rust multi-client encrypted messaging system, also known as Edode's Secured Messaging System. It is an end-to-end(s) commun

Edode 3 Sep 16, 2022
Rust implementation of the i2p client/server/router protocols

ri2p Rust implementation of the i2p client/server/router protocols Status Common Commands cargo build: Builds the ri2p binary cargo run: Runs the ri2p

Christopher Bilger 8 Nov 25, 2022
In addition to encryption library, pure RUST implementation of SSH-2.0 client protocol

In addition to encryption library, pure RUST implementation of SSH-2.0 client protocol

陈年旧事。 73 Jan 1, 2023
Next-generation implementation of Ethereum protocol ("client") written in Rust, based on Erigon architecture.

?? Martinez ?? Next-generation implementation of Ethereum protocol ("client") written in Rust, based on Erigon architecture. Why run Martinez? Look at

Arthur·Thomas 23 Jul 3, 2022
A Rust client for Flashbots Relay.

flashbots-relay-rs Rust client for interacting directly with the Flashbots Relays. How does it work ? Using a client from the reqwest crate, you can u

Luca G.F. 16 Jun 22, 2022
Ethereum JSON-RPC multi-transport client. Rust implementation of web3 library

Ethereum JSON-RPC multi-transport client. Rust implementation of web3 library. ENS address: rust-web3.eth

Tomasz Drwięga 1.2k Jan 8, 2023