Author

Topic: A concise step-by-step guide to splitting your coin the Armory way (on Windows) (Read 486 times)

jr. member
Activity: 70
Merit: 2
Eric Lombrozo (core dev, coinspl.it initiative) gave me a bit further feedback on the coinspl.it slack channel.
I've tweeked the guide to be more general for any future hard-fork with no replay-protection. Also clarified some steps and enhanced the script to make it harder to mess things up.

It is now a sharable/editable google doc:
https://docs.google.com/document/d/1tC4Mcisd5b9-yQXhwXEdlk0PY2JD6TjX_Ls1t_p6Ax8/edit

Thanks again goatpig for the input to this, and your overall contribution to the bitcoin ecosystem.
legendary
Activity: 3766
Merit: 1364
Armory Developer
All this work for nothing =/

Hopefully it stays that way. I'd rather this was all for naught than these idiots try to aggro fork 3 months from now.
jr. member
Activity: 70
Merit: 2
Just as I was about to integrate goatpig's valuable comments (esp. regarding botched privacy) - B2X's politburo standing committee of six voted to shut it down. However, since the work has been done, and perhaps for future use should the need arise, below is a take on a step-by-step guide for splitting your coin in the face of a non-replay protected hard fork (aka segwit2X or its future siblings) version 2:

1.   Ingredients
    a.   Armory running on top of a full node synced by BTC 15.0.1.
    b.   Extra 160GB disk space, preferably SSD for faster sync.
    c.   A small script I wrote to switch Armory between chains (below)

2.   Definitions
    a.   Tainted address: an address that you have generated from your Armory wallet that has coins on one blockchain only. Checking if an address is tainted involves using two blockchain explorers, one on each chain. A tainted address will show it has coins on one blockchain explorer, and no coins on the other blockchain explorer.
    b.   BlockHeight – the top, most recent block number on a given blockchain.
    c.   Post-fork definitions:
        HighChain – The blockchain that has the higher BlockHeight, longer chain.
        HighChainHeight – the BlockHeight of a HighChain.
        LowChain – the shorter blockchain = it has the lower BlockHeight.
        LowChainHeight – the BlockHeight of LowChain.
        TaintWindow = HighChainHeight minus LowChainHeight (measured in blocks).

    d.   ArmoryDir: the directory where armory lives on your machine. It has it's log files, wallets, and ArmorySetting.txt – its settings file, which we will use. It is by default in %appdata%roaming/armory, but can be changed via the –datadir= command line option. In my setup and examples below, it is in f:\armory
    e.   BitcoinDir: the directory where bitcoin stores its Blocks, Chainstate and conf file. It is by default in %appdata%roaming/bitcoin. In my setup and examples below it is in f:\bitcoin.

3.   Method Overview
    a.   When the fork occurs, (block height 494,784), one of two things will happen: either B2X will have the majority of hashpower, or BTC will. No one knows, but either way, we'll all know once the first >1MB is mined by B2X. This hash power asymmetry plus the use of RBF are the tools we'll use to attempt a coin split.

    b.   After some time from the fork event, one chain will find more blocks than the other due to hashrate asymmetry and as a result, one chain will become the HighChain (see definitions above), the other LowChain, with corresponding HighChainHeight, LowChainHight and a non-zero TaintWindow (see definitions).

The chain height of the blockchain Armory runs on is shown at the bottom right corner of Armory once it syncs. We will use this height difference between the chains for tainting.

    c.   Internal mechanism: When Armory generates a transaction, it sets a block height from which the transaction starts to be valid (for various reasons outside our scope here). That height, called 'locktime', is regularly set to be the top height at the time of transaction creation.

Now, since the two chains will eventually diverge in block height, Armory created transactions on the HighChain will be invalid on the LowChain for a period of TaintWindow blocks. To give an example (rounding numbers for simplicity) suppose:

BTC is at block #500,000
B2X is at block #499,990

HighChain=BTC; HighChainHeight=500,000
LowChain=B2X; LowChainHeight=499,990
TaintWindow=500,000 - 499,990 = 10 blocks

The TaintWindow is our opportunity of tainting – it is the time when we know that Armory created transactions on the HighChain can't be replayed on the LowChain.
 
