コード例 #1
0
 /// <summary>
 /// Marks the anchor as successfully recorded in the anchoring medium.
 /// </summary>
 /// <param name="anchor">The anchor to commit.</param>
 /// <returns>The task object representing the asynchronous operation.</returns>
 public async Task CommitAnchor(LedgerAnchor anchor)
 {
     await ExecuteAsync(@"
             INSERT INTO Anchors
             (Position, FullLedgerHash, TransactionCount)
             VALUES (@position, @fullLedgerHash, @transactionCount)",
         new Dictionary<string, object>()
         {
             ["@position"] = anchor.Position.ToByteArray(),
             ["@fullLedgerHash"] = anchor.FullStoreHash.ToByteArray(),
             ["@transactionCount"] = anchor.TransactionCount
         });
 }
コード例 #2
0
        private async Task <LedgerAnchor> ComputeNewAnchor(LedgerAnchor lastAnchor)
        {
            IReadOnlyList <ByteString> newTransactions;

            byte[] currentHash;
            if (lastAnchor != null)
            {
                newTransactions = await storageEngine.GetTransactions(lastAnchor.Position);

                currentHash = lastAnchor.FullStoreHash.ToByteArray();
            }
            else
            {
                newTransactions = await storageEngine.GetTransactions(null);

                currentHash = new byte[32];
            }

            if (newTransactions.Count == 0)
            {
                return(null);
            }

            byte[] position = currentHash;
            byte[] buffer   = new byte[64];
            using (SHA256 sha = SHA256.Create())
            {
                foreach (ByteString rawTransaction in newTransactions)
                {
                    currentHash.CopyTo(buffer, 0);
                    position = MessageSerializer.ComputeHash(rawTransaction.ToByteArray());
                    position.CopyTo(buffer, 32);

                    currentHash = sha.ComputeHash(sha.ComputeHash(buffer));
                }
            }

            LedgerAnchor result = new LedgerAnchor(
                new ByteString(position),
                new ByteString(currentHash),
                newTransactions.Count + (lastAnchor != null ? lastAnchor.TransactionCount : 0));

            return(result);
        }
コード例 #3
0
        /// <summary>
        /// Records a database anchor.
        /// </summary>
        /// <param name="anchor">The anchor to be recorded.</param>
        /// <returns>The task object representing the asynchronous operation.</returns>
        public async Task RecordAnchor(LedgerAnchor anchor)
        {
            byte[] anchorPayload =
                anchorMarker
                .Concat(BitConverter.GetBytes((ulong)anchor.TransactionCount).Reverse())
                .Concat(anchor.FullStoreHash.ToByteArray())
                .ToArray();

            using (HttpClient client = new HttpClient())
            {
                BitcoinAddress address = this.publishingAddress.ScriptPubKey.GetDestinationAddress(this.network);
                HttpResponseMessage response = await client.GetAsync(new Uri(url, $"addresses/{address.ToString()}/unspents"));

                response.EnsureSuccessStatusCode();

                string body = await response.Content.ReadAsStringAsync();

                JArray outputs = JArray.Parse(body);

                TransactionBuilder builder = new TransactionBuilder();
                builder.AddKeys(publishingAddress.GetBitcoinSecret(network));
                foreach (JObject output in outputs)
                {
                    string transactionHash = (string)output["transaction_hash"];
                    uint outputIndex = (uint)output["output_index"];
                    long amount = (long)output["value"];

                    builder.AddCoins(new Coin(uint256.Parse(transactionHash), outputIndex, new Money(amount), publishingAddress.ScriptPubKey));
                }

                Script opReturn = new Script(OpcodeType.OP_RETURN, Op.GetPushOp(anchorPayload));
                builder.Send(opReturn, 0);
                builder.SendFees(satoshiFees);
                builder.SetChange(this.publishingAddress.ScriptPubKey, ChangeType.All);

                ByteString seriazliedTransaction = new ByteString(builder.BuildTransaction(true).ToBytes());

                await SubmitTransaction(seriazliedTransaction);
            }
        }
コード例 #4
0
        private async Task<LedgerAnchor> ComputeNewAnchor(LedgerAnchor lastAnchor)
        {
            IReadOnlyList<ByteString> newTransactions;
            byte[] currentHash;
            if (lastAnchor != null)
            {
                newTransactions = await storageEngine.GetTransactions(lastAnchor.Position);
                currentHash = lastAnchor.FullStoreHash.ToByteArray();
            }
            else
            {
                newTransactions = await storageEngine.GetTransactions(null);
                currentHash = new byte[32];
            }

            if (newTransactions.Count == 0)
                return null;

            byte[] position = currentHash;
            byte[] buffer = new byte[64];
            using (SHA256 sha = SHA256.Create())
            {
                foreach (ByteString rawTransaction in newTransactions)
                {
                    currentHash.CopyTo(buffer, 0);
                    position = MessageSerializer.ComputeHash(rawTransaction.ToByteArray());
                    position.CopyTo(buffer, 32);

                    currentHash = sha.ComputeHash(sha.ComputeHash(buffer));
                }
            }

            LedgerAnchor result = new LedgerAnchor(
                new ByteString(position),
                new ByteString(currentHash),
                newTransactions.Count + (lastAnchor != null ? lastAnchor.TransactionCount : 0));

            return result;
        }
コード例 #5
0
        /// <summary>
        /// Determines whether a new anchor should be calculated and recorded,
        /// and does it if it is the case.
        /// </summary>
        /// <returns>The task object representing the asynchronous operation.</returns>
        public async Task <LedgerAnchor> RecordAnchor()
        {
            if (await anchorRecorder.CanRecordAnchor())
            {
                LedgerAnchor anchor = await anchorState.GetLastAnchor();

                LedgerAnchor latestAnchor = await ComputeNewAnchor(anchor);

                if (latestAnchor != null)
                {
                    // Record the anchor
                    await anchorRecorder.RecordAnchor(latestAnchor);

                    // Commit the anchor if it has been recorded successfully
                    await anchorState.CommitAnchor(latestAnchor);

                    return(latestAnchor);
                }
            }

            return(null);
        }