Creando una cuenta multisig

Esta guía te mostrará cómo configurar una cuenta conjunta.

Caso de uso

Imagina que Alice y Bob tienen cuentas separadas, pero también quieren tener una cuenta compartida para comprar víveres. Si uno de ellos sale de compras, debería poder realizar transacciones utilizando su cuenta conjunta sin requerir autorización explícita de la otra persona.

Esta cuenta compartida aparece en Bitxor como multisig 1-de-2. Crear una cuenta multisig permite a Alice y Bob compartir fondos en una cuenta separada. Dado que la cuenta está configurada como una 1-de-2, solo se requiere la firma de uno de ellos para emitir transacciones desde la nueva cuenta.

../../_images/multisig-1-of-2.png

Ejemplo de cuenta multisig 1-de-2

Prerrequisitos

  • Completa la sección de introducción.

  • Crea una nueva cuenta para convertirla en multisig.

  • Carga la cuenta con suficientes bitxor para pagar las tarifas de transacción.

  • Crea cuentas para Alice y Bob.

Note

Para crear nuevas cuentas, sigue esta guía.

Método #01: Usando la Billetera de Escritorio

  1. Inicia sesión en la cuenta que deseas convertir en una cuenta multisig.

  2. Haz clic en la pestaña “Multisig” en el menú de la izquierda.

  3. Haz clic en “Agregar un cosignatario” y proporciona la dirección o clave pública de la cuenta que deseas agregar como cosignatario de la multisig. Haz clic en el botón “+”.

resources/images/screenshots/create-multisig-2.gif
  1. Repite el paso 3 para cada cuenta que desees agregar como cosignatario de la multisig. En nuestro ejemplo, tenemos 2 cuentas que queremos agregar como cosignatarios: Alice y Bob.

  2. Selecciona el número mínimo de aprobaciones “Min. Approval” y eliminaciones “Min. Removal” para la multisig.

  3. Haz clic en “Enviar”. Revisa la información en el cuadro emergente. Proporciona la contraseña de tu billetera y haz clic en “Confirmar”.

resources/images/screenshots/create-multisig-3.gif
  1. Inicia sesión en una cuenta que seleccionaste como posible cosignatario de la multisig. En la página “Inicio”, haz clic en “Transacciones parciales”. Haz clic en la transacción agregada pendiente. Proporciona la contraseña de tu billetera y haz clic en “Confirmar”.

resources/images/screenshots/create-multisig-4.gif
  1. Repite el paso 7 para cada cuenta que agregaste como posible cosignatario de la multisig.

  2. Inicia sesión en la cuenta que se está convirtiendo en una multisig. Cuando la transacción agregada se complete (confirmada), puedes verificar que se haya convertido volviendo a la página “Multisig”.

resources/images/screenshots/create-multisig-5.png

Método #02: Usando el SDK

1. Primero, define las cuentas que se convertirán en cosignatarios de la cuenta multisig. Siguiendo nuestro ejemplo, estas son las direcciones de Alice y Bob. Luego, abre la cuenta que se convertirá en multisig utilizando su clave privada.

// replace with network type
const networkType = NetworkType.TEST_NET;
// replace with candidate multisig private key
const privateKey =
  'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
const account = Account.createFromPrivateKey(privateKey, networkType);
// replace with cosignatory 1 public key
const cosignatory1PublicKey =
  'D04AB232742BB4AB3A1368BD4615E4E6D0224AB71A016BAF8520A332C9778737';
const cosignatory1 = PublicAccount.createFromPublicKey(
  cosignatory1PublicKey,
  networkType,
);
// replace with cosignatory 2 public key
const cosignatory2PublicKey =
  '462EE976890916E54FA825D26BDD0235F5EB5B6A143C199AB0AE5EE9328E08CE';
const cosignatory2 = PublicAccount.createFromPublicKey(
  cosignatory2PublicKey,
  networkType,
);
// replace with network type
const networkType = bitxor_sdk_1.NetworkType.TEST_NET;
// replace with candidate multisig private key
const privateKey =
    'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF';
const account = bitxor_sdk_1.Account.createFromPrivateKey(
    privateKey,
    networkType,
);
// replace with cosignatory 1 public key
const cosignatory1PublicKey =
    'D04AB232742BB4AB3A1368BD4615E4E6D0224AB71A016BAF8520A332C9778737';