This means we want transactions to get mined asap on the HighChain to begin with, since that keeps the window as wide as possible. Assuming in the previous example that your transaction gets mined in the first block, i.e. #500.001, that puts B2X at block #499,991 and we have 9 blocks till HighChain transaction is mineable on the LowChain. That should be ample time to RBF on the LowChain side.

Basically, as long as TaintWindow is significant enough (as low as 5 blocks could do), there's a comfortable window to RBF the transaction on the LowChain. Make a point of bumping the fee on the LowChain just to make sure that if you don't get mined on the LowChain during the TaintWindow, your LowChain transaction will still take priority over your HighChain transaction after LowChain catches up.


4.   Step 1: pre-fork preparations
    a.   Record your ArmoryDir and your BitcoinDir.
    b.   Make sure Armory is synced over your BTC node in expert mode.
    c.   In Armory, under File-Settings, check 'Let Armory run Bitcoin Core/bitcoind in the background' and insert the proper directories where BTC Core resides – do not leave the two fields blank. The two directories should be identical. Click Save.
    d.   Exit Armory gracefully. Make sure in task-manager that bitcoind has stopped and so did armory.db. It may take bitcoind a good minute to save and exit, especially on a mechanical disk.
    e.   Restart Armory and see that everything works as expected: Armory fires up bitcoind and armory.db syncs and you can see your wallet(s) and transactions. It may take a minute for Armory to start working with the node after startup.
    f.   Go to ArmoryDir and open file ArmorySetting.txt – look for the lines starting with "SatoshiExe" and a few lines below it "SatoshiDatadir". Both should have on the right your BitcoinDir – (e.g. f:\bitcoin)
    g.   Now go to BitcoinDir and copy the entire content to a new directory. It is about 150GB. Name that directory B2X. From now on that will be refered to as B2XDir and will have the entire B2X blockchain. In my examples below, it is in d:\b2x.
Open a new text file and name it "ArmoryCoinSelect.ps1". Make sure the suffix is .ps1 (powershell script) and not .txt (a text file). It will contain a short script to change Armory settings such as its directed to a specific blockchain. Paste the following code into it:

Code:
#Switch armory to BTC or B2X node
param(
[string]$SwitchTo = $(Read-Host 'Coin? [BTC/B2X]'),
[string]$ArmorySetting="F:\Armory\ArmorySettings.txt",
[string]$b2x="d:\b2x",
[string]$btc="f:\bitcoin"
)
if ($SwitchTo -eq "BTC") {
(Get-Content $ArmorySetting).Replace($b2x, $btc) |Set-Content $ArmorySetting
echo "Armory directed to BTC"
}
else{
(Get-Content $ArmorySetting).Replace($btc, $b2x) |Set-Content $ArmorySetting
echo "Armory directed to B2X"
}

[string]$RunArmory=$(Read-Host 'Run Armory? [Y/N]')
if ($RunArmory -eq "Y") {
& "C:\Program Files (x86)\Armory\ArmoryQt.exe" --datadir=f:\armory
}

    h.   In the above script, change a few lines in the likely event your directories are different from the examples here: $ArmorySetting, $b2x, $btc at the start of the script need to point to where these file exist, and the hardcoded datadir at the last line of the script.
    i.   Make sure Armory is not running, nor bitcoind nor armorydb and run the script by right-clicking on the file and choosing 'Run with PowerShell". Choose B2X and 'Y'  if all goes well, Armory will start and shortly after control the B2X node and sync it.
    j.   Create a new wallet to receive your B2X coins. Name it meaningfully so as not to confuse with any other wallet, e.g. MyB2X.
    k.   After it syncs – shut down gracefully and start BTC again. To see which chain you're on, choose in Armory File-Settings and you'll see the directories it is working with – in my examples either f:\bitcoin or d:\b2x.
    l.   You are now ready for the fork. Keep the nodes updated by switching once every few days.

