Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,5 @@ It then spawns a thread for every schedule entity. The thread sleeps until the

It uses a leaky bucket algorithm to precisely control the rate of transaction generation. When the end time specified in the schedule entity is reached, the connection is disconnected and the thread quits. When all threads quit, the run is complete and Txunami ends.

At this point, there is no way to recover any funds left in UTXOs. If needed, it would not be too hard to either write all these UTXOs to disk, or implement a UTXO sweep phase that combines all this dust back into a few UTXOs sent to addresses in the configuration file.
After all phases end correctly, the remaining UTXOs will be written to the file `utxos.json`. If the remaining balance is significant, it is easy to copy-paste the contents of this file back to the `coins` section of `txunami.json` to continue spending; otherwise the private keys can be swept.

41 changes: 35 additions & 6 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "random.h"
#include "utilstrencodings.h"
#include "leakybucket.h"
#include "cashaddrenc.h"

using namespace std;

Expand Down Expand Up @@ -53,6 +54,7 @@ class UTXO

/** Generate transactions at the maximum rate possible to the specified host */
void MaxSpeed(const string& host, vector<UTXO>& utxo, vector<UTXO>& txo);
bool saveUtxos(std::vector<UTXO> utxos);

class ConfigException:public runtime_error
{
Expand Down Expand Up @@ -702,13 +704,13 @@ int main(int argc, char** argv)
printf("preparation: split coins\n");

vector<UTXO> txo;
unsigned int stepSize = 0;
unsigned int stepSize = utxo.size();
unsigned int step = 1;
SimpleClient sc(gc.bitcoind);

uint64_t start = GetStopwatch();
uint64_t createTxLoopStart = 0;
while (stepSize < gc.minUtxos)
while (stepSize <= gc.minUtxos)
{
// Split by the maximum allowed per tx, or by the minimum needed to get beyond our gc.minUtxos choice
unsigned int curSplit = 1;
Expand Down Expand Up @@ -779,6 +781,9 @@ int main(int argc, char** argv)

printf("done in %f4.2 sec\n", ((float)(end-start))/1000000000.0);
printf("create tx loop in %6.2f sec\n", ((float)(end-createTxLoopStart))/1000000000.0);
printf("Generate a block and push <Enter>... ");

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to system() a script (configured in txunami.json) here. That script can just wait for an enter, or it can wait while polling for a block.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah a simple script like the one in point 7 by Mr Toomim would probably suffice.

I have encountered instances where only part of my fan-out transactions would confirm in the first block, even in two stage setups.

For now I'm just monitoring getmempoolinfo to know when to push Enter.

string input;
getline(cin, input);

txo = utxo; // Copy the vector to send to myself

Expand All @@ -794,13 +799,37 @@ int main(int argc, char** argv)
if (runAschedule)
sched.Execute(utxo, txo);
else
{
printf("Generate a block <enter>\n");
string input;
cin >> input;
MaxSpeed(gc.bitcoind, utxo, txo);

if (!saveUtxos(txo))
printf("Could not save the remaining utxos");
}

bool saveUtxos(std::vector<UTXO> utxos)
{
ofstream utxofile;
UniValue results(UniValue::VARR);
for (UTXO &utxo : utxos)
{
UniValue entry(UniValue::VOBJ);
entry.pushKV("txid", utxo.prevout.hash.GetHex());
entry.pushKV("vout", (uint64_t) utxo.prevout.n);
entry.pushKV("satoshi", utxo.satoshi);
CScript script = utxo.constraintScript;
entry.pushKV("scriptPubKey", HexStr(script.begin(), script.end()));
CTxDestination address;
ExtractDestination(script, address);
entry.pushKV("address", EncodeCashAddr(address, Params()));
entry.pushKV("privKey", CBitcoinSecret(utxo.privKey).ToString());
results.push_back(entry);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

write the address as well (yeah I know that txunami doesn't need it)... but it could be useful for scripts that read this and do things like access the spends in an explorer.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I thought about it because it would be useful, but it's not part of the UTXO object, so didn't bother.

I have now added the address.

}

utxofile.open("utxos.json");
if(!utxofile) return false;
utxofile << results.write(1, 4);
utxofile.close();

return true;
}

void MaxSpeed(const string& host, vector<UTXO>& utxo, vector<UTXO>& txo)
Expand Down