const cosignatory1 = bitxor_sdk_1.PublicAccount.createFromPublicKey(
    cosignatory1PublicKey,
    networkType,
);
// replace with cosignatory 2 public key
const cosignatory2PublicKey =
    '462EE976890916E54FA825D26BDD0235F5EB5B6A143C199AB0AE5EE9328E08CE';
const cosignatory2 = bitxor_sdk_1.PublicAccount.createFromPublicKey(
    cosignatory2PublicKey,
    networkType,
);

2. Crea una transacción de modificación de cuenta multisig para convertir la cuenta compartida en una cuenta multisig. Dado que queremos crear una cuenta multisig 1-de-2, establezcamos el número mínimo requerido de firmas en 1.

const multisigAccountModificationTransaction = MultisigAccountModificationTransaction.create(
  Deadline.create(epochAdjustment),
  1,
  1,
  [cosignatory1.address, cosignatory2.address],
  [],
  networkType,
);
const multisigAccountModificationTransaction = bitxor_sdk_1.MultisigAccountModificationTransaction.create(
    bitxor_sdk_1.Deadline.create(epochAdjustment),
    1,
    1, [cosignatory1.address, cosignatory2.address], [],
    networkType,
);

3. Crea una transacción de aggregate bonded, envolviendo la MultisigAccountModificationTransaction definida en el paso anterior. Esta acción es necesaria porque Alice y Bob deben optar por convertirse en cosignatarios de la nueva cuenta multisig.

const aggregateTransaction = AggregateTransaction.createBonded(
  Deadline.create(epochAdjustment),
  [multisigAccountModificationTransaction.toAggregate(account.publicAccount)],
  networkType,
  [],
  UInt64.fromUint(2000000),
);
const aggregateTransaction = bitxor_sdk_1.AggregateTransaction.createBonded(
    bitxor_sdk_1.Deadline.create(epochAdjustment), [multisigAccountModificationTransaction.toAggregate(account.publicAccount)],
    networkType, [],
    bitxor_sdk_1.UInt64.fromUint(2000000),
);
  1. Firma la AggregateTransaction utilizando la clave privada de la futura cuenta multisig.

Note

Para que la transacción sea válida solo para tu red, deberás pasar el primer hash de generación de red. Abre la URL del NODO /node/info en una nueva pestaña del navegador y copia el valor de meta.networkGenerationHash.

// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash =
  '1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = account.sign(
  aggregateTransaction,
  networkGenerationHash,
);
console.log(signedTransaction.hash);
// replace with meta.networkGenerationHash (nodeUrl + '/node/info')
const networkGenerationHash =
    '1DFB2FAA9E7F054168B0C5FCB84F4DEB62CC2B4D317D861F3168D161F54EA78B';
const signedTransaction = account.sign(
    aggregateTransaction,
    networkGenerationHash,
);
console.log(signedTransaction.hash);

5. Before sending an AggregateBondedTransaction, the future multisig account needs to lock at least 10 bitxor. This transaction is required to prevent spamming the network. After the HashLockTransaction has been confirmed, announce the AggregateTransaction signed in (4).

// replace with bitxor id
const networkCurrencyTokenId = new TokenId('5E62990DCAC5BE8A');
// replace with network currency divisibility
const networkCurrencyDivisibility = 6;

const hashLockTransaction = HashLockTransaction.create(
  Deadline.create(epochAdjustment),
  new Token(
    networkCurrencyTokenId,
    UInt64.fromUint(10 * Math.pow(10, networkCurrencyDivisibility)),
  ),
  UInt64.fromUint(480),
  signedTransaction,
  networkType,
  UInt64.fromUint(2000000),
);

const signedHashLockTransaction = account.sign(
  hashLockTransaction,
  networkGenerationHash,
);

// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new RepositoryFactoryHttp(nodeUrl);
const listener = repositoryFactory.createListener();
const receiptHttp = repositoryFactory.createReceiptRepository();
const transactionHttp = repositoryFactory.createTransactionRepository();
const transactionService = new TransactionService(transactionHttp, receiptHttp);

