Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bitcore Stream

Bidirectional payment channels for Bitcore.

Sender API

var channel = SenderChannel();

channel.id;
channel.balance;
channel.expiration;
channel.status; // new, open, closing, closed, expired
channel.fundingAddress;

channel.fund(utxo);
channel.pay(100, {data: 'some_data'});
channel.close(); // naming

channel.on('connected', {});
channel.on('disconnected', {});

channel.on('open', {});
channel.on('charge', {});
channel.on('expired', {});
channel.on('closed', {});

Sender API

var channel = ReceiverChannel();

channel.id;
channel.balance;
channel.expiration;
channel.status;
channel.fundingAddress;

channel.charge(100, {data: 'some_data'});
channel.close();

channel.on('connected', {});
channel.on('disconnected', {});

channel.on('open');
channel.on('payment');
channel.on('expired');
channel.on('closing');
channel.on('closed');

Payment Channel

Payment Script

OP_IF
    2 <PUBKEY1> <PUBKEY2> 2 OP_CHECKMULTISIG
OP_ELSE
    <TIME> OP_CLTV OP_DROP
    <PUBKEY1> OP_CHECKSIG
OP_ENDIF

Redeem Script 1 (multisig)

OP_TRUE <SIGNATURE1> <SIGNATURE2> OP_0

Redeem Script 2 (timeout)

OP_FALSE <SIGNATURE1>

HTLC Channel

Payment channel that allows proxy payments through it.

Open Transaction

Open Transaction

Inputs: UTXOs from A and B to fund the channel.

Output 1: A change address

OP_DUP OP_HASH160 <PUBKEY_HASH_A> OP_EQUALVERIFY OP_CHECKSIG

Output 2: B change address

OP_DUP OP_HASH160 <PUBKEY_HASH_B> OP_EQUALVERIFY OP_CHECKSIG

Output 3: A Channel Balance - Multisig or only A after 30 days.

OP_IF
    2 <PUBKEY_A> <PUBKEY_B> 2 OP_CHECKMULTISIG
OP_ELSE
    <30DAYS> OP_CLTV OP_DROP
    <PUBKEY_A> OP_CHECKSIG
OP_ENDIF

Output 4: B Channel Balance - Multisig or only B after 30 days.

OP_IF
    2 <PUBKEY_A> <PUBKEY_B> 2 OP_CHECKMULTISIG
OP_ELSE
    <30DAYS> OP_CLTV OP_DROP
    <PUBKEY_B> OP_CHECKSIG
OP_ENDIF

API

// Client side
var EXPIRATION = 80000; // Block Height

var utxos = [...];
var utxosPrivateKeys = [...];

var privKey = new bitcore.PrivateKey('...');
var pubKey = privKey.publicKey;
var inputBalance = utxos.reduce(x, total => x.amount + total, 0)
var channelBalance = 30000;

var otherPubkey = new bitcore.PublicKey('...');
var otherChannelBalance = 30000;
var otherChange = 10000;

var channelAddress = channelScript(pubKey, otherPubkey, EXPIRATION).toScriptHashOut().toAddress();
var otherChannelAddress = channelScript(otherPubkey, pubkey, EXPIRATION).toScriptHashOut().toAddress();

var openTransaction = new Transaction()
    .from(utxos)
    .to(myPrivKey.toAddress(), inputBalance - channelBalance)
    .to(otherPubkey.toAddress(), otherChange)
    .to(channelAddress, channelBalance)
    .to(otherChannelAddress, otherChannelBalance)
    .sign(utxosPrivateKeys, bitcore.crypto.Signature.SIGHASH_ANYONECANPAY)

var serialized = openTransaction.toObject();

function channelScript(pubkey1, pubkey2, height) {
    var sortedPubkeys = [pubkey1, pubkey2].sort(function(k1, k2) {
        return k1.toString() > k2.toString() ? 1 : -1;
    }));

    return Script.empty()
        .add('OP_IF')
          .add('OP_2')
          .add(sortedPubkeys[0].toBuffer())
          .add(sortedPubkeys[1].toBuffer())
          .add('OP_2')
          .add('OP_CHECKMULTISIG')
        .add('OP_ELSE')
          .add(BN.fromNumber(height).toScriptNumBuffer())
          .add('OP_CHECKLOCKTIMEVERIFY').add('OP_DROP')
          .add(pubkey1.toBuffer())
          .add('OP_CHECKSIG')
        .add('OP_ENDIF');
}

// Server side
var utxos = [...];
var utxosPrivateKeys = [...];

var privKey = new bitcore.PrivateKey('...');

var openTransaction = Transaction.fromObject(serialized)
    .from(utxos)
    .sign(utxosPrivateKeys)

assert(openTransaction.isFullySigned())

Credits

About

Hash TimeLocked Contracts for Bitcore (HTLC)

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages