0

A part of my MSc thesis is storing the hash of a string with OP_RETURN tx in the Blockchain to exist as a proof.

My main concerns are:

-how can i send this tx successfully to my regtest network

-how can i see (with a RPC) if this tx happend

I have already stored the string to a file and hash it afterwards. But I have difficulties with connecting my Java with the Regtest network.

Here is my code:

public class Main {

public static RegTestParams params = RegTestParams.get();
static BlockStore bs;
static Block b;

public static Context context = new Context(params);
public static WalletAppKit bitcoin;

public static void main(String[] args) throws InterruptedException, ExecutionException, BlockStoreException {

    WalletAppKit kit = new WalletAppKit(RegTestParams.get(), new java.io.File("."), "test");
    kit.startAsync();
    Wallet wallet = new Wallet(params);

    BlockChain chain = kit.chain();
    bs = chain.getBlockStore();
    Peer peer = kit.peerGroup().getDownloadPeer();
    b = peer.getBlock(bs.getChainHead().getHeader().getHash()).get();

    peer.addWallet(wallet);

    Address myAddress = new Address(params, "n4MN27Lk7Yh3pwfjCiAbRXtRVjs4Uk67fG");

    Writer w = new Writer();
    final File results = new File("C:\\Users\\Maria\\workspace\\blockInfo\\results.txt");
    File writtenFile;
    Sha256Hash resultHash;

    // write the results of my draw to a file
    writtenFile = w.writeToFile(results);

    // hash the contents of the file
    resultHash = w.hashTheFile(writtenFile);
    System.out.println(resultHash);

    SendRequest req;
    Transaction transaction = new Transaction(RegTestParams.get());

    // the following statement will help to create an OP_RETURN with
    // resultHash as the message
    transaction.addOutput(Coin.ZERO, ScriptBuilder.createOpReturnScript(resultHash.getBytes()));
    req = SendRequest.forTx(transaction);

}

}

  • I think you're still missing a few steps, for example I can't see where you set the funding transaction hash. Apart from that you can check the mempool of your bitcoin node using: bitcoin-cli -regtest getrawmempool. If it's empty then your tx wasn't accepted. – sipwiz Nov 10 '17 at 11:50
  • @sipwiz the RPC worked and of course it is yet empty. How can i set the funding transaction hash?Could you give a short snippet of code with OP_RETURN? – gtopal Nov 10 '17 at 16:10
  • There are a few steps required to work with the regtest network. Have you seen bitcoin.org/en/developer-examples#regtest-mode? – sipwiz Nov 10 '17 at 21:03
  • @sipwiz I have seen the examples. My problem is how to establish a proper connection with Java in order to catch the results afterwards in regtest network. The RPCs can work alone apart from java code. – gtopal Nov 12 '17 at 9:27
  • I've just an added an answer which is hopefully close to what you are attempting to do. The main thing you should look at is the getting an input for your transaction. You can't spend an output if you don't fund the tx. – sipwiz Nov 12 '17 at 9:59
1

I'm not familiar with the Java API you are using but here are the steps and a C# code sample that I used to create a valid transaction on regtest. The sample and steps are from my rough and ready dev notes so there may be a few leaps of faith (hopefully not).

