Giter VIP home page Giter VIP logo

emurgo / cardano-serialization-lib Goto Github PK

View Code? Open in Web Editor NEW
228.0 15.0 124.0 3.73 MB

This is a library, written in Rust, for serialization & deserialization of data structures used in Cardano's Haskell implementation of Alonzo along with useful utility functions.

License: Other

JavaScript 0.80% TypeScript 1.59% Rust 95.41% Shell 0.03% HTML 2.02% CSS 0.15%
cardano cddl shelley blockchain

cardano-serialization-lib's Introduction

cardano-serialization-lib's People

Contributors

alessandrokonrad avatar bravo-kernel avatar canttouchdis avatar dependabot-preview[bot] avatar dependabot[bot] avatar ecioppettini avatar fell-x27 avatar gclaramunt avatar gostkin avatar katomm avatar kodemill avatar lisicky avatar longngn avatar marcelklammer avatar mitchycola avatar nebyt avatar nicolasdp avatar novadev94 avatar ozgrakkurt avatar pedromtcosta avatar rodrigc avatar rooooooooob avatar rvcas avatar sebastiengllmt avatar stackchain avatar trevor-crypto avatar v-almonacid avatar vincenthz avatar vsubhuman avatar ypopovych avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cardano-serialization-lib's Issues

Building Ipv4 returns other values than introduced

When running this code I expect that the second log shows me 127.0.0.1 as I inserted it at the first line. Instead of this, it shows me 127.

const ipv4 = CardanoWasm.Ipv4.new(Buffer.from("127.0.0.1", "utf-8"));
console.log(Buffer.from(ipv4.to_bytes()).toString("hex"));
const [decoded] = decodeAllSync(ipv4.to_bytes());
console.log(decoded.toString("utf-8"));

Also, I decoded the first log value on cbor.me and returned 127. too

Error: memory access out of bounds

We use the @emurgo/cardano-serialization-lib-nodejs package to build and sign transactions, and after a while, we will get this error:

Error: memory access out of bounds, Stack: RuntimeError: memory access out of bounds
at alloc::vec::Vec<T>::from_raw_parts::habfae1af1b0e58b9 (wasm-function[2886]:5)
at bignum_from_str (wasm-function[1803]:23)  
at Function.from_str (/secure/signerjs-ada-1.2.0-release/node_modules/@emurgo/cardano-serialization-lib-nodejs/cardano_serialization_lib.js:729:24)   
at Transaction.build (/secure/signerjs-ada-1.2.0-release/node_modules/@tokens/ada/dist/transaction.js:73:46)

transaction.js

import * as CardanoWasm from '@emurgo/cardano-serialization-lib-nodejs';
import * as bech32 from 'bech32';


export default class Transaction {
    build(txData) {
        const {
            vin,
            vout,
            expire_block_height: ttl,
            min_fee_a: minFeeA,
            min_fee_b: minFeeB,
            min_utxo_value: minUtxoValue,
            pool_deposit: poolDeposit,
            key_deposit: keyDeposit,
            to: toAddress,
        } = txData;

        const minFeeABigNum = CardanoWasm.BigNum.from_str(minFeeA);
        const minFeeBBigNum = CardanoWasm.BigNum.from_str(minFeeB);
        const linearFee = CardanoWasm.LinearFee.new(minFeeABigNum, minFeeBBigNum);
        const minUtxoValueBigNum = CardanoWasm.BigNum.from_str(minUtxoValue);
        const poolDepositBigNum = CardanoWasm.BigNum.from_str(poolDeposit);
        const keyDepositBigNum = CardanoWasm.BigNum.from_str(keyDeposit);
        const txBuilder = CardanoWasm.TransactionBuilder.new(linearFee, minUtxoValueBigNum, poolDepositBigNum, keyDepositBigNum);

        minFeeABigNum.free();
        minFeeBBigNum.free();
        linearFee.free();
        minUtxoValueBigNum.free();
        poolDepositBigNum.free();
        keyDepositBigNum.free();

        vin.forEach(({ hash, vout_index, address, amount }) => {
            const byronAddress = CardanoWasm.ByronAddress.from_base58(address);
            const transactionHash = CardanoWasm.TransactionHash.from_bytes(Buffer.from(hash, 'hex'));
            const transactionInput = CardanoWasm.TransactionInput.new(transactionHash, vout_index);
            const amountBigNum = CardanoWasm.BigNum.from_str(amount);
            const value = CardanoWasm.Value.new(amountBigNum);

            txBuilder.add_bootstrap_input(byronAddress, transactionInput, value);

            byronAddress.free();
            transactionHash.free();
            transactionInput.free();
            amountBigNum.free();
            value.free();
        });

        this.vin = vin;

        vout.forEach(({ address, amount }) => {
            let addr;

            try {
                addr = CardanoWasm.ByronAddress.from_base58(address).to_address();
            } catch (err) {
                addr = CardanoWasm.Address.from_bech32(address);
            }

            const amountBigNum = CardanoWasm.BigNum.from_str(amount);
            const value = CardanoWasm.Value.new(amountBigNum);
            const transactionOutput = CardanoWasm.TransactionOutput.new(addr, value);
            txBuilder.add_output(transactionOutput);

            addr.free();
            amountBigNum.free();
            value.free();
            transactionOutput.free();
        });

        txBuilder.set_ttl(ttl);

        let address;
        try {
            address = CardanoWasm.ByronAddress.from_base58(toAddress).to_address();
        } catch (err) {
            address = CardanoWasm.Address.from_bech32(toAddress);
        }

        txBuilder.add_change_if_needed(address);
        address.free();

        this.txBuilder = txBuilder;

        return this;
    }
}

Please help me find why do we encounter such a problem? Is there a problem with the code?

Thanks!!

Add to_json on transactions

I'm not sure what are the implications of doing this (maybe for some reason it gets really ugly), but the old Byron WASM bindings has a to_json function on transactions. This was very useful for quick debugging.

Derivate Bip39 chain code

Hi,

I try to create an HD wallet from entropy but the result given by the lib is different from cardano-cli.

echo planet scout acquire actress dutch crisp relax slender ignore voice title control sword dumb silent good toy knee olympic burger interest slow attract result | cardano-address key from-recovery-phrase Shelley | cardano-address key child 1852H/1815H/0H

> acct_xsk19rzvtxa3ep32sr0c5j37rtn8k6clv5qwvndmexfdyl48s5mqnetk0z76x7ck52e599tl0wrqwpwfejynf8ljmxxkchecw0upx57aczjlzw5ekc4qde0a0s3d4a2k3x4vq5uk65a6r0v22cklp0w0hr8zssc4882d
import { mnemonicToEntropy } from 'bip39';
let harden = function (num) {
  return 0x80000000 + num;
}

const entropy = mnemonicToEntropy(
    "planet scout acquire actress dutch crisp relax slender ignore voice title control sword dumb silent good toy knee olympic burger interest slow attract result"
  )

  const rootKey = wasm.Bip32PrivateKey.from_bip39_entropy(
    Buffer.from(entropy, 'hex'),
    Buffer.from(''),
  );

  let account = rootKey
    .derive(harden(1852))
    .derive(harden(1815))
    .derive(harden(0))
    .to_bech32();

