Coinstack Multisig

1. Introduction

Bitcoin secured with Public Key Encryption is safe and handy, but there is a risk to lost all Bitcoins of an address when the PrivateKey of the address is lost. Indeed, an amount of Bitcoins could be confined by the lost private key. Also, if you don't save your private key safely and properly, you can lose your Bitcoins easily.

If the address can have multiple public keys and unlock with a couple of them, not all, it will not be a critical problem as mentioned above to lost just one key.

For instance, there is two public keys that are set up for an address, and the address can be unlocked by one of them. Let's store these keys separately. Even if one of the keys is lost, Bitcoins of the address can be used by the other key.

As another example, there is three public keys, and two keys should be provided to use Bitcoin. Let's assume that one of keys is saved in a market, the other is passed to a wallet-service company, and the last is in your hand. You don't have to bring the key by yourself, brcause other two keys are supported as a service. Additionally, even if you lost the key that was brought by yourself, you can send safely using other two keys. In another case, even if the wallet-service company had hacked by someone, you don't need to worry about the safeness of your Bitcoin.

This is Multisig that n number, n > 1, of public keys are set to use Bitcoin in an address, m number, n >= m >= 1, of public keys are used when to spend the Bitcoin.

2. Multisig Address

  1. Create P2SH Address

  2. Create Transaction for Bitcoin to P2SH Address

Multisig address, P2SH address must be created for Multisig. A public script of P2SH is like below.

Pubkey script: OP_HASH160 <Hash160(redeemScript)> OP_EQUAL

And, a redeem script as an input of the public script is like below.

Pubkey script: <m> <A pubkey> [B pubkey] [C pubkey...] <n> OP_CHECKMULTISIG

n number of public keys to create this transaction and value m to use this transaction should be provided.

Below is an example to create a redeem script with n = 3 and m = 2.

Java
// create a redeem script.
public void testRedeemScript() throws UnsupportedEncodingException, DecoderException {
    String publickey1 = "04a93d29a957d3e0064f6fde7a6c296e1ab2643f877d98ca5f52bdb9df43d3f70dfc040ee212b9bae63b2cf266ca677d31d72db53d1e928851d131d1cb9d9bde25";
    String publickey2 = "04c30518fb1d5f0e96ba9f262f31260c8ce02e322494436e4ccb0981ba687a1a2626ab30911ddad22023bcbdac1329fc73e999ff2836c608e9c8e405f4e6c0b615";
    String publickey3 = "04486a7c8754177b488982dcb13bd37fa6005a439dce55101c35ba3c5f60928036920e72a59429f0425967b735a1c52c9d2018a5ef4f63b8a8473ded4a29d5bad0";
    List<byte[]> pubkeys = new ArrayList<byte[]>(3);

    pubkeys.add(Hex.decodeHex(publickey1.toCharArray()));
    pubkeys.add(Hex.decodeHex(publickey2.toCharArray()));
    pubkeys.add(Hex.decodeHex(publickey3.toCharArray()));

    String redeemScript = MultiSig.createRedeemScript(2, pubkeys);
}

Below is an example to create P2SH address.

Java
// create P2SH Address
public static String createAddressFromRedeemScript(String redeemScript, boolean isMainNet) throws MalformedInputException {
    Script redeem = null;
    String from = null;
    try {
        redeem = new Script(Hex.decodeHex(redeemScript.toCharArray()));
    } catch (ScriptException e) {
        throw new MalformedInputException("Invalid redeem script", "Parsing redeem script failed");
    } catch (DecoderException e) {
        throw new MalformedInputException("Invalid redeem script", "Parsing redeem script failed");
    }
    from = createAddressFromRedeemScript(redeem, isMainNet);
    return from.toString();
}

When you want to send Bitcoin to this P2SH address, you can use like a normal address. When to spend, you have to provide a signature script with m number of private keys.

3. Multisig Transaction

When to spend Bitcoin of Multisig address, m number of private keys are provided as a list.

