1

I'm getting the following error when trying to consume a UTxO sitting in a multisig script address:

[
  {
    "scriptWitnessNotValidating": [
      "74947280b4d63d1051d319d700e21dac50ee858c089378ccc410b568"
    ]
  }
]

This is the script I created for requiring 4 of 6 signatures to consume the UTxO:

const jsonScript = {
    type: 'atLeast',
    require: 4,
    scripts: [
        {
          type: 'sig',
          keyHash: '6bccf3fc71642dbc8f34deb976784ca636665043ef1384b31cab2524'
        },
        {
          type: 'sig',
          keyHash: 'acfdc19b3081ef21301f76eee0e5e35411b9d2c2b5624e580f36bac4'
        },
        {
          type: 'sig',
          keyHash: 'f03009eb94e1d4a208ccc64bde7e91dc3f6a6c1d8660199fc2f120b8'
        },
        {
          type: 'sig',
          keyHash: '3c76bbfc8af2b0862c3aca122a1d5a4493ee8b2aa2cfb7aadcfdcbc5'
        },
        {
          type: 'sig',
          keyHash: '52a09a992dfbe55f9ec80bc73fecf1bf7f42434c73e8bb79067aaf30'
        },
        {
          type: 'sig',
          keyHash: 'dd31fc7bf8d266eb08f840361ff528108d6689eeb3af96cfa77d8547'
        }
    ]    
};

I'm using this function to provide each of the signing keys to the transaction I want to execute:

tx.addKeyWitnesses(signingKeys[0]);
tx.addKeyWitnesses(signingKeys[1]);
tx.addKeyWitnesses(signingKeys[2]);
tx.addKeyWitnesses(signingKeys[3]);
tx.addKeyWitnesses(signingKeys[4]);
tx.addKeyWitnesses(signingKeys[5]);

Is there something I'm missing?

Thank you

2
  • Are you sure you are trying to consume the right UTxO? Check the index, maybe you are trying to consume the wrong output of that transaction. Feb 28 at 8:37
  • I tried all over again and it worked. I'm not sure if it was that or not but at least I have it right now. Thanks for your reply. Mar 2 at 0:29

1 Answer 1

1

Finally I was able to sort this out.

You can use this library to create the multisig: https://github.com/tango-crypto/cardano-wallet-js

The code I ran was the following:

multisig.js

const { WalletServer , Seed } = require('cardano-wallet-js');

const data = {
    "type":  "atLeast", //requires at least 4 keys to sign the tx
    "require": 4,
    "scripts":
    [
        {
            "type": "sig"
        },
        {
            "type": "sig"
        },
        {
            "type": "sig"
        },
        {
            "type": "sig"
        },
        {
            "type": "sig"
        },
        {
            "type": "sig"
        },
    ]
};
// generate the native script
const script = Seed.buildScript(data);

const jsonScript = Seed.scriptToJson(script);

console.log(jsonScript);

// get native script private keys (all them will be needed to sign the final tx)
const keys = Seed.getScriptKeys(script).map(k => k.to_bech32());
console.log("keys:", keys);

//Generate script address
const address = Seed.getScriptAddress(script, 'testnet').to_bech32();
console.log("address:", address);

The code to sign the transaction is this one (you need to replace every 'XXXX' on scriptKeys with your signing keys, and every 'YYYY' on jsonScript.scripts with the key hashes of each signature - all this is output of multisig.js):

tx-sign.js

const { WalletServer , Seed , Config, Bip32PrivateKey } = require('cardano-wallet-js');

const scriptKeys = [
    'XXXX',
    'XXXX',
    'XXXX',
    'XXXX',
    'XXXX',
    'XXXX'
];

const signingKeys = scriptKeys.map(key => Bip32PrivateKey.from_bech32(key).to_raw_key());

// get native script (this is the SAME SCRIPT, we're just "loading" it back)
const jsonScript = {
    type: 'atLeast',
    require: 4,
    scripts: [
      {
        type: 'sig',
        keyHash: 'YYYY'
      },
      {
        type: 'sig',
        keyHash: 'YYYY'
      },
      {
        type: 'sig',
        keyHash: 'YYYY'
      },
      {
        type: 'sig',
        keyHash: 'YYYY'
      },
      {
        type: 'sig',
        keyHash: 'YYYY'
      },
      {
        type: 'sig',
        keyHash: 'YYYY'
      }
    ]
};

// set network configuration
let buildOpts = {
    startSlot: 0, 
    config: Config.Testnet,
};

const ttl = 52399446; // slot before the tx should be processed

const CoinSelectionWallet = {
    "withdrawals": [],
    "inputs": [
        {
            "amount": {
                "quantity": 10000000,
                "unit": "lovelace"
            },
            "address": "addr_test1xr20j5t970ssz0323tzqqvp3pp02s96yf64zmzj83kksyvx5l9gktulpqylz4zkyqqcrzzz74qt5gn429k9y0rddqgcq2yupvs", // script address
            "id": "d48f256aea384066756be0c11c6e6b8baef8f7ad25ba92b76d1ae3c294443400",
            "assets": [],
            "index": 0
        },
    ],
    "deposits": [],
    "change": [
        {
            "amount": {
                "quantity": 8800000, // fee of 200000 initially
                "unit": "lovelace"
            },
            "address": "addr_test1xr20j5t970ssz0323tzqqvp3pp02s96yf64zmzj83kksyvx5l9gktulpqylz4zkyqqcrzzz74qt5gn429k9y0rddqgcq2yupvs",
            "assets": []
        }
    ],
    "outputs": [
        {
            "amount": {
                "quantity": 1000000,
                "unit": "lovelace"
            },
            "address": "addr_test1qpypxf9jma2lkmzwn6nhypmynqpmus7x0ekwp2jfdrxqgm8vecdcssszlmywlyn7h0nkqp9jyk8p7dhjecglhu9m75xq4mwl9v",
            "assets": []
        }
    ]
};

const script = Seed.buildScript(jsonScript);
// for the script witnesses we only need to specify the native script root
const scripts = [script.root];

// build the tx (you can include scripts/signingkeys here, eg: let tx = Seed.buildTransactionMultisig(selection, ttl, scripts, null, sigingKeys, buildOpts);)
let tx = Seed.buildTransactionMultisig(CoinSelectionWallet, ttl, [], null, [], buildOpts);
// add script
tx.addScriptWitness(...scripts);
// add witness
tx.addKeyWitnesses(signingKeys[0]);
tx.addKeyWitnesses(signingKeys[1]);
tx.addKeyWitnesses(signingKeys[2]);
tx.addKeyWitnesses(signingKeys[3]);
tx.addKeyWitnesses(signingKeys[4]);
tx.addKeyWitnesses(signingKeys[5]);
    
const signed = tx.build();
console.log(signed)

When you do :

tx.addKeyWitnesses(signingKeys[0]);
tx.addKeyWitnesses(signingKeys[1]);
tx.addKeyWitnesses(signingKeys[2]);
tx.addKeyWitnesses(signingKeys[3]);
tx.addKeyWitnesses(signingKeys[4]);
tx.addKeyWitnesses(signingKeys[5]);

You are signing with all 6 signatures. You can sign with any 4 you want and the UTxO will be consumed as well. On the contrary, if you provide less than 4 signatures, then the validation will fail.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.