// xprv19rzvtxa3ep32sr0c5j37rtn8k6clv5qwvndmexfdyl48s5mqnetk0z76x7ck52e599tl0wrqwpwfejynf8ljmxxkchecw0upx57aczjlzw5ekc4qde0a0s3d4a2k3x4vq5uk65a6r0v22cklp0w0hr8zssnyq900

the prefix is different but more importantly the last bytes are different.

...c4882d โ‰  ...nyq900

I then try to read the bech32 given by the lib and Cardano-cli complain that invalid chars are present:

user error (Bech32 error: Invalid character(s) in string:
acct_xsk19rzvtxa3ep32sr0c5j37rtn8k6clv5qwvndmexfdyl48s5mqnetk0z76x7ck52e599tl0wrqwpwfejynf8ljmxxkchecw0upx57aczjlzw5ekc4qde0a0s3d4a2k3x4vq5uk65a6r0v22cklp0w0hr8zssnyq900) 

Add support to calculate Minimum UTxO

I'm 1-month old in Cardano, but since the introduction of multi-assets I've noticed that the calculation of Minimum UTxO got a little complex. (Correct me if I'm wrong)

I found this doc explanation on how to calculate the Minimum ADA:
https://github.com/input-output-hk/cardano-ledger-specs/blob/master/doc/explanations/min-utxo.rst

After checking the Doc, I think it'll be very helpful to have a function to calculate the Minimum ADA of a UTxO with X-Amount of Y-types of assets.

Or maybe there's already an easy way of directly calculating it and I haven't noticed it? ๐Ÿ˜…

Consume from C

I'm not a rust developer. I have only messed with rust in a hobby fashion.

I want the ability to consume the rust binary from a C based application. Since this library compiles using the #[wasm_bindgen], can I just create bindings using #[no_mangle] and adding extern "C" to the method signatures. The intention is to use it with FFI

as_bytes() method returns empty Uint8Array

Hi.
I'm using @emurgo/cardano-serialization-lib-nodejs package, v^6.0.0.

Code:
const bip32PrivateKey = CardanoWasm.Bip32PrivateKey.from_bech32('my-private-key-to-witness-tx-in-bech32');
const bytesKey = bip32PrivateKey.to_raw_key().as_bytes();

The problem is in one of my projects (require syntax, pure js) the part bip32PrivateKey.to_raw_key().as_bytes() behaves as expected giving me non empty Uint8Array.
But in my other project (import syntax, typescript) the same lines give me empty Uint8Array.

I tried to use require syntax and typescript in both and that didn't helped, so I'm out of ideas.
Do you have any idea why the same code behaves differently?

Remove dependency on Jormungandr

Currently, our library re-uses some cryptography for Jormungandr. We do that by just adding the whole Jormungandr library as a dependency and this bloats the binary size quite a bit. We should extract the functionality we need and then remove this dependency

Generate a legacy Daedalus key from recovery phrase

Cardano contains two ways to derive child keys: v1 for Daedalus addresses and v2 for everything else.

This functionality was provided by an old WASM library for Cardano (https://www.npmjs.com/package/cardano-wallet), but we didn't add it to our library.

I'm not sure if we need to introduce new dependencies to add this functionality, but it may be useful to have a derive function added to LegacyDaedalusPrivateKey along with a from_bip39_entropy function.

We can assume purpose is 44' and cointype is 1815' for Dd addresses.

offset is out of bounds: getUint8Memory0().set(arg, ptr / 1)

Hi, if I loop through addresses with a function shown below, eventually (after about 2880000 iterations) I get an error offset is out of bounds: getUint8Memory0().set(arg, ptr / 1):

function computeAddress(ExtendedPublicKey, index, phrase) {
  let rootKey = csl.Bip32PublicKey.from_bytes(
    Buffer.from(
      ExtendedPublicKey.publicKeyHex +
          ExtendedPublicKey.chainCodeHex,
      "hex"
    )
  ); 

  let paymentKey = rootKey
    .derive(0) // visible address
    .derive(index) // looping through to see what address I'm getting at any given index
    .to_raw_key();

  let stakeKey = rootKey
    .derive(2) // staking chain
    .derive(0) // fixed value for staking keys for given account
    .to_raw_key();

  let addr = csl.BaseAddress.new(
    1, 
    csl.StakeCredential.from_keyhash(paymentKey.hash()),
    csl.StakeCredential.from_keyhash(stakeKey.hash())
  ).to_address();

  console.log(addr.to_bytes());
  console.log(addr.to_bech32());

  incomingAddr = null
  addr = null
  stakeKey = null
  paymentKey = null
  rootKey = null
}
node_modules\@emurgo\cardano-serialization-lib-nodejs\cardano_serialization_lib.js:153
    getUint8Memory0().set(arg, ptr / 1);
                      ^

RangeError: offset is out of bounds
    at Uint8Array.set (<anonymous>)
    at passArray8ToWasm0

I tried nulling all vars to get the garbage collector to mop up unused memory, but that doesn't help. Any suggestions you might offer?

Thanks in advance!

Implement CIP5

CIP5 defines what prefixes should be use for which object.

Now that #61 and #53 are merged, we should be able to add the bech32 version of all the relevant types.

FeeTooSmallUTxO when multiple inputs are used

I have code to create and broadcast a transaction which works when I have a single UTXO input.

But when I have 3, it fails with FeeTooSmallUTxO. I'm using add_change_if_needed at the end - I believe this should handle it, shouldn't it? There is no metadata and only 1 witness.

I've tried checking the output of min_fee after each step:

  1. Empty transaction: min_fee() returns 156173.
  2. After add_output: min_fee() returns 159033.
  3. After first add_key_input: min_fee() returns 165149, add_change_if_needed() fails with Insufficient input in transaction (as expected).
  4. After second add_key_input: min_fee() returns 166733, add_change_if_needed() fails with Insufficient input in transaction (as expected).
  5. After third add_key_input: min_fee() returns 168317, add_change_if_needed() succeeds.
  6. Now after add_change_if_needed() ran successfully, min_fee() returns 169945, and get_fee_if_set() returns the same.

I'm adding one witness with make_vkey_witness at the end.

The final signed transaction hex is:

83a40083825820016da679e8757a0ba17e4de79fd3e7677fdfb38d9853d5a6fc6106498e3c8d6b00825820731b9db933db3d2ca5473308873dd17dd325613d413322e6f3ac7f68ffa696590082582036440d14605cc9c718e842353dff013a8024c93f8801dd56694908086c5a8cdf00018282583901d45dfb79d0dc15f7d6620fb3ab22a167bca6e023d17550ae70dd267b4b745cce6e3bbbf16ab2fb0840f233eb042b45a251d1a9b37e78e9d91a004c4b4082581d6109b387c3a5c2e7035e708034018994fd37a1b918d76104418b9f5fde1a00900f1f021a000297d9031a01c8ba76a10081825820edc832195b4478e51daac85fa6b2b13e8aafcfa1818baded22cf7adde4ea345c58407b62300a7ace3a1c0e9aa6cc5790882767acb63d74564721d690ffdd147f6abe39ab56964432d66b4759406fc2dfbde1c8d96e20624c106d9ffd2c3634c9da07f6

(Is there some tool to deserialize a raw TX like that? I didn't find any.)

But broadcasting this transaction fails:

GraphqlError: Shelley command failed: transaction submit Error: Error while submitting tx: ApplyTxError [LedgerFailure (UtxowFailure (UtxoFailure (FeeTooSmallUTxO (Coin 170033) (Coin 169945))))]

Add VRF key generation

Our library doesn't handle VRF keys at the moment, but it would would be useful for pool operators who want to use our library

You can find more information about what implementation is used by the Haskell codebase, etc. here: IntersectMBO/cardano-base#100

Different between poolID and pool_keyhash

Hi all,

I don't know the difference between poolID and pool_keyhash. How to create a new pool_keyhash from poolID to make a new delegation transaction.
Pleae help to take a look. Thank you so much

Derivation scheme (possible) inconsistency for 12-word mnemonics

I noticed for test case

expect(baseAddr.to_address().to_bech32()).to.eq('addr1qz2fxv2umyhttkxyxp8x0dlpdt3k6cwng5pxj3jhsydzer3jcu5d8ps7zex2k2xt3uqxgjqnnj83ws8lhrn648jjxtwqcyl47r');

That the expected result is obtained using the V2 derivation scheme (probably as a result of having the scheme hardcoded here:

let new_key = key.0.derive(DerivationScheme::V2, index);
), although AFAIK, 12-word mnemonics belong to legacy Daedalus wallets which were using V1 scheme and AFAIK Daedalus does not support derivation of base addresses for them, prompting the users to migrate to shelley-ready wallets based on 15/24 word mnemonics.

Is this derivation scheme "inconsistency" just a matter of the tests or are there actually 12-word mnemonics which we should be using V2 derivation scheme for?

Add KES key generation

It's unclear what we need to do to get KES generation working well in our library.

There exists a Rust KES implementation by IOHK (https://github.com/input-output-hk/kes-mmm-sumed25519) but I'm not sure if it's compatible with the Haskell implementation of Cardano.

To quote IOHK on this matter:

Duncan Coutts

We are not using the Rust KES impl. We've had the one we are using audited, but we did want to compare to the rust one as a reference.
We spent some time trying to compare the two impls but got to a bit of an impasse. There are two Rust impls, the "naive recursive" one and the "production" one. There are no Haskell bindings for the recursive one so it makes it hard to compare. It appears however that the recursive one at least would produce the same size output as we expect (and as expected from the paper).

Vincent Hanquez

Thereโ€™s no difference of โ€œalgorithmsโ€ between the two rust versions above. Case in point, the naive version is used to KAT test the production version.

React TextDecoder error

TypeError: TextDecoder is not a constructor
(anonymous function)
node_modules/@emurgo/cardano-serialization-lib-nodejs/cardano_serialization_lib.js:26

I get this error after installing in react the 4 serialisation libraries in a React app.

yarn add @emurgo/cardano-serialization-lib-asmjs
yarn add @emurgo/cardano-serialization-lib-browser
yarn add @emurgo/cardano-serialization-lib-nodejs
yarn add @emurgo/react-native-haskell-shelley

trying to convert addr1 into stake1 with this:

const cardano = require('@emurgo/cardano-serialization-lib-nodejs')
// import {BaseAddress} from '@emurgo/cardano-serialization-lib-browser'

export default function stake1_from_addr1() {
	// Build base address
	let addr = cardano.Address.from_bech32('addr1q9whnenj7f83wvqtqw756drkd85pynz2hxrxz8szd4k5yd9uxl00u6yewtjluzse4x8mpd9x0k6x6zjmtsxtaamrtyjq7f78vk')
	let base_addr = cardano.BaseAddress.from_address(addr)

	// Extract stake credential               
	let stake_cred = base_addr.stake_cred()

	// Log hex address
	console.log(Buffer.from(stake_cred.to_keyhash().to_bytes().buffer).toString("hex"))
	// bc37defe689972e5fe0a19a98fb0b4a67db46d0a5b5c0cbef7635924
	// same address in hex format.

	// Build reward address (add 0xe1 prefix to 28 last bytes of stake credential one) 
	let reward_addr_bytes = new Uint8Array(29)                                          
	reward_addr_bytes.set([0xe1], 0)                                                
	reward_addr_bytes.set(stake_cred.to_bytes().slice(4, 32), 1)           
	let reward_addr = cardano.RewardAddress.from_address(cardano.Address.from_bytes(reward_addr_bytes))

	// Log bech32 address         
	console.log(reward_addr.to_address().to_bech32())
	// stake1ux7r0hh7dzvh9e07pgv6nraskjn8mdrdpfd4cr977a34jfquwqrj9
}

Issues with @emurgo/cardano-serialization-lib-nodejs

Using webpack 5.24.4

  1. Error: Cannot find module 'util' is thrown when loading. Commenting out const { TextDecoder } = require(String.raw); fixes the issue, but is there a way to achieve this without modifying the code myself?

  2. path set on const path = require('path').join(__dirname, 'cardano_serialization_lib_bg.wasm'); yields incorrect path as this does not lead to node_modules directory

  3. WebAssembly.Compile is disallowed on the main thread, if the buffer size is larger than 4KB. Use WebAssembly.compile, or compile on a worker thread is thrown. This is fixed only when I replace

const wasmInstance = new WebAssembly.Instance(wasmModule, imports);
wasm = wasmInstance.exports;
module.exports.__wasm = wasm;

with

WebAssembly.compile(bytes).then((
    mod => {
        WebAssembly.instantiate(mod, imports).then(
            wasmInstance => {
                wasm = wasmInstance.exports;
                module.exports.__wasm = wasm;        
            }
        );
    }
));

bug: can't spend byron UTxO on the MC4

UTxO

$ cardano-cli shelley query utxo --testnet-magic 42 --address Ae2tdPwUPEZEY1CHq8oQxLm523fWkN7V7AK2WKiQTi8thiA9qZJpsEQgn95

                           TxHash                                 TxIx        Lovelace
----------------------------------------------------------------------------------------
62c337c54795149010a805ee42eb8554d8db5c327d9d88e0b83529fe42fde57b     0          10000000

Code

#![allow(unused_variables, unused_imports)]

use cardano_serialization_lib::{self as adalib, crypto, utils};
use cbor_event::{self as cbor};

fn main() {
    let xprv = "48ca6b8fa0d8fdc3f2c028a3c0a8bac6b9e91546b337ca911c2fbf1798c894467c7782535b50d1f0242d7aeecb8c197d0df062baf5892b5c800233d7ba11509ff1720f17e7573e467a1a582b0b0c4d84d8c638448168996310f69341c94b87e1";
    let xprv = hex::decode(xprv).unwrap();
    let xprv = crypto::Bip32PrivateKey::from_bytes(xprv.as_slice()).unwrap();
    let xpub = xprv.to_public();

    let txid = "62c337c54795149010a805ee42eb8554d8db5c327d9d88e0b83529fe42fde57b";
    let txid = crypto::TransactionHash::from_bytes(hex::decode(txid).unwrap()).unwrap();

    let input = adalib::TransactionInput::new(&txid, 0);
    let mut inputs = adalib::TransactionInputs::new();
    inputs.add(&input);

    let receiver = "addr1v9phtfkrjl5uv2l4wjulx7a7yhl5ujs6czvcyytl99k855sy29vsy";
    let receiver = adalib::address::Address::from_bech32(receiver).unwrap();
    let output = adalib::TransactionOutput::new(&receiver, &utils::Coin::new(9000000));
    let mut outputs = adalib::TransactionOutputs::new();
    outputs.add(&output);

    let txbody =
        adalib::TransactionBody::new(&inputs, &outputs, &utils::Coin::new(1000000), 226400);

    let tosign = utils::hash_transaction(&txbody);
    let byron = adalib::address::ByronAddress::from_icarus_key(&xpub, 1);
    let witness = utils::make_icarus_bootstrap_witness(&tosign, &byron, &xprv);
    let mut witness_set = adalib::TransactionWitnessSet::new();

    let mut bootstrap_witness = crypto::BootstrapWitnesses::new();
    bootstrap_witness.add(&witness);
    witness_set.set_bootstraps(&bootstrap_witness);
    let newtx = adalib::Transaction::new(&txbody, &witness_set, None);
    println!("{}", hex::encode(cbor::cbor!(newtx).unwrap()));
}

result

83a4008182582062c337c54795149010a805ee42eb8554d8db5c327d9d88e0b83529fe42fde57b00018182581d614375a6c397e9c62bf574b9f37bbe25ff4e4a1ac09982117f296c7a521a00895440021a000f4240031a00037460a102818458208621b4ed226c33282bea86f495aa589349280f739032f9cdb847e393a6bd32e7584071f410a3a4d684c4a0dcdc451b1a647a6fd29f708e10d879e5770ebeea4b25c76e493628faa0bb03f90cb8bb2d9fdf284158bc64d91a00f79f2705669f65160e5820f1720f17e7573e467a1a582b0b0c4d84d8c638448168996310f69341c94b87e141a0f6

send to cardano-submit-api and get a error

CBOR failed with error: DeserialiseFailure 231 "expected bytes"

Question - how to sign the transactions

Hi!

Just would like to get some help - is it possible to use this lib for signing transactions?
I saw example about transaction build.

Thanks in advance!

Fix key generation function

Functions like generate_ed25519_bip32 are broken in the same way they were broken in Jormungandr input-output-hk/js-chain-libs#59

I think the curve25519-dalek package was updated maybe 1-2 months ago and it may have fixed this issue, but I've never bothered updating the dependency in our serialization lib because it would be kind of ugly to do. Ugly because the dependency on curve25519-dalek exists inside Jormungandr and instead of copying the cryptography into our codebase, we instead made Jormungandr a dependency.

To bump the version, you would have to change it in Jormungandr and fix all the issues in Jormungandr before then upgrading our lib so it's probably easier to tackle #47 first

Building Transaction with Assets to Mint

As far as I know, in all cases inputs + withdrawals - outputs + refund - deposit - min fee should result in 0. But when minting comes into play, this balance breaks.

Using cardano-serialization-lib, the command set_mint() is available after you've already built the TransactionBody, in my opinion should be done on the TransactionBuilder, so whenever you call the add_change_if_needed() it correctly calculates everything to set the correct fee.

Taking this into consideration, as of of today, to successfully mint I need to manually calculate the fee by:

  1. Build the TransactionBody without caring if it sums or not to 0
  2. Create the Transaction
  3. Call min_fee(tx: Transaction, linear_fee: LinearFee): BigNum; to get the real fee
  4. Go back to my TransactionBuilder to set the new calculated fee.
  5. Re-build the TransactionBody with the correct fee.
  6. And submit Transaction with my minted assets

Am I missing something?

cardano_serialization_lib_bg.js includes a "require"

Thanks for this awesome lib.

The browser package includes a "require()" call in cardano-serialization-lib-browser/cardano_serialization_lib_bg.js

Would it be possible to get rid of that call? I have to comment out the whole function otherwise I see:

WARNING  Compiled with 1 warnings                                                                                                                                                                                                                                                                     5:01:36 PM

 warning  in ./src/utils/cardano-serialization-lib-browser/cardano_serialization_lib_bg.js

Critical dependency: the request of a dependency is an expression

ModuleDependencyWarning: Critical dependency: the request of a dependency is an expression
    at Compilation.reportDependencyErrorsAndWarnings (/Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/webpack/lib/Compilation.js:1459:23)
    at /Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/webpack/lib/Compilation.js:1258:10
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:20:1)
    at AsyncSeriesHook.lazyCompileHook (/Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/tapable/lib/Hook.js:154:20)
    at Compilation.finish (/Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/webpack/lib/Compilation.js:1253:28)
    at /Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/webpack/lib/Compiler.js:672:17
    at eval (eval at create (/Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:11:1)
    at /Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/webpack/lib/Compilation.js:1185:12
    at /Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/webpack/lib/Compilation.js:1097:9
    at processTicksAndRejections (node:internal/process/task_queues:75:11)
    at CommonJsRequireContextDependency.getWarnings (/Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/webpack/lib/dependencies/ContextDependency.js:40:18)
    at Compilation.reportDependencyErrorsAndWarnings (/Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/webpack/lib/Compilation.js:1454:24)
    at /Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/webpack/lib/Compilation.js:1258:10
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:20:1)
    at AsyncSeriesHook.lazyCompileHook (/Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/tapable/lib/Hook.js:154:20)
    at Compilation.finish (/Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/webpack/lib/Compilation.js:1253:28)
    at /Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/webpack/lib/Compiler.js:672:17
    at eval (eval at create (/Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:11:1)
    at /Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/webpack/lib/Compilation.js:1185:12
    at /Users/marcelklammer/Documents/workspaces/github/ccwallet/node_modules/webpack/lib/Compilation.js:1097:9
    at processTicksAndRejections (node:internal/process/task_queues:75:11)

Process finished with exit code 130 (interrupted by signal 2: SIGINT)

Fee calculation does not take metadata into account

I'm building transactions using the transaction builder and I am using add_change_if_needed to get the optimal fees calculation. However, if I add metadata to the transaction, submitting it fails with

transaction submit error ShelleyTxValidationError ShelleyBasedEraMary (ApplyTxError [LedgerFailure (UtxowFailure (UtxoFailure (FeeTooSmallUTxO (Coin xxx) (Coin xxx)))),LedgerFailure (UtxowFailure (MissingTxBodyMetadataHash (AuxiliaryDataHash {unsafeAuxiliaryDataHash = SafeHash "xxx"})))])

As far as I can tell, this is because the fees calculation doesn't take metadata into account.

Wrapper for TransactionBody to use for signing

Currently when you call build on the TransactionBuilder, you get back a TransactionBody. This isn't great because you lose

  1. Information about which witnesses are needed
  2. Information about the "amount" of each input

It'd be better if we made the build function instead give you a TransactionSigner with functions to add witnesses, and its give you an error if you're missing a witness at the end (instead of being told the witness is missing once you submit it to your Cardano node)

Add get_implicit_input to TransactionBody

TransactionBuilder has this handy function called get_implicit_input which handles summing up the withdrawals and refunds in a transaction. Unfortunately, the Transaction class doesn't have this, but it probably should.

Empty asset names

I'm having issues dealing with tokens like the testnet faucet's "Testcoin", which have zero length asset names.

let assetName="";
AssetName.new(Buffer.from(assetName, 'hex'));
...

How should I treat them to avoid this error further in code:
Deserialization: Invalid cbor: not enough bytes, expect 0 bytes but received 0 bytes.

Thanks.

How to use this libaray in a java application

Hi,

We want to create and sign cardano transactions programmatically in a java application using this library. But those available packages looks like for application written in typescript language. Can we use this library in an applicatio written in java language?

Thank you

deserialize tx

Can you show an example using this lib to deserialize a borc encoded tx back to JSON?

WASM clears memory on Option<> function argument

We pass everything by reference to avoid memory being unexpectedly free'd from the WASM side. However, neither &Option<> nor Option<&> works with wasm-bindgen at the moment, and therefore optional arguments end up freeing whatever is passed in.

We need to either add this feature to wasm-bindgen or make a wrapper for an optional reference.

Validate an Address using the Public Key

I'm working on a project that uses this library and I'm looking to verify if an Address belongs to a Public Key.

Is this possible with the library? Is this even possible with Cardano?

I could easily do this using the Private Key, but validation is being done on the server-side and I don't want in any way to send the Private Key over the Network in any kind of way.

So how could I know if a pair of Address+Public Key belong together.

Add support for block parsing, etc.

Currently our library doesn't handle parsing blocks and some other stuff like protocol parameter updates.

Some of these are because we just didn't have time to run the CDDL codegen on it.
Some of them are because of CDDL codgen is missing some functionality

It would be nice to add all of these eventually though.

Error: Cannot find module '@emurgo/cardano-serialization-lib-asmjs'

I'm trying to get the asmjs version to run as the WASM version isn't compatible with the framework I'm using (MeteorJS). I've installed @emurgo/cardano-serialization-lib-asmjs as you normally do npm install --save @emurgo/cardano-serialization-lib-asmjs

image

When I run it though it comes back as:

Error: Cannot find module '@emurgo/cardano-serialization-lib-asmjs'

In the description, it says Browser (pure JS - no WASM) ASM.js package. Being an NPM module I would have expected this to still be compatible with NodeJS (server side) and not just limited to the browser.

I just wanted to double check that @emurgo/cardano-serialization-lib-asmjs can run from NodeJS and there's no special setup require?

error: failed to run custom build command for `clear_on_drop v0.2.3`

Hi!
I have an issue when building on macOS. Running command npm run preinstall fails with output:


> cd rust; wasm-pack build --target=nodejs; wasm-pack pack; cd ..

[INFO]: ๐ŸŽฏ  Checking for the Wasm target...
[INFO]: ๐ŸŒ€  Compiling to Wasm...
   Compiling clear_on_drop v0.2.3
   Compiling wasm-bindgen-backend v0.2.63
error: failed to run custom build command for `clear_on_drop v0.2.3`

Caused by:
  process didn't exit successfully: `/projects/cardano-serialization-lib/rust/target/release/build/clear_on_drop-edaa748acb43a456/build-script-build` (exit code: 1)
--- stdout
TARGET = Some("wasm32-unknown-unknown")
OPT_LEVEL = Some("s")
HOST = Some("x86_64-apple-darwin")
CC_wasm32-unknown-unknown = None
CC_wasm32_unknown_unknown = None
TARGET_CC = None
CC = None
CFLAGS_wasm32-unknown-unknown = None
CFLAGS_wasm32_unknown_unknown = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
DEBUG = Some("false")
running: "clang" "-Os" "-ffunction-sections" "-fdata-sections" "-fPIC" "--target=wasm32-unknown-unknown" "-Wall" "-Wextra" "-o" "/projects/cardano-serialization-lib/rust/target/wasm32-unknown-unknown/release/build/clear_on_drop-52df18e6f401774c/out/src/hide.o" "-c" "src/hide.c"
cargo:warning=error: unable to create target: 'No available targets are compatible with this triple.'
cargo:warning=1 error generated.
exit code: 1

--- stderr


error occurred: Command "clang" "-Os" "-ffunction-sections" "-fdata-sections" "-fPIC" "--target=wasm32-unknown-unknown" "-Wall" "-Wextra" "-o" "/projects/cardano-serialization-lib/rust/target/wasm32-unknown-unknown/release/build/clear_on_drop-52df18e6f401774c/out/src/hide.o" "-c" "src/hide.c" with args "clang" did not execute successfully (status code exit code: 1).



warning: build failed, waiting for other jobs to finish...
error: build failed
Error: Compiling your crate to WebAssembly failed
Caused by: failed to execute `cargo build`: exited with exit code: 101
Error: Unable to find the pkg directory at path ".", or in a child directory of "."

What could be the problem?

How to use `Address` instead of `ByronAddress` as witness

I am currently looking at https://github.com/Emurgo/cardano-serialization-lib/blob/master/example/index.spec.ts#L75 and https://github.com/Emurgo/cardano-serialization-lib/blob/master/example/index.spec.ts#L104 and trying to use a Shelley address for the same process by using Address.from_bech32 but the witness methods all expect an instance of ByronAddress.

Is support for Shelley addresses fully implemented and if so, what would be the process of using a Shelley address as a witness?

the transaction created by libs can't send to cardano-node

shelley cardano-node: v1.14.2
shelley cardano-wallet: 2020.7.6-shelley

code with commit 320191c

#![allow(unused_variables, unused_imports)]

use cardano_serialization_lib::{self as adalib, crypto};
use cbor_event::{self as cbor};

pub fn main() {
    let xprv = "xprv1wq9th6qy7ej8w03cgas2lzwvzncvwaje8ek8lps6u6mwyhtpaewap0w2f9hhrpg6tvrffcvz5ecevvhfl6vnznswss96kqyncm2drut3kfps0pv0r4q3fuy6urzs52ywdpzx55muncgf283fr378hwzwp5p27ewe";
    let xprv = crypto::Bip32PrivateKey::from_bech32(xprv).unwrap();

    let xpub = xprv.to_public();
    // crypto::blake2b224 visibility changed
    let keyhash = crypto::blake2b224(&xpub.as_bytes()[0..32]).to_vec();
    let keyhash = crypto::AddrKeyHash::from_bytes(keyhash).unwrap();
    let cred = adalib::address::StakeCredential::from_keyhash(&keyhash);
    let payment = adalib::address::EnterpriseAddress::new(0, &cred);

    let mut inputs = adalib::TransactionInputs::new();
    let txid = "2558aad25ec6b0e74009f36dc60d7fec6602ce43d603e80c9edde9dd54c78eb4";
    let txid = crypto::TransactionHash::from_bytes(hex::decode(txid).unwrap()).unwrap();
    let input = adalib::TransactionInput::new(&txid, 0);
    inputs.add(&input);

    let mut outputs = adalib::TransactionOutputs::new();
    let output = adalib::TransactionOutput::new(&payment.to_address(), adalib::Coin::new(9000000));
    outputs.add(&output);

    let txbody =
        adalib::TransactionBody::new(&inputs, &outputs, adalib::Coin::new(1000000), 832163);

    let vkwt = txbody.sign(&xprv.to_raw_key());
    let mut vkwts = crypto::Vkeywitnesses::new();
    vkwts.add(&vkwt);
    let mut witness_set = adalib::TransactionWitnessSet::new();
    witness_set.set_vkeys(&vkwts);
    let newtx = adalib::Transaction::new(&txbody, &witness_set, None);

    use std::io::prelude::*;
    let mut file = std::fs::File::create("tx.raw").unwrap();
    file.write_all(&cbor::cbor!(&newtx).unwrap()).unwrap();

    // println!("{}", hex::encode(cbor::cbor!(newtx).unwrap()));
}

the signed tx with hexify

83a400818258202558aad25ec6b0e74009f36dc60d7fec6602ce43d603e80c9edde9dd54c78eb400018182581d60c5fb57853a4a5bbb13bcd494ee0facd4e1fca33720a640664df151341a00895440021a000f4240031a000cb2a3a10081825820c6e47dceb9235ad31fec01ef3e34b02839d22fb583cd28fac7ec81ebbe653a395840e94817956d902702ed6172db8edca0193b33aba511a72e1998cc18aa492be8cffaca96c8305ffbb2836c3c04c886e23302e222b99185b87b701a40a10c50660ff6

and then post signed tx to cardano-wallet

curl -X POST 'http://10.60.82.100:8090/v2/proxy/transactions' -H 'Content-Type: application/octet-stream' --data-binary tx.raw

the response data

{
  "code": "malformed_tx_payload",
  "message": "I couldn't verify that the payload has the correct binary format. Therefore I couldn't send it to the node. Please check the format and try again."
} 

can't access lexical declaration 'Bip32PrivateKey' before initialization with Webpack5 and browser version

We are trying to use the browser version of the library in a project built with webpack5 (with experiments.asyncWebAssembly = true) and calls to the library are failing with errors like:

can't access lexical declaration 'Bip32PrivateKey' before initialization

Interestingly, when we rebuilt the library locally from source with npm rust:build-browser, this version didn't have the problem. We have a suspicion it's related to this: rustwasm/wasm-bindgen#2343 - so probably republishing the lib with the latest wasm building tooling is the solution to this problem

We don't have a minimum repro of this issue, but given that issue the explanation seems plausible

Need an example for creating delegation transaction

Hi all,

Please help to give me an example for creating delegation transaction. I found that there was only 2 examples on how to create a new address and make a transfer transaction.

Thank you in advance.

Allow different bech32 address prefixes

Currently the Address to_bech32 function has a hard-coded prefix addr

However, it's entirely reasonable for people to want their own prefixes. Especially because for testnets, IOHK wants to use addr_test as the prefix for addresses

FeeTooSmallUTxO when multiple assets are used in a UTXO

Hi, I'm getting the min fee for a tx that will mint a token but sometimes the functions return a fee too small. This is the function:

/**
 * @param {Transaction} tx
 * @param {LinearFee} linear_fee
 * @returns {BigNum}
 */
declare export function min_fee(tx: Transaction, linear_fee: LinearFee): BigNum;

My code takes a structure coming from the cardano-wallet (coinSelection) and builds a tx using TxBuilder, then I set the mint object using set_mint, then sign it and get the fee with min_fee.

To get the min fee I call set_mint this way:

min_fee(tx, LinearFee.new(BigNum.from_str("44"), BigNum.from_str("155381")));

This is how I'm constructing the TransactionBody from the coinSelection:

buildTransaction(coinSelection: CoinSelectionWallet, ttl: number, data?: TransactionMetadata, startSlot = 0, config = Config.Mainnet): TransactionBody {
	    const protocolParams = config.protocolParams;
	    let txBuilder = TransactionBuilder.new(
		    // all of these are taken from the mainnet genesis settings
		    // linear fee parameters (a*size + b)
		    LinearFee.new(BigNum.from_str("44"), BigNum.from_str("155381")),
		    // minimum utxo value
		    BigNum.from_str("1000000"),
		    // pool deposit
		    BigNum.from_str("500000000"),
		    // key deposit
		    BigNum.from_str("2000000")
	    );

	    // add tx inputs
	    coinSelection.inputs.forEach((input, i) => {
		    let address = Address.from_bech32(input.address);
		    let txInput = TransactionInput.new(
			    TransactionHash.from_bytes(Buffer.from(input.id, 'hex')),
			    input.index
		    );
		    let amount = Value.new(
			    BigNum.from_str(input.amount.quantity.toString())
		    );
		    txBuilder.add_input(address, txInput, amount);
	    });

	    // add tx outputs
	    coinSelection.outputs.forEach(output => {
		    let address = Address.from_bech32(output.address);
		    let amount = Value.new(
			    BigNum.from_str(output.amount.quantity.toString())
		    );

		    // add tx assets
		    if(output.assets && output.assets.length > 0){
			    let multiAsset = Seed.buildMultiAssets(output.assets);
			    amount.set_multiasset(multiAsset);
		    }

		    let txOutput = TransactionOutput.new(
			    address,
			    amount
		    );
		    txBuilder.add_output(txOutput);
	    });

	    // add tx change
	    coinSelection.change.forEach(change => {
		    let address = Address.from_bech32(change.address);
		    let amount = Value.new(
			    BigNum.from_str(change.amount.quantity.toString())
		    );

		    // add tx assets
		    if(change.assets && change.assets.length > 0){
			    let multiAsset = Seed.buildMultiAssets(change.assets);
			    amount.set_multiasset(multiAsset);
		    }

		    let txOutput = TransactionOutput.new(
			    address,
			    amount
		    );
		    txBuilder.add_output(txOutput);
	    });

	    // add tx metadata
	    if (data) {
		    txBuilder.set_metadata(data);
	    }

	    // set tx validity start interval
	    txBuilder.set_validity_start_interval(startSlot);

	    // set tx ttl
	    txBuilder.set_ttl(ttl);

	    // calculate fee
	    let fee = coinSelection.inputs.reduce((acc, c) => c.amount.quantity + acc, 0) 
	    - coinSelection.outputs.reduce((acc, c) => c.amount.quantity + acc, 0) 
	    - coinSelection.change.reduce((acc, c) => c.amount.quantity + acc, 0);
	    
	    // set tx fee
	    txBuilder.set_fee(BigNum.from_str(fee.toString()));

	    let txBody = txBuilder.build();
	    return txBody;
    }

This is Seed.buildMultiAssets():

static buildMultiAssets(assets: WalletsAssetsAvailable[]): MultiAsset {
	let multiAsset = MultiAsset.new();
	assets.forEach(a => {
			let asset = Assets.new();
			let scriptHash = Seed.getScriptHashFromPolicy(a.policy_id);
			asset.insert(AssetName.new(Buffer.from(a.asset_name, 'hex')), BigNum.from_str(a.quantity.toString()));
			multiAsset.insert(scriptHash, asset);
	});
	return multiAsset;
}

Here the code to create the Mint object:

static buildTransactionMint(tokens: TokenWallet[]): Mint {
	let mint = Mint.new();
	tokens.forEach(t => {
		let mintAssets = MintAssets.new();
		let scriptHash = Seed.getScriptHashFromPolicy(t.asset.policy_id);
		mintAssets.insert(AssetName.new(Buffer.from(t.asset.asset_name)), Int.new_i32(t.asset.quantity));
		mint.insert(scriptHash, mintAssets);
	});

	return mint;
}

After the TransactionBody is built I set the mint object this way:

let txBody = buildTransaction(coinSelection, ttl, metadata); // metadata is of type `TransactionMetadata`
txBody.set_mint(mint);

After that I sign the tx with txBody the signingKeys, metadata and the scripts // are of type NativeScripts[].
To finally get the min fee using min_fee.

The thing is I'm not sure when specifically the issue shows up (it works sometimes) but there are some cases that could be a starting point. For example, the min_fee is wrong when I have 3 assets in one UTXO plus metadata like this:

{
  inputs: [
    {
      amount: {
        quantity: 1444443,
        unit: "lovelace",
      },
      address: "addr1qyuxc75xmzzy7sy955pyz4tqg0ycgttjcv2u39ay929q2yp59kkfl90wf7f9vlm99fek6e9l5zh65td8jhw63hn9skqqya2xl3",
      id: "ef4911bd3ac3f45ad69a21b933a5c7cb9470cb77661f41f50e07476eb87c1b2a",
      derivation_path: [
        "1852H",
        "1815H",
        "0H",
        "0",
        "0",
      ],
      assets: [
        {
          asset_name: "54616e676f32",
          quantity: 1000000,
          policy_id: "a716bcf749e3afc27674da23c15fb24a63435f837760dcc823bca995",
        },
      ],
      index: 0,
    },
    {
      amount: {
        quantity: 1444443,
        unit: "lovelace",
      },
      address: "addr1qyuxc75xmzzy7sy955pyz4tqg0ycgttjcv2u39ay929q2yp59kkfl90wf7f9vlm99fek6e9l5zh65td8jhw63hn9skqqya2xl3",
      id: "b9f927b44c0905697c1767d77f6ceb798091d6a854c3f04543e23c688277ff01",
      derivation_path: [
        "1852H",
        "1815H",
        "0H",
        "0",
        "0",
      ],
      assets: [
        {
          asset_name: "54616e676f35",
          quantity: 1000000,
          policy_id: "19933db2e7c74625ab0a4174bab9a27170f97555634082c2f16d3bea",
        },
      ],
      index: 0,
    },
    {
      amount: {
        quantity: 1444443,
        unit: "lovelace",
      },
      address: "addr1qyuxc75xmzzy7sy955pyz4tqg0ycgttjcv2u39ay929q2yp59kkfl90wf7f9vlm99fek6e9l5zh65td8jhw63hn9skqqya2xl3",
      id: "4b5efe05d035d510bac0fa9dd84db70912c13a95efd97e2fdd9afb362438dc0a",
      derivation_path: [
        "1852H",
        "1815H",
        "0H",
        "0",
        "0",
      ],
      assets: [
        {
          asset_name: "54616e676f33",
          quantity: 1000000,
          policy_id: "fcd84d1acc1ad2780f0a231779ea5d9da20826c3c13c7a3dda6efa5a",
        },
      ],
      index: 0,
    },
  ],
  outputs: [
    {
      amount: {
        quantity: 1444443,
        unit: "lovelace",
      },
      address: "addr1qyuxc75xmzzy7sy955pyz4tqg0ycgttjcv2u39ay929q2yp59kkfl90wf7f9vlm99fek6e9l5zh65td8jhw63hn9skqqya2xl3",
      assets: [
        {
          policy_id: "7e634c9d8edfd106326767cf58fdf6666a2db4f3179cadb2b9054122",
          asset_name: "54616e676f",
          quantity: 1000000,
        },
      ],
    },
  ],
  change: [
    {
      amount: {
        quantity: 2696486,
        unit: "lovelace",
      },
      address: "addr1qxqlyjyrqcgar3xx8ayyhxphkmnqnt2w524hwg8y555vtkf59kkfl90wf7f9vlm99fek6e9l5zh65td8jhw63hn9skqqhxnp7w",
      derivation_path: [
        "1852H",
        "1815H",
        "0H",
        "1",
        "7",
      ],
      assets: [
        {
          asset_name: "54616e676f35",
          quantity: 1000000,
          policy_id: "19933db2e7c74625ab0a4174bab9a27170f97555634082c2f16d3bea",
        },
        {
          asset_name: "54616e676f32",
          quantity: 1000000,
          policy_id: "a716bcf749e3afc27674da23c15fb24a63435f837760dcc823bca995",
        },
        {
          asset_name: "54616e676f33",
          quantity: 1000000,
          policy_id: "fcd84d1acc1ad2780f0a231779ea5d9da20826c3c13c7a3dda6efa5a",
        },
      ],
    },
  ],
  withdrawals: [
  ],
  certificates: undefined,
  deposits: [
  ],
  metadata: "oQCheDg3ZTYzNGM5ZDhlZGZkMTA2MzI2NzY3Y2Y1OGZkZjY2NjZhMmRiNGYzMTc5Y2FkYjJiOTA1NDEyMqFlVGFuZ2+laWFyd2VhdmVJZGphcndlYXZlLWlkZmlwZnNJZGdpcGZzLWlkZG5hbWVlVGFuZ29rZGVzY3JpcHRpb25xVGFuZ28gY3J5cHRvIGNvaW5kdHlwZWRDb2lu",
}

In this case, the error is this (min_fee returns 204177):

HardForkApplyTxErrFromEra S (S (S (Z (WrapApplyTxErr {unwrapApplyTxErr = ApplyTxError [LedgerFailure (UtxowFailure (UtxoFailure (FeeTooSmallUTxO (Coin 210900) (Coin 204177))))]})))).

If no metadata is present the tx for 3 assets in one UTXO just works but when the assets are 5 the error happens again:

{
  inputs: [
    {
      amount: {
        quantity: 2692805,
        unit: "lovelace",
      },
      address: "addr1qxuq6szwm8gdmxzvv7c0r2sgkyva69tmh2h8dseyg8uzdv359kkfl90wf7f9vlm99fek6e9l5zh65td8jhw63hn9skqqvjjcev",
      id: "ffc81613c24bb158858fdf4008934a6917b2772206603f9cb617432a1719f446",
      derivation_path: [
        "1852H",
        "1815H",
        "0H",
        "1",
        "9",
      ],
      assets: [
        {
          asset_name: "54616e676f32",
          quantity: 1000000,
          policy_id: "9a8565c9bd0fcf3add4fdd08956e40e1607a762b92f17dfaab2dfec5",
        },
        {
          asset_name: "54616e676f34",
          quantity: 1000000,
          policy_id: "a1c81493ce562eba9a5c6c6ed3e6a0514d9d1196afd5677d43c655e5",
        },
        {
          asset_name: "54616e676f33",
          quantity: 1000000,
          policy_id: "fcd84d1acc1ad2780f0a231779ea5d9da20826c3c13c7a3dda6efa5a",
        },
      ],
      index: 1,
    },
    {
      amount: {
        quantity: 1444443,
        unit: "lovelace",
      },
      address: "addr1qyuxc75xmzzy7sy955pyz4tqg0ycgttjcv2u39ay929q2yp59kkfl90wf7f9vlm99fek6e9l5zh65td8jhw63hn9skqqya2xl3",
      id: "ffc81613c24bb158858fdf4008934a6917b2772206603f9cb617432a1719f446",
      derivation_path: [
        "1852H",
        "1815H",
        "0H",
        "0",
        "0",
      ],
      assets: [
        {
          asset_name: "54616e676f33",
          quantity: 1000000,
          policy_id: "472b254819d86a3393726eb118b1ba860dd04fa630810b38c2e553fc",
        },
      ],
      index: 0,
    },
    {
      amount: {
        quantity: 1444443,
        unit: "lovelace",
      },
      address: "addr1qyuxc75xmzzy7sy955pyz4tqg0ycgttjcv2u39ay929q2yp59kkfl90wf7f9vlm99fek6e9l5zh65td8jhw63hn9skqqya2xl3",
      id: "b9f927b44c0905697c1767d77f6ceb798091d6a854c3f04543e23c688277ff01",
      derivation_path: [
        "1852H",
        "1815H",
        "0H",
        "0",
        "0",
      ],
      assets: [
        {
          asset_name: "54616e676f35",
          quantity: 1000000,
          policy_id: "19933db2e7c74625ab0a4174bab9a27170f97555634082c2f16d3bea",
        },
      ],
      index: 0,
    },
  ],
  outputs: [
    {
      amount: {
        quantity: 1444443,
        unit: "lovelace",
      },
      address: "addr1qyuxc75xmzzy7sy955pyz4tqg0ycgttjcv2u39ay929q2yp59kkfl90wf7f9vlm99fek6e9l5zh65td8jhw63hn9skqqya2xl3",
      assets: [
        {
          policy_id: "001ff1c3d7cc7083d2d569748ad941910246a58e460287f708f3c137",
          asset_name: "54616e676f34",
          quantity: 1000000,
        },
      ],
    },
  ],
  change: [
    {
      amount: {
        quantity: 3937119,
        unit: "lovelace",
      },
      address: "addr1q87p0ml3mj8xaxjrmcr7dgulkg7ylt0cgkh5l0l0twr2p6359kkfl90wf7f9vlm99fek6e9l5zh65td8jhw63hn9skqqu5wdxs",
      derivation_path: [
        "1852H",
        "1815H",
        "0H",
        "1",
        "10",
      ],
      assets: [
        {
          asset_name: "54616e676f35",
          quantity: 1000000,
          policy_id: "19933db2e7c74625ab0a4174bab9a27170f97555634082c2f16d3bea",
        },
        {
          asset_name: "54616e676f33",
          quantity: 1000000,
          policy_id: "472b254819d86a3393726eb118b1ba860dd04fa630810b38c2e553fc",
        },
        {
          asset_name: "54616e676f32",
          quantity: 1000000,
          policy_id: "9a8565c9bd0fcf3add4fdd08956e40e1607a762b92f17dfaab2dfec5",
        },
        {
          asset_name: "54616e676f34",
          quantity: 1000000,
          policy_id: "a1c81493ce562eba9a5c6c6ed3e6a0514d9d1196afd5677d43c655e5",
        },
        {
          asset_name: "54616e676f33",
          quantity: 1000000,
          policy_id: "fcd84d1acc1ad2780f0a231779ea5d9da20826c3c13c7a3dda6efa5a",
        },
      ],
    },
  ],
  withdrawals: [
  ],
  certificates: undefined,
  deposits: [
  ],
  metadata: undefined,
}

This is the error (min_fee returns 200129):

HardForkApplyTxErrFromEra S (S (S (Z (WrapApplyTxErr {unwrapApplyTxErr = ApplyTxError [LedgerFailure (UtxowFailure (UtxoFailure (FeeTooSmallUTxO (Coin 201700) (Coin 200129))))]}))))

I also test it with 4 assets in one UTXO and it works. Maybe I'm doing something intrinsically wrong but if I'm not I hope these examples help you find the issue.

Signing Mary transaction

I'm currently working on an ADA integration over at ArkEcosystemArchive/platform-sdk#1034 but always run into the issue LedgerFailure (UtxowFailure (MissingVKeyWitnessesUTXOW (WitHashes (fromList [KeyHash \"09a9dd24b43ce6f22de361f2423e62a8a72a6ebb1e972a69ebb3bdcc\"])))) when the transaction gets broadcasted which is a bit odd because the passphrase and/or private key used to sign the transaction are correct.

// This is the transaction builder that uses values from the genesis block of the configured network.
const txBuilder = CardanoWasm.TransactionBuilder.new(
	CardanoWasm.LinearFee.new(
		CardanoWasm.BigNum.from_str(minFeeA.toString()),
		CardanoWasm.BigNum.from_str(minFeeB.toString()),
	),
	CardanoWasm.BigNum.from_str(minUTxOValue.toString()),
	CardanoWasm.BigNum.from_str(poolDeposit.toString()),
	CardanoWasm.BigNum.from_str(keyDeposit.toString()),
);

// Get a `Bip32PrivateKey` instance and turn it into a `PrivateKey` instance
const rootKey = deriveRootKey(input.sign.mnemonic);
const accountKey = deriveAccountKey(rootKey, 0);
// const privateKey = accountKey.to_raw_key();
// console.log(
// 	"privateKey",
// 	Buffer.from(privateKey.as_bytes()).toString("hex"),
// 	"publicKey",
// 	Buffer.from(privateKey.to_public().as_bytes()).toString("hex"),
// );
// These are the inputs (UTXO) that will be consumed to satisfy the outputs. Any change will be transferred back to the sender
const utxos: UnspentTransaction[] = await this.listUnspentTransactions(input.from);

// for (let i = 0; i < utxos.length; i++) {
const i = 0;
const utxo: UnspentTransaction = utxos[i];

txBuilder.add_input(
	Address.from_bech32(utxo.address),
	CardanoWasm.TransactionInput.new(
		CardanoWasm.TransactionHash.from_bytes(Buffer.from(utxo.transaction.hash, "hex")),
		parseInt(utxo.index),
	),
	createValue(utxo.value),
);

console.log("utxo", utxo);
// break;
// }

// These are the outputs that will be transferred to other wallets. For now we only support a single output.
txBuilder.add_output(
	CardanoWasm.TransactionOutput.new(
		CardanoWasm.Address.from_bech32(input.data.to),
		createValue(input.data.amount),
	),
);

// This is the expiration slot which should be estimated with #estimateExpiration
txBuilder.set_ttl(input.data.expiration);

// calculate the min fee required and send any change to an address
txBuilder.add_change_if_needed(CardanoWasm.Address.from_bech32(input.from));

// once the transaction is ready, we build it to get the tx body without witnesses
const txBody = txBuilder.build();
const txHash = CardanoWasm.hash_transaction(txBody);
const witnesses = CardanoWasm.TransactionWitnessSet.new();

// add keyhash witnesses
const vkeyWitnesses = CardanoWasm.Vkeywitnesses.new();
vkeyWitnesses.add(
	CardanoWasm.make_vkey_witness(
		CardanoWasm.TransactionHash.from_bytes(Buffer.from(utxo.transaction.hash, "hex")),
		deriveSpendKey(accountKey, 0).to_raw_key(),
	),
);
vkeyWitnesses.add(
	CardanoWasm.make_vkey_witness(
		CardanoWasm.TransactionHash.from_bytes(Buffer.from(utxo.transaction.hash, "hex")),
		deriveChangeKey(accountKey, 0).to_raw_key(),
	),
);
// vkeyWitnesses.add(CardanoWasm.make_vkey_witness(txHash, deriveStakeKey(accountKey, 0).to_raw_key()));
// vkeyWitnesses.add(CardanoWasm.make_vkey_witness(txHash, deriveChangeKey(accountKey, 0).to_raw_key()));
vkeyWitnesses.add(CardanoWasm.make_vkey_witness(txHash, accountKey.to_raw_key()));
witnesses.set_vkeys(vkeyWitnesses);

console.log("hash", Buffer.from(txHash.to_bytes()).toString("hex"));

This issue pops up when attempting to broadcast a transaction on testnet, haven't tried mainnet yet. Are any values that are being used wrong like the keys that are required for signing? Tried multiple different scenarios and values and always end up with the same error when broadcasting the transaction.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.