5.   Post Fork Tainting (the hard part)
    a.   Switch Armory to HighChain.
    b.   Double check it is synced and on the chain you've intended (File-Settings).
    c.   Go to the Send dialog. Pick your HighChain wallet as the sender. For recipients, pick your HighChain wallet as well. This will grab a fresh address in your HighChain wallet.
    d.   Open the Coin Control dialogue a pick a single UTXO.
    e.   Record the UTXO, you will need the same UTXO for later.
    f.   Check "MAX" on the recipient entry, next to the value field. Manually input a fee healthy fee, sign and broadcast.

This makes sure that:
    •   You are sending these coins to yourself with no change. You don't need change for this, you are sending back to yourself after all.
    •   You are moving a single, whole UTXO. This is the only way to protect your privacy, by moving your UTXOs one at a time without change.
    •   Lastly, you want a big fee because you want to get mined in the next HighChain block, so as to have the longest TaintWindow.
    g.   Once you have 1 confirmation on the HighChain, shut down Armory and restart via the script and switch to the LowChain.
    h.   Double check it is synced and on the LowChain you've intended (Choose File-Settings to verify).
    i.   Here you will perform the exact same spend but send to your LowChain wallet instead of your HighChain wallet. Obviously pick the same UTXO as with the HighChain transaction, recorded in step e.
    j.   You are trying to send to a different address on the LowChain. That's the whole point of tainting, to get an output on one chain that does not exists on the other.

    k.   Do not forget to spike the fee even higher than with the HighChain transaction. You want to get in the next LowChain block and you want this transaction to have a highest fee of the two if it fails to mine quickly.

Once you've got your confirmation on the LowChain, you have a tainted UTXO.
    l.   Rinse and repeat with each of your UTXOs.

legendary
Activity: 3766
Merit: 1364
Armory Developer
Are you trying to force my hand at writing a guide? This is all over the place.

I'm assuming B2X is the chain with the least blocks for the entirety of this post, makes like simpler. I'm also assuming BTC and B2X maintain the same median block rate (i.e. they both add a block every ~10min or so).

--- Setup ---

4.c) The use of auto bitcoind is asking to get shot in the foot. Take the extra minute to run the relevant node manually. Auto bitcoind is just too unstable for this purpose, and you'd need to monitor processes to make sure it shuts down in between swaps, which eats into the convenience benefit. If you're gonna bother explaining how to swap around between chains, you should explain how to run b2x and core concurrently on 2 separate VM/computers instead.

4.g) You are complicating things with one script ruling them all. If you want to switch instances around, have 2 scripts/shortcuts, one per side of the chain, and have them each summon the node as well as Armory. Easier to tell them apart, you get a node GUI and you don't risk mixing up manually spawned nodes with the wrong Armory instance. Also easier to confirm the node has shut down.

4.k) Don't know where you are going with this. Just create and backup a wallet that is exclusively meant to receive your B2X. Load your BTC and B2X wallets on the B2X Armory instance. Load only your BTC wallets on your BTC instance. More on that later.

4.m) You don't need those. This is potentially a privacy leak if the explorer service logs your IP against your searches.


--- Tainting ---

5) You don't care for hash rate, you only care for block height and median block rate. Again, we assume BTC has a higher block height than B2X.

6.c-d) Start your BTC Armory instance. Go to the Send dialog. Pick your BTC wallet as the sender. For recipients, pick your BTC wallet as well. This will grab a fresh address in your BTC wallet. Open the Coin Control dialogue a pick a single UTXO. Check "MAX" on the recipient entry, next to the value field. Manually input a fee above average. Sign and broadcast.

This makes sure of a couple things:

First, you are sending these coins to yourself with no change. You don't need change for this, you are sending back to yourself after all. Second, you are moving a single, whole UTXO. This is the only way to protect your privacy, by moving your UTXOs one at a time without change. Lastly, you want a big fee because you want to get mined in the next BTC block.

6.g) Once you have 1 conf on the BTC chain, shutdown the BTC instance and start the B2X instance. Here you will perform the exact same spend but send to your B2X wallet instead of your BTC wallet. Obviously pick the same UTXO as with the BTC transaction. You are trying to send to a different address on the B2X chain. That's the whole point of tainting, to get an output on one chain that does not exists on the other.