Java
public void testMultiSigTransaction() throws Exception {
    String privateKey1 = "5Jh46BhaJJeiW8C9tTz6ockGEgYnLYfrJmGnwYdcDpBbAvWvCbv";
    String privateKey3 = "5JSad8KB82c3XW69e1hz8g1YFFts4GTdjHuWHkh4d4A8MZWw12N";
    String redeemScript = "52410468806910b7a3589f40c09092d3a45c64f1ef950e23d4b5aa92ad4c3de7804ed95f0f50aca9ae928fb6e00223fad667693bf3e2b716dd6c9d474ad79f5b7a107e410494bae4aa9a4c2ca6103899098ca0867f62ca24af02fee2d6473a698d92fbc8c449aa2e236c0684ebb9e0fbb23d847d4624fd8ca4a1fdc940df432c6e312e18e84104cbc882d221f567005ea61aa45d5414f25371472f6ab5973e13a39a9edc26359b6980aa4f6f34cea62e82bbe13adc7fde9fc26bba2be2e7c5f8011a68bea39bae53ae";

    List<String> prikeys = new ArrayList<String>();
    prikeys.add(privateKey1);
    prikeys.add(privateKey3);

    String to = "1F444Loh6KzUQ8u8mAsz5upBtQ356vN95s";
    long amount = Math.convertToSatoshi("0.0039");
    long fee = Math.convertToSatoshi("0.0001");

    TransactionBuilder builder = new TransactionBuilder();
    builder.addOutput(to, amount);
    builder.setFee(fee);

    String signedTx = coinStackClient.createMultiSigTransaction(builder, prikeys, redeemScript);

    if (signedTx == null) {
        // Error.
    }

    coinStackClient.sendTransaction(signedTx);
}

4. Multisig Partial Sign

Multisig transaction needs m number of private keys, that is, you should know m number of private keys and use at once. However, the situation that you know all private keys and use them seems to be impossible. Can you give your private to another person?

Therefore, an incomplete transaction that is signed with only your private key can be made and sent. This is Multisig partial sign.

Below is an example to create a transaction with only one sign and send it.

Java
public void testPartialSignTransaction() throws Exception {
    String privateKey3 = "5JiqywVBWDphZbR2UWnUtj3yTX52LmGhnBy8gGED7GDdxzPuRaZ";
    String privateKey2 = "5J4ZadEdMs3zaqTutP1eQoKnCGKSYrUgkPwBZrk3hNmFiz7B6Ke";
    String redeemScript = "524104162a5b6239e12d3d52f2c880555934525dbb014dae7165380f77dcbf58b121b8033f59a1f7a4dcea589fc4405ac756542dfa393d53f7a559038f59b8d1084de541046a8fca1041f6ecf55aaa4e431b6c4ee72b51492330e777f2967697eb633e277eabf5d6e2ab3132b218a2d03b013ac90a80a4a2b5a27d1fa2a78cccad64d43b6f4104e850211b270fe7c97335411fcb774f6c7af0a8dd2e3360ba577e0c2979c51a375f5c256e2c8701d1b9777c15b7fc8b42af435977fe338e4a4e19683c884ad0fd53ae";
    String to = "1F444Loh6KzUQ8u8mAsz5upBtQ356vN95s";
    long amount = Math.convertToSatoshi("0.0001");
    long fee = Math.convertToSatoshi("0.0001");

    TransactionBuilder builder = new TransactionBuilder();
    builder.addOutput(to, amount);
    builder.setFee(fee);

    String incompleteTx = coinStackClient.createMultiSigTransactionWithPartialSign(builder, privateKey3, redeemScript);
    signedTx = coinStackClient.signMultiSigTransaction(incompleteTx, privateKey2, redeemScript);

    if (incompleteTx == null) {
        // Error.
    }

    coinStackClient.sendTransaction(incompleteTx);
}

results matching ""

    No results matching ""