You'll need to adjust the steps below for your own paths/OS/set up.

  • Step 1: The command line used for the local bitcoin full node in regression test mode (https://bitcoin.org/en/developer-examples#regtest-mode):

    • "C:\Program Files\Bitcoin\daemon\bitcoind" printtoconsole -datadir=f:\temp\bitcoind -server -regtest -debug=1
  • Step 2: The command line used to request the bitcoin daemon to generate a 101 height blockchain:

    • "C:\Program Files\Bitcoin\daemon\bitcoin-cli" -datadir=f:\temp\bitcoind -regtest generate 101
  • Step 3: If the bitcoin server node was initialised with an empty blockchains the getbalance command should now display a 50.00000000 which represents the coin base amount from the first block following the genesis block.

    • "C:\Program Files\Bitcoin\daemon\bitcoin-cli" -datadir=f:\temp\bitcoind -regtest getbalance
  • Step 4: To find the transactions available for spending.

    • "C:\Program Files\Bitcoin\daemon\bitcoin-cli" -datadir=f:\temp\bitcoind -regtest listunspent
    • ["C:\Program Files\Bitcoin\daemon\bitcoin-cli" -datadir=f:\temp\bitcoind -regtest getrawtransaction true]
  • Step 5: To get the private key to sign a spend transaction (MAKE SURE -regtest IS SPECIFIED OTHERWISE YOU COULD EXPORT YOUR LIVE PRIVATE KEY AND POTENTIALLY LOSE $$$).

    • "C:\Program Files\Bitcoin\daemon\bitcoin-cli" -datadir=f:\temp\bitcoind -regtest dumpprivkey
  • Step 6: After sending a transaction check whether it was accepted as valid and added to the mempool.

    • "C:\Program Files\Bitcoin\daemon\bitcoin-cli" -datadir=f:\temp\bitcoind -regtest getrawmempool
  • Step 7: If the transaction is successfully validated and accepted into the mempool then the next step is to generate a block that includes it.

    • "C:\Program Files\Bitcoin\daemon\bitcoin-cli" -datadir=f:\temp\bitcoind -regtest generate 1
  • Step 8: The address that the coins were sent to can then be checked to verify that the coins were received (not you can't use getbalance unless the send to address's private key is imported into the wallet).

    • "C:\Program Files\Bitcoin\daemon\bitcoin-cli" -datadir=f:\temp\bitcoind -regtest importaddress mssuKhM1CMDgcCm3LyGunA1o6129FnkHyk rescan
    • "C:\Program Files\Bitcoin\daemon\bitcoin-cli" -datadir=f:\temp\bitcoind -regtest getreceivedbyaddress mssuKhM1CMDgcCm3LyGunA1o6129FnkHyk

In the code sample below you need to replace the keys with the ones you extract using the bitcoin-cli steps above. There's undoubtedly an easier way to do this and these notes are from my first couple of weeks mucking around with Bitcoin.

using System;
using System.Threading;
using NBitcoin;
using NBitcoin.Protocol;
using log4net;

namespace SpendTransaction_WithCli
{
    class Program
    {
        static ILog logger = log4net.LogManager.GetLogger("default");
        static Network _network = Network.RegTest;

        static string _unspentTxId = "5d1db816efc865ab33eb8d5c9f0238501dfd849fc67cc941565236b36e43b234";    // Need to get this from bitcoin-cli (see Step 4 above).
        static string _unspentScriptPubKey = "03c1a1a614c8549373b2ec35f586aa8b33a3bf5ac3e0a1b8cf27e650bdb5a126f0 OP_CHECKSIG"; // Need to get this from bitcoin-cli (see Step 4 above).
        static string _sendFromPrivateKey = "cQYdUpoeJZP7FmxUeiaKSLPo9eHsDAYbWs17DgY44yHX2sATK2Cw";         // Need to get this from bitcoin-cli (see Step 5 above).
        static string _receiveToPrivateKey = "cR7X4Nd5WqA5mNwgX67th4Jo3K9vTTm28w8njLL9JT8hHPdbstL8";        // This is an arbitrary key that is used to send some coins to.

        static void Main(string[] args)
        {
            log4net.Config.XmlConfigurator.Configure();

            // Set up the private keys and addresses for the sender and receiver.
            Key sendFromPrivKey = Key.Parse(_sendFromPrivateKey, _network);
            BitcoinPubKeyAddress sendFromAddr = sendFromPrivKey.PubKey.GetAddress(_network);

            Key receiveToPrivKey = Key.Parse(_receiveToPrivateKey, _network);
            BitcoinPubKeyAddress receiveToAddr = receiveToPrivKey.PubKey.GetAddress(_network);

            logger.DebugFormat("Sending from {0} to {1}.", sendFromAddr, receiveToAddr);

            logger.Debug(sendFromPrivKey.ScriptPubKey);
            logger.Debug(sendFromPrivKey.PubKey);

            // Create the transaction to spend the bitcoin.
            OutPoint spending = new OutPoint(uint256.Parse(_unspentTxId), 0);
            Script spendScriptPubKey = new Script(_unspentScriptPubKey);

            var spendTx = new Transaction();
            spendTx.Inputs.Add(new TxIn(spending, spendScriptPubKey));
            spendTx.Outputs.Add(new TxOut(Money.Parse("49"), receiveToAddr.ScriptPubKey));  

            spendTx.Sign(sendFromPrivKey, false);

            logger.Debug(spendTx.ToString(RawFormat.BlockExplorer));

            // Send the transaction to the local bitcoin node.
            using (var node = Node.ConnectToLocal(_network))
            {
                node.VersionHandshake();
                node.SendMessage(new InvPayload(InventoryType.MSG_TX, spendTx.GetHash()));
                node.SendMessage(new TxPayload(spendTx));
                Thread.Sleep(500);
            }

            Console.WriteLine("Press q to quit...");

            while (true)
            {
                var keyPress = Console.ReadKey();
                if (keyPress.KeyChar == 'q')
                {
                    break;
                }
            }

            Console.WriteLine("Exiting...");
        }
    }
}
  • very helpul, especially the steps for RPCs. I will try to adapt the steps to my java code and execute. – gtopal Nov 14 '17 at 8:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.