0.0.2 • Published 2 years ago

@mit-dci/opencbdc v0.0.2

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

opencbdc-js

This is a pure JS node module which reads and writes the binary transaction packet formats used in opencbdc-tx. It also contains utilities to calculate UHS and transaction hashes from output data.

Getting Started

  • Clone the code
    $ git clone "https://github.com/mit-dci/opencbdc-js.git"
  • Install the necessary dependencies
    $ npm install
  • Run the test suite
    $ npm test

Contributing

Patches are welcome! Please see the OpenCBDC contribution guide for more information!

The following is a breakdown of sections and classes for this cbdc-module:

Crypto

  • Address

    • constructor(script_type, pubHex) - a new Address Object
      • script_type - {Number} representing the script type of the address
      • pubHex - {String} represents valid 32 byte hexadecimal string
    • getAddress() - returns {String} represented the bech32 encoding version of a publickey e.g.
    • decodeAddress() - returns {Object} with fields script_type (string representing) and pubHex (hex string of public key)

    • static decodeFromAddressString(address) - returns {Object} with fields script_type {Number} and pubHex {String} (hexdecimal string of public key)

  • Publickey

    • constructor(secretKeyData) - returns a new Publickey object
      • secretKeyData - {String} a valid 32 byte hexadecimal string
    • static fromPrivateKeyData(secretKeyData)
      • secretKeyData - {String} a valid 32 byte hexadecimal string
    • toBuffer() - returns {Buffer} 32 byte buffer publickey
  • Secretkey

    • contructor(randBytes) - returns new SecretKey with randBytes provided as random seed (if provided), otherwise it creates random key from random secrety bytes
      • randBytes - {Buffer} optional 32 bytes used to seed for privatekey, otherwise another random
    • toString() - returns {String} valid hexadecimal string of privatekey
    • toBuffer() - returns {Buffer} valid 32 byte Buffer for privatekey
    • static fromHex(secretKeyHex)- returns {SecretKey} from secretKeyHex
      • secretKeyHex - valid 32 byte hexadecimal string for privateKey
    • toHex() - returns hexadecimal representation of privateKey

Networking

  • Networking
    • broadcastTx(port, host, signedTxHex) - broadcast a signedTxBuf to a sentinel server at host {host} and port {port} number
      • port - {number} port number of host
      • host - {string} hostname url to send signedTx
      • signedTxHex - {string} a valid hexadecimal encoded transaction that has been signed

Transaction

  • Input
    • constructor(tx_hash, index, witnessProgramCommitment, value) returns new Input Object Type
      • tx_hash - {String} valid hexadecimal string for transaction hash this input references
      • index - {number} index position of the input for tx
      • witnessProgramCommitment {String} - witness commitment for this input
      • value {number} - the number of dollar units this input is worth
    • writeInputToBuffer() - returns Buffer representation as buffer type
    • getUHSHash() - returns {Buffer} Universal Hash Set hash of the input e.g. concatentation of [txid, index, witnessProgramCommitment, value] into bytes e.g.
    • toString() - returns {String} representing valid input

Utils

  • Utility Methods CBDC module
    • sign(secretKey, message) - returns signature that signed message {message} with privateKey {privateKey}
      • secretKey - {String} - 32 byte hexadecimal string
      • message - {String} - message that is signed
    • verify(publicKey, message, signature) returns true or false whether the produced signature is validly signed publicKey
      • publicKey - 32 byte hexadecimal string
      • message - message to verify was signed
      • signature - {String} signature to verify validly signed message against public key message pair

N.B.: A hash is used to identify a specfic UTXO within the monetary supply (the UHS ID); it is a concatenation of a txid, a 64-bit index of the UTXO's position in previous tx's outputs, a witnessProgramCommitment, and the 64-bit encoded value of that output

  • Output

    • constructor(witnessProgramCommitment, value) returns new Output Object type
      • witnessProgramCommitment - {String}
      • value - {Number}
    • writeOutputToBuffer() - returns a Buffer representation of this output in raw bytes
    • static fromOutputData(pubHex, value) - returns a new {Output} from publicKey and value provided
      • pubHex - {String}
      • value - {Number}
    • toString() - returns {String} string representation of Output
  • Transaction

    • constructor(inputs, outputs, witnesses) - returns new {Transaction} object
      • inputs - Array{Input}
      • outputs - Array{Output}
      • witnesses - Array of witness object
    • toHex() - returns {String} hexadecimal string of the unsigned raw transaction
    • getTxid() - returns {String} returns hexadecimal string of transaction id (txid)
    • sign(secretKey) - returns {Buffer} signed tx in bytes
    • static txFromHex(rawHex) - returns {Transaction} object from the provided rawTx
      • rawHex - valid hexadecimal string represents a valid tx

Special Notes

BigInt is used everywhere throughout this module, that may pose problems in using toJson() methods or serializing for output

Example Usage

