Alvin Yyers forms a cartel to protect Bitcoin Cash
In an unexpected turn, Bitcoin SV proponent Alvin Yyers unites miners to protect Bitcoin Cash, as the coin is expected to plummet to new hash rate lows.
*"Bitcoin Cash will be the first coin to reach block reward halving. Without us, the coin will be in trouble. We're here to defend it."* Alvin tells NerdGeek in an exclusive interview.
Alvin emphasizes that Bitcoin Cash is not the real Bitcoin, not anymore.
*Bitcoin Cash is Bitcoin Cash, it does not scale and does not follow the original white paper. It will eventually be dwarfed by the real Bitcoin, Bitcoin SV. For now it's a useful tool to help global adoption.*
In return for protecting the chain, the cartel will receive protection money in the form of mere 12.5% of all coinbase rewards.
*It's a small price to pay for chain protection. It will only last 6 months, while we wait for other coins to reach their block reward halving ..*
Already a 12.5% claim
Alvin looks surprised, as NerdGeek tells him that there is already a claim for 12.5% of the mining reward by a different mining cartel.
*The Chinese have always been good at espionage and copying. But I never expected them to be so fast and efficient.*
After some thinking, he concludes that it's not an issue. On the contrary, it makes his cartel even more important. With now claims on 25% of the block reward, the cartel protection is even more important.
*There still remains 75% of the block reward to miners that solve the blocks. This still brings enough external hash power, that our two mining cartels combined can easily protect the chain.*
The Bitcoin Cash reference client
NerdGeek reached out to Bitcoin SBC, the reference client of Bitcoin Cash. A spokesperson for the client had the following to say:
*While we wait for all the sha256d coins to reach their reward halving, Bitcoin Cash will need all the reorg protection it can get. According to my calculations, with this arrangement, the BTC miners will take the most cost.* ***The game theory is solid****.*
Bitcoin SV is the real Bitcoin
The genesis protocol upgrade will make history. We're making Bitcoin what Satoshi Nakamoto envisioned and still envisions today.
*The protection money will also help promote the real Bitcoin. I throw the wildest parties you know. I have a reputation to uphold.*
Calling it tax is okay
Proponents of a the new consensus rule, where 12% of the miners earned reward is *required* to be sent to a hong kong shell company, *do not want to you call it tax*.
Their argument is that no state violence happens if you do not include this reward. Cops will not come knocking down some miners door that claims his entire reward for himself.
And they are correct. They are technically correct. The best kind of correct.
To most of us, **tax** is something we are forced to pay, supposedly out of necessity to maintain our local community.
When we're late on tax, cops don't come to our house. We're charged with late fees. The state threatens to dissolve our company. We are economically punished.
When a miners block is orphaned, they are economically punished. Before their block is mined, they are economically threatened to have their block orphaned.
This concept of taking a claim from another miners reward is new. We don't have a word for it. So for lack of a better word, it's okay to call it *tax*. The word describes the concept well, well enough. The word *tax* is also negative to most of us, and as such it may also describes how we feel about it.
What shall we call it if not tax?
We don't have a good word for it. Proponents will name it something less negative sounding, such *a "service fee for the miners"*. They may also make it sound positive. The zcash community has a name for the concept that gives me a chuckle, they call it *"Founders' Reward".*
Opponent may not want to call it tax either. The word tax may rub them the wrong way.
Whether you are opponent or proponent, if you have a good word for the concept, share it with me in the comments. When discussing, I'd suggest we don't get hung up on what the concept is called. Try to see past the word used.
But it's okay too, to have a chuckle at absurd names for this concept.
Quickly creating lots of UTXO's with Electron Cash
If you tend to run into the transaction chain limit, or run out of shuffled coins, it's time to split up your coins. Electron Cash has a largely undocumented, but powerful Python console. The source code is the best documentation, so look at the source code. https://github.com/Electron-Cash/Electron-Cash/blob/master/lib/commands.py
The console tab is not visible by default, so if you haven't, you can add it by going to `View -> Show console`.
*Disclamer: The console is powerful and lets you shoot yourself in the foot, don't blame me if you do that!*
Here's an example of how to create **5 new utxos** using the console:
Create 5 new addresses
>> addresses = [createnewaddress() for _ in range(5)]
>> print(addresses)
['qqzq5xmrwzp6u8pwddsnddzphrrqjk336vskk2g0de', 'qps0ax66rzde56qvg39qymn7wnelp2ftdus9yaj5ew', 'qq4352kp6wedd7fnhcpvjcayha5hfsawq5kjc5c4ud', 'qravjyev5cl6xvqldxqfurwsyqgptey0qvpp3543l0', 'qzatvg72ve63q6c38u64xtl8paktyux03v0vlm4dc3']
Create the outputs for sending 0.0001BCH to each address
>> outputs = [[addr, 0.0001] for addr in addresses]
>> print(outputs)
[['qqzq5xmrwzp6u8pwddsnddzphrrqjk336vskk2g0de', 0.0001], ['qps0ax66rzde56qvg39qymn7wnelp2ftdus9yaj5ew', 0.0001], ['qq4352kp6wedd7fnhcpvjcayha5hfsawq5kjc5c4ud', 0.0001], ['qravjyev5cl6xvqldxqfurwsyqgptey0qvpp3543l0', 0.0001], ['qzatvg72ve63q6c38u64xtl8paktyux03v0vlm4dc3', 0.0001]]
Create the transaction
>> tx = paytomany(outputs)
>> print(tx)
{'hex': '01000000017851d81132a94a0f5e0495169e1021cdbcecc7100312f888898597db89346eb70100000064412aaab95d84dc3a57385bde9a70f60cc0613e68b5b216604f7f3cb96e639e6a95130b51933fecbdfdb18426560986131e728add05de3e3f5afbbcf72b9cf9516841210203401e4cb7260fc1f594e2719cf2b49e39abd1edb0870ae5586057583884f384feffffff0610270000000000001976a914040a1b637083ae1c2e6b6136b441b8c6095a31d388ac10270000000000001976a9142b1a2ac1d3b2d6f933be02c963a4bf6974c3ae0588ac10270000000000001976a91460fe9b5a189b9a680c444a026e7e74f3f0a92b6f88ac10270000000000001976a914bab623ca6675106b113f35532fe70f6cb270cf8b88ac10270000000000001976a914fac9132ca63fa3301f69809e0dd0201015e48f0388ac486b0100000000001976a9142f181a2ff7c44b1e678e53fe2e689c6b56c8bb1d88acb8710900', 'complete': True, 'final': True}
>>
Broadcast the transaction
>> broadcast(tx)
[
true,
"8f298905d530b41ae5588588c48a76aaf7f5abea86ed3b0d500682c76df08138"
]
The result
If you go back to the History tab, you should see a new transaction. Right click for details. It will look something like this:
[sponsors]