listener.open().then(() => {
  transactionService
    .announceHashLockAggregateBonded(
      signedHashLockTransaction,
      signedTransaction,
      listener,
    )
    .subscribe(
      (x) => console.log(x),
      (err) => console.log(err),
      () => listener.close(),
    );
});
// replace with bitxor id
const networkCurrencyTokenId = new bitxor_sdk_1.TokenId('5E62990DCAC5BE8A');
// replace with network currency divisibility
const networkCurrencyDivisibility = 6;
const hashLockTransaction = bitxor_sdk_1.HashLockTransaction.create(
    bitxor_sdk_1.Deadline.create(epochAdjustment),
    new bitxor_sdk_1.Token(
        networkCurrencyTokenId,
        bitxor_sdk_1.UInt64.fromUint(
            10 * Math.pow(10, networkCurrencyDivisibility),
        ),
    ),
    bitxor_sdk_1.UInt64.fromUint(480),
    signedTransaction,
    networkType,
    bitxor_sdk_1.UInt64.fromUint(2000000),
);
const signedHashLockTransaction = account.sign(
    hashLockTransaction,
    networkGenerationHash,
);
// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new bitxor_sdk_1.RepositoryFactoryHttp(nodeUrl);
const listener = repositoryFactory.createListener();
const receiptHttp = repositoryFactory.createReceiptRepository();
const transactionHttp = repositoryFactory.createTransactionRepository();
const transactionService = new bitxor_sdk_1.TransactionService(
    transactionHttp,
    receiptHttp,
);
listener.open().then(() => {
    transactionService
        .announceHashLockAggregateBonded(
            signedHashLockTransaction,
            signedTransaction,
            listener,
        )
        .subscribe(
            (x) => console.log(x),
            (err) => console.log(err),
            () => listener.close(),
        );
});

6. Cofirmar AggregateTransaction con CLI utilizando la cuenta de Alice. Reemplace el hash A6A374E66B32A3D5133018EFA9CD6E3169C8EEA339F7CCBE29C47D07086E068C con el hash AggregateTransaction registrado (4). .. code-block:: bash

bitxor-cli transaction cosign –hash A6A374E66B32A3D5133018EFA9CD6E3169C8EEA339F7CCBE29C47D07086E068C –profile alice

  1. Cosign the AggregateTransaction with Bob’s account.

bitxor-cli transaction cosign --hash A6A374E66B32A3D5133018EFA9CD6E3169C8EEA339F7CCBE29C47D07086E068C --profile bob

8. Si todo va bien, la cuenta ahora está configurada como multisig, siendo las cuentas Alice y Bob sus cosignatarios. Puede obtener la lista de las cuentas multisig donde Alice o Bob son cosignatarios con la función MultisigHttp.getMultisigAccountInfo().

// replace with multisig address
const rawAddress = 'BXRG6L-KWXRA7-PSWUEE-ILQPG4-3V5CYZ-S5652T-JTUU';
const address = Address.createFromRawAddress(rawAddress);

// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new RepositoryFactoryHttp(nodeUrl);
const multisigHttp = repositoryFactory.createMultisigRepository();

multisigHttp.getMultisigAccountInfo(address).subscribe(
  (multisigInfo) => console.log(multisigInfo),
  (err) => console.error(err),
);
// replace with multisig address
const rawAddress = 'BXRG6L-KWXRA7-PSWUEE-ILQPG4-3V5CYZ-S5652T-JTUU';
const address = bitxor_sdk_1.Address.createFromRawAddress(rawAddress);
// replace with node endpoint
const nodeUrl = 'NODE_URL';
const repositoryFactory = new bitxor_sdk_1.RepositoryFactoryHttp(nodeUrl);
const multisigHttp = repositoryFactory.createMultisigRepository();
multisigHttp.getMultisigAccountInfo(address).subscribe(
    (multisigInfo) => console.log(multisigInfo),
    (err) => console.error(err),
);
        // replace with node endpoint
        try (final RepositoryFactory repositoryFactory = new RepositoryFactoryVertxImpl(
            "NODE_URL")) {

            final MultisigRepository multisigRepository = repositoryFactory
                .createMultisigRepository();

            // replace with multisig address
            final String rawAddress = "BXRG6L-KWXRA7-PSWUEE-ILQPG4-3V5CYZ-S5652T-JTUU";
            final Address address = Address.createFromRawAddress(rawAddress);

            final MultisigAccountInfo multisigAccountInfo = multisigRepository
                .getMultisigAccountInfo(address).toFuture().get();

            final JsonHelper helper = new JsonHelperJackson2();
            System.out.println(helper.prettyPrint(multisigAccountInfo));

Siga la siguiente guía para modificar la cantidad de firmas requeridas.