The following are example code snippets.

  • Address

    const addr = new Address('00', '3ad8f015f9212f8262248af4cf4cc39907d0215fdde14507f8bc09ad5836bbe9')
    
    console.log(addr.getAddress()); 
    usd1qqad3uq4lysjlqnzyj90fn6vcwvs05pptlw7z3g8lz7qnt2cx6a7jty6gr5
    
    console.log(addr.decodeAddress());
    
    { script_type: 0, pubHex: '3ad8f015f9212f8262248af4cf4cc39907d0215fdde14507f8bc09ad5836bbe9' }
  • Publickey

    const pub = new Publickey('e00b5c3d80899217a22fea87e7337907203df8a1efebd4d2a8773c8f629fff36')
    console.log(pub.toBuffer());
  • Secretkey

    const secKey = new SecretKey(Buffer.from(parseInt(Math.round(Math.random() * 10)), 'hex'));
    secKey.toString();
    secKey.toBuffer();
  • Networking

    let network = require('./networking/broadcast');
    const txBuf = new Transaction();
    Networking.broadcastTx(5555, '127.0.0.1', Buffer.from(tx.toHex(), 'hex'))
  • Transaction

    const input = new Input('9f981e64afc0fc56a0d7b355cd9eba36f3d19507088713b1f73afc5bf301a44e', 0, '70cd87ebaaa0d2d059dccaceeb7f9f823a5791d60b00aef9d9573f1fbf91ca29', 200)
    const output = new Output('81b095a242974d9f4e98ca18b468b8e644e4168380a035b3d66bc279b36c6510', 200)
    const tx = new Transaction([input], [output], []);
    tx.sign('e00b5c3d80899217a22fea87e7337907203df8a1efebd4d2a8773c8f629fff36')
    console.log(tx.getTxid());
    
    12e01dfa90358fd203da3acbbe105b1ed2d249cd8e601ed919f4b8b2a99cbb02
    
    console.log(tx);
    01000000000000009f981e64afc0fc56a0d7b355cd9eba36f3d19507088713b1f73afc5bf301a44e000000000000000070cd87ebaaa0d2d059dccaceeb7f9f823a5791d60b00aef9d9573f1fbf91ca29c800000000000000010000000000000081b095a242974d9f4e98ca18b468b8e644e4168380a035b3d66bc279b36c6510c80000000000000001000000000000006100000000000000003ad8f015f9212f8262248af4cf4cc39907d0215fdde14507f8bc09ad5836bbe901986cc97272bdb7624a824afcef76936b8f945e55d6e8479b95c81298e77b42d5a255e8529fc2f0d90743e7f9997a7159b6121105c7ec9b9252da992f34611f
    • Constructing, signing and broacasting tx to sentinel

      const secretKey = 'e00b5c3d80899217a22fea87e7337907203df8a1efebd4d2a8773c8f629fff36';
      
      const input = new Input('9f981e64afc0fc56a0d7b355cd9eba36f3d19507088713b1f73afc5bf301a44e', 0, '70cd87ebaaa0d2d059dccaceeb7f9f823a5791d60b00aef9d9573f1fbf91ca29', 200)
      const output = new Output('81b095a242974d9f4e98ca18b468b8e644e4168380a035b3d66bc279b36c6510', 200)
      const tx = new Transaction([input], [output], []);
      
      tx.sign(secretKey);
      
      Networking.broadcastTx(5555, '127.0.0.1', Buffer.from(tx.toHex(), 'hex'))
    • Signing and Verifying

      const secretKey = "e00b5c3d80899217a22fea87e7337907203df8a1efebd4d2a8773c8f629fff36";
      const publicKey = "3ad8f015f9212f8262248af4cf4cc39907d0215fdde14507f8bc09ad5836bbe9";
      const sha256 = function () {...};
      const message = 'onomatopoeia';
      
      const sig = utils.sign(secretKey, message);
      utils.verify(publicKey, Buffer.from(sha256(message), 'hex'), sig);

Sample Data

Secret and Related Public Key

secret key: e00b5c3d80899217a22fea87e7337907203df8a1efebd4d2a8773c8f629fff36
public key: 3ad8f015f9212f8262248af4cf4cc39907d0215fdde14507f8bc09ad5836bbe9

Signed Transaction

01000000000000009f981e64afc0fc56a0d7b355cd9eba36f3d19507088713b1f73afc5bf301a44e000000000000000070cd87ebaaa0d2d059dccaceeb7f9f823a5791d60b00aef9d9573f1fbf91ca29c800000000000000010000000000000081b095a242974d9f4e98ca18b468b8e644e4168380a035b3d66bc279b36c6510c80000000000000001000000000000006100000000000000003ad8f015f9212f8262248af4cf4cc39907d0215fdde14507f8bc09ad5836bbe901986cc97272bdb7624a824afcef76936b8f945e55d6e8479b95c81298e77b42d5a255e8529fc2f0d90743e7f9997a7159b6121105c7ec9b9252da992f34611f

Signed Transaction Decoded

Tx {
  inputs: [
    {
      tx_hash: '9f981e64afc0fc56a0d7b355cd9eba36f3d19507088713b1f73afc5bf301a44e',
      index: 0n,
      witness_program_commitment: '70cd87ebaaa0d2d059dccaceeb7f9f823a5791d60b00aef9d9573f1fbf91ca29',
      value: 200n
    }
  ],
  outputs: [
    {
      witness_program_commitment: '81b095a242974d9f4e98ca18b468b8e644e4168380a035b3d66bc279b36c6510',
      value: 200n
    }
  ],
  witnesses: [
    {
      witness_length: 97n,
      script_type: 0,
      pubkey: '3ad8f015f9212f8262248af4cf4cc39907d0215fdde14507f8bc09ad5836bbe9',
      signature: '01986cc97272bdb7624a824afcef76936b8f945e55d6e8479b95c81298e77b42d5a255e8529fc2f0d90743e7f9997a7159b6121105c7ec9b9252da992f34611f'
    }
  ]
}