How to Split and Forward Bitcoin Cash with Python
This code snippet is a bit longer than what I usually write here. That is because this time, we're writing a fully working program.
This is a program that:
Listens and reacts to receiving coins in a brainwallet. https://read.cash/@cashdev/creating-a-brainwallet-with-python-03758c0e
Creates a new transaction, forwarding all the received coins to two different donation addresses, splitting them 50/50
Broadcasts the new transaction to the network
And to do this, we'll be **creating a transaction ground up** using the **raw Bitcoin data structures**, signing the inputs **with Schnorr signatures** and communicating with the blockchain using the **public Electrum network**.
You'll also see a method for calculating the transaction fee for your transaction, achieving exactly 1 satoshi per byte every time.
We're using the bitcoincash Python library. https://bitcoincash.network/python/
*Disclamer: Use this guide at own risk. Remember that it's easy to mess up transactions in various ways, for example by spending all coins to miner fees.*
**TL;DR:** **Here is the full program****. Below I'll cover it section by section**. https://gist.github.com/dagurval/d34076523a6ebb794c1ee6822e5fa26c
DEMO!
https://asciinema.org/a/291635
Demo using insecure brainwallet! Don't do this at home. Any coins sent to the above QR code will get stolen.
Here is the transaction in a blockchain explorer https://explorer.bitcoin.com/bch/tx/60af59e9404c9a1d9119e45b3059cc55151181f09f4df3b80f7d877d252f4e54
Step 1) The boilerplate imports
We start by importing all the stuff we'll use. Lets also define the two addresses we'll be forwarding to. These were fetched from EatBCH Venezuela and EatBCH South Sudans twitter profiles. https://twitter.com/eatbch_ve https://twitter.com/eatbch_ss
import hashlib
import qrcode
import asyncio
from bitcoincash.core import b2x, lx, COutPoint, CMutableTxOut,\
CMutableTxIn, CMutableTransaction
from bitcoincash.core.script import CScript, SignatureHash, OP_RETURN, \
SIGHASH_ALL, SIGHASH_FORKID
from bitcoincash.core.scripteval import VerifyScript
from bitcoincash.wallet import CBitcoinAddress, CBitcoinSecret, P2PKHBitcoinAddress
from bitcoincash.electrum import Electrum
EATBCH_VE = "bitcoincash:pp8skudq3x5hzw8ew7vzsw8tn4k8wxsqsv0lt0mf3g"
EATBCH_SS = "bitcoincash:qrsrvtc95gg8rrag7dge3jlnfs4j9pe0ugrmeml950"
Step 2) The main loop
We create a private and public key with a super insecure brain wallet phrase, encode the public key in a cashaddr and print out the QR code. After that, we enter the never ending forwarding loop. https://read.cash/@cashdev/creating-a-brainwallet-with-python-03758c0e
async def main():
# Connect to an Electrum server
cli = Electrum()
await cli.connect()
# Create an insecure brainwallet
h = hashlib.sha256(b'replace this please or get coins stolen').digest()
private_key = CBitcoinSecret.from_secret_bytes(h)
address = P2PKHBitcoinAddress.from_pubkey(private_key.pub)
# Output a QR code for the address in the terminal
qr = qrcode.QRCode()
qr.add_data(str(address).upper())
qr.print_ascii()
print(str(address))
try:
while True:
await forward_loop(cli, private_key, address)
import time
time.sleep(5)
finally:
await cli.close()
Notice that we upper case the cashaddr in the QR code. Upper case cashaddr are also valid, and by upper casing them, the data load can be encoded differently, making the QR code smaller, simpler and easier to scan.
Step 3) The forward loop
This is where the magic happens. We'll be:
Checking if we've received coins
Creating a blank transaction
Adding all received coins as inputs to the transaction
Adding the EatBCH addresses at outputs
Signing the inputs with Schnorr
Broadcasting the transaction
async def forward_loop(cli, private_key, address):
# Get list of spendable coins in address
coins = await cli.RPC(
'blockchain.scripthash.listunspent',
address.to_scriptHash())
if not len(coins):
return
By calling `blockchain.scripthash.listunspent` we're asking the electrum server if there are any coins sent to our address, that have yet to spend. If non, we just return to the mail loop.
Before we go forward, note that `CTransaction`, `CTxIn`, `COutPoint`, `CTxOut` and `CScript` are all basic building blocks of the Bitcoin protocol. You will find the same data structures in all full nodes. In any code derived from Satoshis code base, they'll even have the same name. When there is *Mutable* in the name, it just means they are not read only, we're allowed to modify them.
I believe its worthwhile to get familiar with these data structures, as you'll encounter them a lot when working with Bitcoin.
tx = CMutableTransaction()
# Store input amounts for later
amounts = []
# All coins received as inputs
for c in coins:
tx_input = CMutableTxIn(COutPoint(lx(c['tx_hash']), c['tx_pos']))
# This dummy scriptSig makes fee calculation simple.
# We know that the Schnorr signature exactly 65 bytes.
tx_input.scriptSig = CScript([b'0' * 65, private_key.pub])
tx.vin.append(tx_input)
amounts.append(c['value']) # store for later
We create a blank transaction and append our coins as input. We don't need the coin amount yet.
Our scriptSig will proof that we can and want to send these coins, and we'll replace it later after building the full transaction. But for now, adding a dummy placeholder that is the same size as the final scriptSig will help us calculate the transaction fee.
# Dummy output amount (nValue). We need to calculate fee
# before setting the actual amount.
for addr in (CBitcoinAddress(EATBCH_VE), CBitcoinAddress(EATBCH_SS)):
tx_output = CMutableTxOut(nValue = -1, scriptPubKey = addr.to_scriptPubKey())
tx.vout.append(tx_output)
# For fun, let's add a small OP_RETURN greeting as well
tx.vout.append(CMutableTxOut(nValue = 0, scriptPubKey = CScript(
[OP_RETURN, b'Happy new year 2020!'])))
We add our outputs, which are the two EatBCH addresses. For fun, we can add a third dummy OP_RETURN output to encode a small greeting.
We can't add the amounts we're sending yet, because we've yet to calculate the transaction fees. Now that we've created the transaction, we can calculate the fee.
total = sum(amounts)
fee = len(tx.serialize())
if total - fee < 2000:
# The amount is tiny, lets wait for more coins
return
Yep, that was easy. Find how many bytes the serialized transaction takes. Use that as fee. That makes it one satoshi per byte.
# Update output values
total -= fee
half = total // 2 # // is integer division
tx.vout[0].nValue = half # EatBCH VE
tx.vout[1].nValue = half # EatBCH SS
After subtracting the fee, we need to update the outputs. In this program, we choose to split them between the two outputs.
# Hash and sign inputs
flags = SIGHASH_ALL | SIGHASH_FORKID
for i in range(0, len(tx.vin)):
sighash = SignatureHash(
address.to_scriptPubKey(),
txTo = tx,
inIdx = i,
hashtype = flags,
amount = amounts[i])
signature = private_key.signSchnorr(sighash) + bytes([flags])
tx.vin[i].scriptSig = CScript([signature, private_key.pub])
# Optional, but useful for developers: Verify that the input is valid.
VerifyScript(
tx.vin[i].scriptSig,
address.to_scriptPubKey(),
tx, i, amount = amounts[i])
Now all that remains is to sign the inputs with Schnorr.
Hash the transaction
Sign the hash value
Update the scriptSigs with the signature
# We're playing with money here, so lets assert for safety.
# + 1 off is OK because of the integer division above.
assert sum(o.nValue for o in tx.vout) + 1 + fee >= sum(amounts)
assert len(tx.serialize()) == fee # 1 sat/byte fee
print("Received {} satoshis in {} coins!\n"\
"Forwarding {} to EatBCH VE and {} to EatBCH SE. Tx fee {}.".format(
sum(amounts), len(coins), tx.vout[0].nValue, tx.vout[1].nValue, fee))
# Done! Broadcast to the network.
print("Broadcasting transaction...")
print("Result: {}".format(
await cli.RPC('blockchain.transaction.broadcast', b2x(tx.serialize()))))
Finally, we do some sanity checks and then broadcast our transaction to the Bitcoin Cash network.
Now that we've gone through this step-by-step, you should be able to understand **the full program****.** https://gist.github.com/dagurval/d34076523a6ebb794c1ee6822e5fa26c
If you found this interesting, let me know. Subscribe and comment. Thanks!
[sponsors]
Creating a brainwallet with Python
Using a brainwallet is a terrible idea. We humans are terrible at creating phrases that cannot be easily brute force attacked.
Using a brainwallet is a terrible idea and you're likely to loose all your coins.
But its also awesome and convenient when developing and testing.
What's a brainwallet?
A brainwallet is simply a text phrase, such as `steal these coins` that is encoded into a private key. Encoded with sha256 and some magic –`sha256("steal these coins")`.
Creating a brainwallet with Python
...using the libraries bitcoincash and qrcode https://bitcoincash.network/python/ https://pypi.org/project/qrcode/
from bitcoincash.wallet import CBitcoinSecret, P2PKHBitcoinAddress
import hashlib
def calculate_brainwallet(phrase):
h = hashlib.sha256(phrase).digest()
private_key = CBitcoinSecret.from_secret_bytes(h)
address = P2PKHBitcoinAddress.from_pubkey(private_key.pub)
return address, private_key
SECRET_PHRASE = b'secret phrase replace or loose all coins'
cashaddr, privkey = calculate_brainwallet(SECRET_PHRASE)
For extra convenience, output the addresses as QR codes in the terminal
def print_qrcode(data):
import qrcode
qr = qrcode.QRCode()
qr.add_data(data)
qr.print_ascii()
print_qrcode(str(cashaddr))
print(f"Cashadddr: {cashaddr}")
print_qrcode(str(privkey))
print(f"Private key: {privkey}")
[sponsors]
Electrum RPC with Python — Trust a stranger (or SPV verify)
Running your own full node is not always the best option, so a full nodes RPC interface is not exactly readily available.
You can still interact with the Bitcoin Cash blockchain using public Electrum servers.
Here is a code snippet using the bitcoincash Python library that fetches the block header of block *613880*. https://bitcoincash.network/python
$ cat test.py
from bitcoincash.electrum import Electrum
from bitcoincash.core import CBlockHeader, x
import asyncio
async def electrum_stuff():
cli = Electrum()
await cli.connect()
header_hex = await cli.RPC('blockchain.block.header', 613880)
header = CBlockHeader.deserialize(x(header_hex))
print(f"Received header: {header}")
await cli.close()
loop = asyncio.get_event_loop()
loop.run_until_complete(electrum_stuff())
loop.close()
And when ran:
$ python3 test.py
Received header: CBlockHeader(545259520,
lx(000000000000000002e937da590fdc4325da13c250f26a73343d635913467019),
lx(f9acfe3f0e98fc321123f787e21e17984998f46866d30244328bf7552051d57a),
1576668009, 0x18030793, 0x34e3adb0)
Full list of Electrum RPC methods are documented by ElectrumX. https://electrumx.readthedocs.io/en/latest/protocol-methods.html
In this code snippet, we're trusting the server to provide us with correct the information. That may be fine for your use case. Or perhaps you or a friend are running your own electrum server, which you trust.
Electrum servers still provide enough data to give you SPV security, so you don't have to trust the public server. You can verify. Should I write articles about SPV verifying blockchain data? Comment below.
[sponsors]
«What are the addresses involved in this transaction?» using Python
**A Bitcoin Cash transaction contains no addresses**, yet whenever we're presented with a transaction in a graphical interface, we always get to see the addresses involved. Let's find a recent transaction in a block explorer:
Tech used
I use the python bitcoincash library, in addition I have a full node running that supports the satoshi client RPC interface. In this case Bitcoin Unlimited. https://pypi.org/project/bitcoincash/
How to find the Bitcoin Cash address
We need to **derive the addresses from the transaction outputs**. Let's have a look at the above transaction:
import bitcoincash.rpc
from bitcoincash.core import lx
TX_ID = "07cca646b20b27f2e2385bb9ed63663220b80abe8380072973eef078a1d6f51e"
rpc = bitcoincash.rpc.Proxy()
tx = rpc.getrawtransaction(lx(TX_ID))
print(tx.vout)
$ python3 test.py
(CTxOut(0.00005299*COIN,
CScript(
[OPDUP, OPHASH160, x('b1f1ec3aa28f212cdbb32269f33e6d0ecbc8364c'),
OPEQUALVERIFY, OPCHECKSIG])),)
The `CScript` here is the `ScriptPubKey` of the transaction output. It looks like the most common used script in Bitcoin Cash, the Pay-to-PubKey Hash (P2PKH).
Pay-to-PubKey Hash has the standard template `OPDUP OPHASH160 <pubKeyHash> OPEQUALVERIFY OPCHECKSIG`. **And this can be represented as a Bitcoin Cash address.**
The python library has a built in function to derive this, continuing the script above:
from bitcoincash.wallet import CBitcoinAddress
print("Outputs:")
for o in tx.vout:
print(str(CBitcoinAddress.from_scriptPubKey(o.scriptPubKey)))
$ python3 test.py
Outputs:
bitcoincash:qzclrmp6528jztxmkv3xnue7d58vhjpkfsr4uskz69
But what about the inputs?
The transaction pretty much only contains pointers to previous transaction and no other info. So to find the input addresses, we need to fetch the parent transactions to get their `scriptPubKey`.
print("Inputs:")
for i in tx.vin:
prevout = i.prevout
prevtx = rpc.getrawtransaction(prevout.hash)
script_from_input = prevtx.vout[prevout.n].scriptPubKey
print(str(CBitcoinAddress.from_scriptPubKey(script_from_input)))
$ python test.py
Outputs:
bitcoincash:qzclrmp6528jztxmkv3xnue7d58vhjpkfsr4uskz69
Inputs:
bitcoincash:qzcnx0z2l9ncs7el5fcwgufv4mrng605ngc8p5csqn
Hurray!
**Wow! You made it to the end, thanks for reading!**
[sponsors]
«Is it an SLP transaction?» using Python
Here is a quick and crude way to check if an transaction is likely an SLP transaction. It can be a transaction that sends a SLP token, creates one, mints more or whatever.
We don't check that its valid, or if what it's doing is valid, we just want to flag it as potentially SLP.
Here's how you do it:
# OPRETURN [PUSH 4] S L P 0x00
SLP_PREFIX = bytearray(b"\x6a\x04\x53\x4c\x50\x00")
def has_slp_output(outputs):
for o in outputs:
if o.scriptPubKey.startswith(SLP_PREFIX):
return True
return False
This uses the python library python-bitcoincash. To install, run `pip install bitcoincash` (replace `pip` with `pip3` if you're on Debian/Ubuntu to use Python 3) https://pypi.org/project/bitcoincash/
What magic is this?
SLP token transaction all have an *OP_RETURN* output. This output also starts with the 4 byte prefix *SLP0*. So all we need to do is check for this byte prefix.
`0x6a` - OP_RETURN
`0x04` - Push 4 bytes
`0x53` - ASCII character 'S'
`0x4c` - ASCII character 'L'
`0x50` - ASCII character 'P'
`0x00` - 0
A simple test
Here are two transaction in raw hex, how you parse them and call the above function on them. You can fetch raw transactions from *bitcoind* with the RPC command `getrawtransaction txid`.
NOT_SLP = '010000000122836eee490f711e6a32727aeabaf3ea55d577ce66d2dfc3c9f15448e03358990000000064412f09efc8ace5405bec70257f4d749ebab32dbf296158a46195d611c1b4a49f2159789446171fd191ae1c3e3b5151cca79c021d7c0f5d5e3add2fbc9748dc2fe8412103920fbdeb0667bae173b0ab297869206e4bc23faaa527d6c910bb3f6f66a72cfbfeffffff019a8b9600000000001976a91481b193ccc14242267f1b8a07294d7cb12c91356d88ac8d510900'
SLP_TX = "02000000026b1a3267a7f298f1a65786fa17e0887abfbb358f08c67248deda0ef3891bc9d8020000006a47304402203f23889cca2b5fec5dd144696b1927477f98d973ce101ad8bcec269368facbe7022039acb6ce6d6270aef13a8b5c7fb67408831dcb1fbfb09a1eea948d0ca3bb8e5141210350090260acd0cd7a5f7030b2aad76ec6454626ab0872246031f3809d210e4569ffffffff6b1a3267a7f298f1a65786fa17e0887abfbb358f08c67248deda0ef3891bc9d8030000006a4730440220306fda9874be7bd9c079562f96e1526a7c83425992d8e8c0d354a216aa09712402202c29f9e6f7278de141b617d662bb80164fa3b1aa5b3e24fda316388e2f619fde41210350090260acd0cd7a5f7030b2aad76ec6454626ab0872246031f3809d210e4569ffffffff040000000000000000406a04534c500001010453454e44207f8889682d57369ed0e32336f8b7e0ffec625a35cca183f4e81fde4e71a538a1080000000000000f4a080000000018608da022020000000000001976a9148eec439abdb0fc45bc4dd7a7960b38ac54fd10e688ac22020000000000001976a9144942f11b739a3835d867554ff93cc6685eb1eb5388ac03cf3400000000001976a9144942f11b739a3835d867554ff93cc6685eb1eb5388ac00000000"
from bitcoincash.core import CTransaction, x
tx = CTransaction.deserialize(x(SLP_TX))
assert(has_slp_output(tx.vout))
tx = CTransaction.deserialize(x(NOT_SLP))
assert(not has_slp_output(tx.vout))
[sponsors]