Do not forget to spike the fee even higher than with the BTC transaction. You want to get in the next B2X block and you want this tx to have a highest fee of the 2 if it fails to mine quickly.

Once you've got your confirmation on the B2X chain, you have a tainted UTXO. Rinse and repeat with each of your UTXOs. If you have trouble keeping track of which UTXO needs tainted on your BTC wallet, either keep track of it through the B2X instance or use a fresh wallet on the BTC side to receive the post fork coins.

7) DO NOT DO ANY OF THE STEPS IN SECTION 7 OF THE ORIGINAL POST. You will forever link your coins together and erode all the privacy you ever had. You can attempt to obfuscate your coins later but that requires using 3rd parties or coin-joining with other users. It's lengthy, potentially risky and onerous. And it doesn't change the fact that there is an IMMUTABLE AND PUBLIC EVENT linking all your coins together. Be diligent and taint your UTXOs one at a time. Also let's be real here, if you won't take to move your UTXOs one a time, would deploy the larger effort that is to tumble your coins once you're tainted?

Lastly, keep in mind that both chains can erode your privacy. Don't go around lopping all your coins together on one chain post taint thinking that you're now safe. It will shit all over your privacy all the same. Treat both side of the chain with equal diligence when it comes to your privacy, regardless of what you dump.

--- How does it work ---

There is no such thing as a replay attack in this split. B2X uses the same tx format, same signature and same port as BTC. When you push a transaction on the network post split, not only your intention cannot be told apart (was the tx meant for BTC or B2X?), but both chains will see it as valid. Do not imagine there are nefarious actors out there making a point of replicating the BTC mempool in B2X and vice versa just for the sake of disruption, this is built in B2X! Makes you wonder who the nefarious actors actually are...

Anyways, the method I outlined works thanks to the tx locktime. Armory will set the locktime of its transactions to current top height. This is a measure that was introduced in Core to dampen selfish mining attacks scenarios. What the locktime field does is to signify the block height starting which the transaction is valid.

The idea was to reduce the incentive where a miner tries to steal transaction fees from other miners by orphaning their blocks and stuffing his with the juiciest fees from blocks he orphaned, since he'd have to mine at least as high as the current block height to steal the most recent fees. Otherwise there are scenarios where a large miner would profit from orphaning consecutive blocks from small miners.

In our case the locktime is useful because the 2 chains will eventually diverge in block height. This means the tx you create on the highest chain will be invalid on the lowest chain, irreverent of hash rate or difficultly, as long as the shortest chain has not caught up to the height your tx is locked for. To give an example (rounding numbers for simplicity):

BTC is at block #500,000
B2X is at block #499,990

The tx Armory creates on the BTC chain will be invalid on the B2X chain until the B2X chain grows to height #500,000, i.e you have 10 blocks worth of time where you know your tx can't be replayed on the B2X chain.

This is the window you want to exploit to taint your coins. This is why you want to get mined asap on the BTC chain to begin with, since that keeps the window as wide as possible. Assuming in the previous example that your tx gets mined in the first block, i.e. #500.001, that puts B2X at block #499,991 and you have 9 blocks till your BTC tx is mineable on the B2X chain. That should be ample time to RBF on the B2X side.

Basically, as long as the height difference between the 2 chains is significant enough (as low as 5 blocks could do), you are guaranteed a comfortable window to RBF your tx on the shortest chain. You make a point of bumping the fee on the B2X chain just to make sure that if you don't get mined on the B2X chain in the locktime window, your B2X tx still will take priority over your BTC tx after B2X catches up.

--- But but, doing it this way increases my cost in fees to taint! ---

Marginally. You still have to pay a baseline sat/B to move all your coins, whether you do it one UTXO at a time, or taint a single UTXO and crunch all of your coins together into privacy purgatory. Also consider that you stand to make much more from dumping the shitcoin (I'll let you decide which one it is to you, though I sure know which one I'll drop like a diseased crack whore) that what you will pay in fee to make the shitcoin spendable in the first place.






