Happy Holidays 2021

How it works

To understand how this app is implemented one first has to understand what is P2TH.

http://peercoin.github.io/P2TH/

P2TH is essentially an address derived from something mutually agreed on. You can derive address from anything, ranging from a string to a number. It’s all numbers anyway and computers are good with numbers. For example a string like “battery powered horse”. When such address is derived we are sending every transaction of his application to p2th address as vout[0] (first output), because that is our tag address.
Cool thing about Peercoin protocol is that it allows for zero value outputs, so you can send 0 coins to this tag address. Which makes using tags as cheap as possible.

Now one can query all incoming transactions on the p2th address and get a list of all transactions which contain some data we are looking for. This is much more efficient than parsing the entire chain transaction by transaction.

P2TH allows for cheap and easy lookup of relevant transactions on a public blockchain without sifting through hundreds of even thousands of transactions while looking for what is relevant to some dapp.

This is why we are able to implement an app like this peercoin.holiday in mere hours and without need for servers of any sort. Client app like this can run of github pages or similar (cloudfare pages) and query the chain through blockexplorer API or electrum server API.

Code example

const bitcore = require('bitcore-lib');

//
// Add peercoin network params
//

bitcore.Networks.add({
    name: 'peercoin',
    alias: 'ppcoin',
    pubkeyhash: 0x37,
    privatekey: 0xb7,
    scripthash: 0x75,
    xpubkey: 0x0488b21e,
    xprivkey: 0x0488ade4,
  });

bitcore.Networks.add({
    name: 'peercoin-testnet',
    alias: 'ppcoin-test',
    pubkeyhash: 0x6f,
    privatekey: 0xef,
    scripthash: 0xc4,
    xpubkey: 0x043587cf,
    xprivkey: 0x04358394,
  });


// set peercoin-testnet as default network
bitcore.Networks.defaultNetwork = bitcore.Networks.get('peercoin-testnet');


// derive P2TH address
const value = Buffer.from('battery powered horse!'); // we are making the private key from this random string
const hash = bitcore.crypto.Hash.sha256(value);
const bn = bitcore.crypto.BN.fromBuffer(hash);
const privateKey = new bitcore.PrivateKey(bn);
const P2TH_address = privateKey.toAddress(); // we have made an address from the string above

console.log("This is my address: ", P2TH_address.toString()); // this is the P2TH address 

// Now all transactions of this dapp should have vout[0] to this p2th address

// txn should be something like this
// vout[0] = p2th address 
// vout[1] = op_return data
// vout[2] = change (myAddress)
const transaction = new bitcore.Transaction()
    // Expects an array of utxos 
    .from(utxo)
    .feePerKb(10000) // data on Peercoin costs 0.01 PPC / kB
    .to(p2th_address, 0) // no need to send any coins to p2th
    .addData(data_string) // Add data if you want
    .change(myAddress) // change to your address
    .sign(privateKey);

// Overriding txn version to 3, because that's what it needs to be to work with peercoin
transaction.version = 3;

// we are sending everything to p2th address, because that is our tag address. Now one can query all incoming transactions on p2th address and get a list of all transactions which contain data we are looking for. This is much more efficient than parsing the entire chain transaction by transaction.

// Disable dust output warning so it doesn't complain about p2th output
const txHex = transaction.serialize({disableDustOutputs: true});
console.log(txHex);

3 Likes