Proof-of-Work on Waves

How to mine
Here’s a sample program written in C# that “mines” the asset, that is, generates transactions until the transaction satisfies all specified conditions, and then sends the transaction to the blockchain. If N was updated earlier than 15 blocks back, then the program sends a DataTransaction that updates N.

using System;
using System.Collections.Generic;
using WavesCS;

namespace Miner
{
    class MainClass
    {
        static Node node = new Node(Node.MainNetChainId);
        static Asset asset = node.GetAsset("BXSAEa9jm9Qrkmn2XPqqKBkukZoBkJ8YpQ9EZywjdnnx");

        static byte[] senderPublicKey = node.GetTransactionById(asset.Id).SenderPublicKey;
        static string sender = AddressEncoding.GetAddressFromPublicKey(senderPublicKey, node.ChainId);
        static string recipient = ""; // put your address here

        static long lastUpdateHeight = (long)node.GetAddressData(sender)["lastUpdateHeight"];
        static long difficulty = (long)node.GetAddressData(sender)["difficulty"];

        static int validityPeriod = 15;
        static int transferAmount = 1;
        static int miningRate = 100;

        static int minDifficulty = 20;
        static int maxDifficulty = 64;

        public static void UpdateDifficulty()
        {
            try
            {
                var currentHeight = (long)node.GetHeight();
                lastUpdateHeight = (long)node.GetAddressData(sender)["lastUpdateHeight"];

                if (currentHeight - lastUpdateHeight >= validityPeriod)
                {
                    var currentBalance = asset.AmountToLong(node.GetBalance(sender, asset));
                    var lastUpdateBalance = (long)node.GetAddressData(sender)["lastUpdateBalance"];

                    difficulty = (long)node.GetAddressData(sender)["difficulty"];

                    var delta = lastUpdateBalance - currentBalance > 0 ? lastUpdateBalance - currentBalance : 1;
                    var sgn = (delta < miningRate) ? -1 : 1;
                    var k = (delta < miningRate) ? miningRate / delta : delta / miningRate;
                    var log2 =  Math.Min(10, (long)Math.Floor(Math.Log(k, 2)));
                    difficulty = difficulty + sgn * log2;
                    difficulty = Math.Max(minDifficulty, difficulty);
                    difficulty = Math.Min(maxDifficulty, difficulty);

                    var data = new Dictionary<string, object>
                    {
                        { "difficulty", difficulty },
                        { "lastUpdateHeight", currentHeight },
                        { "lastUpdateBalance", currentBalance }
                    };
                    var tx = new DataTransaction(node.ChainId, senderPublicKey, data, 0.005m);

                    Http.Tracing = true;
                    node.Broadcast(tx.GetJsonWithSignature());

                    Console.WriteLine($"Mining difficulty was updated");
                    Console.WriteLine($"Current mining difficulty: {difficulty}");
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                Http.Tracing = false;
            }
        }

        public static void Main(string[] args)
        {
            Http.Tracing = false;
            Console.WriteLine($"Current mining difficulty: {difficulty}");
            
            for (var iterations = 0; ; iterations++)
            {
                if (iterations % 1000000 == 0)
                {
                    UpdateDifficulty();
                }

                var tx = new TransferTransaction
                (
                    chainId: node.ChainId,
                    senderPublicKey: senderPublicKey,
                    recipient: recipient,
                    asset: asset,
                    amount: asset.LongToAmount(transferAmount),
                    fee: 0.005m
                );

                var id = tx.GenerateBinaryId();
                
                var leadingZeros = 0;
                for (int i = 0; i < 32; i++)
                {
                    if (id[i] == 0)
                        leadingZeros += 8;
                    else
                    {
                        leadingZeros += 7 - (int)Math.Floor(Math.Log(id[i], 2));
                        break;
                    }
                }

                if (leadingZeros >= difficulty)
                {
                    Console.Write("Generated transaction id: " + id.ToBase58());

                    try
                    {
                        Http.Tracing = true;
                        node.Broadcast(tx);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }
                    finally
                    {
                        Http.Tracing = false;
                    }
                }
            }
        }
    }
}