jr. member
Activity: 70
Merit: 2
This is an attempt for a step by step guide to a DIY coin split on the upcoming B2X fork. Any and all feedback on improving and especially simplifying the process without involving any third party would be appreciated.
EDIT: Please see goatpig's comments in the followup post, especially regarding botched privacy - I'll be integrating the comments to an updated post
1.   Ingredients
    a.   Armory running on top of a full node synced by BTC 15.0.1.
    b.   Extra 160GB disk space, preferably SSD for faster sync.
    c.   A small script I wrote to switch Armory between chains (below)

2. Definitions
    a.   Tainted address: an address that you have generated from your Armory wallet that has coins on one blockchain only. Checking if an address is tainted involves using two blockchain explorers, one on each chain. A tainted address will show it has coins on one blockchain explorer, and no coins on the other blockchain explorer.
    b.   BTC tainted address: a tainted address that has coins on the BTC blockchain. We'll call it BTCTaint from now on.
    c.   B2X tainted address: a tainted address that has coins on the segwit2X  blockchain. We'll call it B2XTaint from now on.
    d.   ArmoryDir: the directory where armory lives on your machine. It has it's log files, wallets, and ArmorySetting.txt – its settings file, which we will use. It is by default in %appdata%roaming/armory, but can be changed via the –datadir= command line option. In my setup and examples below, it is in f:\armory
    e.   BitcoinDir: the directory where bitcoin stores its Blocks, Chainstate and conf file. It is by default in %appdata%roaming/bitcoin. In my setup and examples below it is in f:\bitcoin.

3.   Method Overview
The method involves three steps, with the first step the hard part, the second and third are trivial.
    Step 1: create a BTC tainted address and a B2X tainted address.
    Step 2: using the tainted addresses, move your entire stash to two different new wallets – one will contain your BTC, the other your B2X.
    Step 3: recycle the wallets for added privacy and security, preferably also dumping B2X coins via an exchange once they reopen for business as the dust settles down.

4. Step 1: pre-fork preparations
    a.   Record your ArmoryDir and your BitcoinDir.
    b.   Make sure Armory is synced over your BTC node in expert mode.
    c.   In Armory, under File-Settings, check 'Let Armory run Bitcoin Core/bitcoind in the background' and insert the proper directories where BTC Core resides – do not leave the two fields blank. The two directories should be identical. Click Save. The script I wrote below depends on this.
    d.   Exit Armory gracefully. Make sure in task-manager that bitcoind has stopped and so did armory.db. It may take bitcoind a good minute to save and exit, especially on a mechanical disk.
    e.   Restart Armory and see that everything works as expected: Armory fires up bitcoind and armory.db syncs and you can see your wallet(s) and transactions. It may take a minute for Armory to start working with the node after startup.
    f.   Go to ArmoryDir and open file ArmorySetting.txt – look for the lines starting with "SatoshiExe" and a few lines below it "SatoshiDatadir". Both should have on the right your BitcoinDir – (e.g. f:\bitcoin)
    g.   Now go to BitcoinDir and copy the entire content to a new directory. It is about 150GB. Name that directory B2X. From now on that will be refered to as B2XDir and will have the entire B2X blockchain. In my examples below, it is in d:\b2x.
Open a new text file and name it "ArmoryCoinSelect.ps1". Make sure the suffix is .ps1 (powershell script) and not .txt (a text file). It will contain a short script to change Armory settings such as its directed to a specific blockchain. Paste the following code into it:

Code:
#Switch armory to BTC or B2X node
param(
[string]$SwitchTo = $(Read-Host 'Coin? [BTC/B2X]'),
[string]$ArmorySetting="F:\Armory\ArmorySettings.txt",
[string]$b2x="d:\b2x",
[string]$btc="f:\bitcoin"
)
if ($SwitchTo -eq "BTC") {
(Get-Content $ArmorySetting).Replace($b2x, $btc) |Set-Content $ArmorySetting
echo "Armory directed to BTC"
}
else{
(Get-Content $ArmorySetting).Replace($btc, $b2x) |Set-Content $ArmorySetting
echo "Armory directed to B2X"
}

