Emurgo / cardano-serialization-lib

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.
Other
234 stars 125 forks source link

Unable to create a staking transaction #383

Closed akshitv1 closed 1 month ago

akshitv1 commented 2 years ago

Hi guys, i am trying to create a staking transaction using cardano serialisation library and then use blockfrost/infinito to send the transaction. I am using @emurgo/cardano-serialization-lib-nodejs: ^9.1.4,

Here's my code :

createStakeTx(inputs, ttl, poolID, isFirstStake) {
        try {
            // let rootKey = Cardano.Bip32PrivateKey.from_bytes(Buffer.from(this.masterKey, 'hex'));
            console.log(
                'inside create stake tx ::::::::::::::'
            )
            console.log('inputs :', inputs); 
            console.log('ttl :', ttl);
            console.log('poolId :', poolID);
            console.log('isFirstStake :', isFirstStake);

            // this.masterKey = Cardano.Bip32PrivateKey.from_bip39_entropy(Buffer.from(entropy, 'hex'), Buffer.from(''))
            let rootKey = this.masterKey 
            let spend = rootKey
                .derive(harden(1852))
                .derive(harden(1815))
                .derive(harden(0))
                .derive(this.accountKey) // 1
                .derive(this.addressKey); // 34
            let spendPubKey = spend.to_public();

            let stake = rootKey
                .derive(harden(1852))
                .derive(harden(1815))
                .derive(harden(0))
                .derive(2)
                .derive(0);
            let stakePubkey = stake.to_public();
            let ed = stake.to_public().to_raw_key().hash();
            // console.log('ed :', ed);
            let spendCred = Cardano.StakeCredential.from_keyhash(stake.to_public().to_raw_key().hash());
            let stakeCred = Cardano.StakeCredential.from_keyhash(spend.to_public().to_raw_key().hash());

            // testnet: 0, mainnet: 1
            let address = Cardano.BaseAddress.new(1, spendCred, stakeCred).to_address().to_bech32();

            let linearFee = Cardano.LinearFee.new(
                Cardano.BigNum.from_str('44'),
                Cardano.BigNum.from_str('155381')
            );
            let txBuilder = Cardano.TransactionBuilder.new(
                linearFee,
                Cardano.BigNum.from_str('1000000'),
                Cardano.BigNum.from_str('500000000'),
                Cardano.BigNum.from_str('2000000'),
                16384,
                5000,
            );

            let sumInputs = bigNumber(0);
            inputs.forEach(element => {
                txBuilder.add_key_input(
                    spendPubKey.to_raw_key().hash(),
                    Cardano.TransactionInput.new(
                        Cardano.TransactionHash.from_bytes(Buffer.from(element.tx_id, 'hex')),
                        element.vout
                    ),
                    Cardano.Value.new(Cardano.BigNum.from_str(element.amount))
                );
                sumInputs = sumInputs.plus(element.amount);
            });

            txBuilder.set_ttl(ttl + 2000);

            let poolKeyHash = Cardano.Ed25519KeyHash.from_bytes(Buffer.from(poolID, 'hex'));
            let certs = Cardano.Certificates.new();

            if (isFirstStake == true) {
                certs.add(
                    Cardano.Certificate.new_stake_registration(
                        Cardano.StakeRegistration.new(
                            stakeCred
                        )
                    )
                );                
            }

            certs.add(
                Cardano.Certificate.new_stake_delegation(
                    Cardano.StakeDelegation.new(
                        stakeCred,
                        poolKeyHash
                    )
                )
            );

            txBuilder.set_certs(certs);

            let estimate = this.estimateStakeTxFee(inputs, poolID, isFirstStake);
            txBuilder.set_fee(Cardano.BigNum.from_str(bigNumber(estimate.fee).toFixed()));

            let changeAmount = bigNumber(0);
            console.log('sumInputs :', sumInputs)
            if (isFirstStake == true) {
                changeAmount = sumInputs.minus(KEY_DEPOSIT).minus(estimate.fee);
            } else {
                changeAmount = sumInputs.minus(estimate.fee);
            }

            console.log('changeAmount :', changeAmount)
            txBuilder.add_output(
                Cardano.TransactionOutput.new(
                    Cardano.Address.from_bech32(address),
                    Cardano.Value.new(Cardano.BigNum.from_str(changeAmount.toFixed()))
                )
            );

            let txBody = txBuilder.build();

            const txHash = Cardano.hash_transaction(txBody);

            let witnesses = Cardano.TransactionWitnessSet.new();
            let vkeyWitnesses = Cardano.Vkeywitnesses.new();
            vkeyWitnesses.add(Cardano.make_vkey_witness(
                txHash,
                spend.to_raw_key(),
            ));

            vkeyWitnesses.add(Cardano.make_vkey_witness(
                 txHash,
                 stake.to_raw_key(),
            ));

            witnesses.set_vkeys(vkeyWitnesses);

            let tx = Cardano.Transaction.new(
                txBody,
                witnesses,
            );
            console.log('rawtx ::', Buffer.from(tx.to_bytes()).toString('hex'))
            const res = await client.txSubmit(Buffer.from(tx.to_bytes()).toString('hex'));
            return res;
        } catch (err) {
            console.log('err: ', err);
            return null;
        }
    }

// Error when i use blockfrost :

transaction submit error ShelleyTxValidationError ShelleyBasedEraAlonzo (ApplyTxError [UtxowFailure (WrappedShelleyEraFailure (MissingVKeyWitnessesUTXOW (WitHashes (fromList [KeyHash \"some hash\"])))),DelegsFailure (DelplFailure (DelegFailure (StakeDelegationImpossibleDELEG (KeyHashObj (KeyHash \"somehash\")))))])

//Error when i use infinito : {"type":"jsonwsp/fault","version":"1.0","servicename":"ogmios","fault":{"code":"client","string":"Invalid request: DeserialiseFailure 539 \"Size mismatch when decoding \nRecord RecD.\nExpected 4, but found 3.\"."},"reflection":{"requestId":"XEpib"}} is an unknown result

Maybe i am just creating the transaction in a wrong way or my keys might be messed up.

Open to any help and suggestions

THnaks

bwhour commented 2 years ago

any update about this issue ?
how to build up register or stake transaction using this lib ? are there any documents can we refer to ?

i use /proxy/subbmit interface and got the errors as follwoing:

'500 - "{\"code\":\"created_invalid_transaction\",\"message\":\"The submitted transaction was rejected by the local node. Here's an error message that may help with debugging: TxValidationErrorInMode (ShelleyTxValidationError ShelleyBasedEraAlonzo (ApplyTxError [UtxowFailure (WrappedShelleyEraFailure (UtxoFailure (**ValueNotConservedUTxO**(Value 19679048 (fromList [])) (Value 9679048 (fromList [])))))])) AlonzoEraInCardanoMode\"}"'

and i estimate the fee like this:

let outputTxFee = txBuilder.fee_for_output(outputTx).to_str(); let currentFee = txBuilder.min_fee().to_str()

any one can help ?

nooxx commented 2 years ago

would love some help here as well

lisicky commented 1 month ago

According to error a signature for stake delegation is not provided, you need to sign a transaction by stake key.

@bwhour balancing is not correct. If you still have ( I hope not ) , create an issue with code example.