[string]$RunArmory=$(Read-Host 'Run Armory? [Y/N]')
if ($RunArmory -eq "Y") {
& "C:\Program Files (x86)\Armory\ArmoryQt.exe" --datadir=f:\armory
}

    h.   In the above script, change a few lines in the likely event your directories are different from the examples here: $ArmorySetting, $b2x, $btc at the start of the script need to point to where these file exist, and the hardcoded datadir at the last line of the script.
    i.   Make sure Armory is not running, nor bitcoind nor armorydb and run the script by right-clicking on the file and choosing 'Run with PowerShell". Choose B2X and 'Y'  if all goes well, Armory will start and shortly after control the B2X node and sync it.
    j.   After it syncs – shut down gracefully and start BTC again. To see which chain you're on, choose in Armory File-Settings and you'll see the directories it is working with – in my examples either f:\bitcoin or d:\b2x.
    k.   Finally, send 10,000 Satoshis to a new address that you generated. We'll call that address GenesisAddr – we'll use it post-fork to create BTCTaint and B2XTaint. Write the GenesisAddr down on notepad.
    l.   You are now ready for the fork. Keep the nodes updated by switching once every few days.
    m.   Have a bookmark on two block explorers: one on the BTC chain and one on the B2X chain.

5.   Fork event overview
    a.   When the fork occurs, (block height 494,784), one of two things will happen: either B2X will have the majority of hashpower, or BTC will. No one knows, but either way, we'll all know once the first >1MB is mined by B2X. This hash power asymmetry plus the use of RBF are the tools we'll use to attempt a coin split.

At that point, the fork occurs, and you'd need to find out which has the majority hash. We'll call the chain with the majority hash: MHChain.

Once the fork occurs, we'll attempt to send the content of GenesisAddr to BTCTaint and B2XTaint and when we succeed – the rest is easy.

6.   Post Fork Tainting (the hard part)
    a.   Now that we know which chain is MHChain, switch Armory to the MHChain. In the example below, I'm assuming MHChain is B2X, but the process is identical
    b.   Double check it is synced and on the chain you've intended (File-Settings).
    c.   Generate a receiving address. We'll call it B2XTaint (assuming MHChain is B2X).
    d.   Send the content (10000 satoshi in our example) from GenesisAddr to B2XTaint, with normal fees. Since it has a majority hash rate, it should confirm quicker than the minority hash chain. Open the majority hash block explorer (in our example a block explorer for segwit2x) in a separate window.
    e.   Shut down Armory and restart via the script and switch to the minority hash chain – in our example, BTC.
    f.   Double check it is synced and on the chain you've intended (File-Settings).
    g.   Look at the transactions tab. Hopefully, the minority chain has not confirmed your above transaction. If it did, the transaction was replay-attacked. Go back to step 6c.
    h.   If it didn't, generate a receiving address. We'll call it BTCTaint (assuming minority chain is BTC). It needs to be different from B2XTaint of course.
    i.   Send the content of GenesisAddr to BTCTaint using a very small fee (say 3 satoshi/byte) and a RBF option. Check on the blockchain explorer of the minority chain that it is unconfimed.
    j.   Now the critical step: look at the block explorer in the majority hash chain and the minority hash chain. Look for the majority hash transaction confirmed there (first confirmation, on B2X chain), but before it was replay-attacked (confirmed in the minority hash chain) – do RBF with a good fee on the minority chain. You are racing against a possible replay-attacker. If the minority chain transaction confirmed (you have the GenesisAddr coin in BTCTaint address) – you're done.
    k.   You should now see two transactions on the relevant blockchain explorers: one from GenesisAddr to BTCTaint confirmed. The other from GenesisAddr to B2XTaint confirmed.

7.   Completing the Coin split
    a.   Open Armory on the BTC Chain.
    b.   Generate a new address, lets call it BTCStash. Make a transaction that includes the remainder of your wallet, including the coins from BTCTaint to BTCStash. You now have your entire BTC in address BTCStash.
    c.   Repeat step a and b for the B2X Chain, creating address B2XStash and sending to it the remainder of your wallet including the coins from B2XTaint.
    d.   You now have separate, split coins on the two blockchains.

8.   Recycling the wallet
    a.   It is advisable to recycle the wallet. Check elsewhere how to do it. goatpig published this regarding to the BCH split I think.




Jump to: