Commit f8eff20e authored by Jeremy Bokobza's avatar Jeremy Bokobza

Added Merkel Proof to receiving transactions

parent 662503f8
...@@ -161,8 +161,8 @@ namespace Breeze.Wallet ...@@ -161,8 +161,8 @@ namespace Breeze.Wallet
/// </summary> /// </summary>
/// <param name="transaction">The transaction.</param> /// <param name="transaction">The transaction.</param>
/// <param name="blockHeight">The height of the block this transaction came from. Null if it was not a transaction included in a block.</param> /// <param name="blockHeight">The height of the block this transaction came from. Null if it was not a transaction included in a block.</param>
/// <param name="blockTime">The block time.</param> /// <param name="block">The block in which this transaction was included.</param>
void ProcessTransaction(Transaction transaction, int? blockHeight = null, uint? blockTime = null); void ProcessTransaction(Transaction transaction, int? blockHeight = null, Block block = null);
/// <summary> /// <summary>
/// Saves the wallet into the file system. /// Saves the wallet into the file system.
......
...@@ -439,6 +439,13 @@ namespace Breeze.Wallet ...@@ -439,6 +439,13 @@ namespace Breeze.Wallet
[JsonConverter(typeof(DateTimeOffsetConverter))] [JsonConverter(typeof(DateTimeOffsetConverter))]
public DateTimeOffset CreationTime { get; set; } public DateTimeOffset CreationTime { get; set; }
/// <summary>
/// Gets or sets the Merkle proof for this transaction.
/// </summary>
[JsonProperty(PropertyName = "merkleProof")]
public MerkleProof MerkleProof { get; set; }
/// <summary> /// <summary>
/// Determines whether this transaction is confirmed. /// Determines whether this transaction is confirmed.
/// </summary> /// </summary>
...@@ -473,4 +480,23 @@ namespace Breeze.Wallet ...@@ -473,4 +480,23 @@ namespace Breeze.Wallet
[JsonConverter(typeof(MoneyJsonConverter))] [JsonConverter(typeof(MoneyJsonConverter))]
public Money Amount { get; set; } public Money Amount { get; set; }
} }
/// <summary>
/// An object representing a Merkle proof
/// </summary>
public class MerkleProof
{
/// <summary>
/// Gets or sets the merkle root.
/// </summary>
[JsonProperty(PropertyName = "merkleRoot")]
[JsonConverter(typeof(UInt256JsonConverter))]
public uint256 MerkleRoot { get; set; }
/// <summary>
/// Gets or sets the merkle path.
/// </summary>
[JsonProperty(PropertyName = "merklePath", ItemConverterType = typeof(UInt256JsonConverter))]
public ICollection<uint256> MerklePath { get; set; }
}
} }
\ No newline at end of file
...@@ -451,7 +451,7 @@ namespace Breeze.Wallet ...@@ -451,7 +451,7 @@ namespace Breeze.Wallet
foreach (Transaction transaction in block.Transactions) foreach (Transaction transaction in block.Transactions)
{ {
this.ProcessTransaction(transaction, height, block.Header.Time); this.ProcessTransaction(transaction, height, block);
} }
// update the wallets with the last processed block height // update the wallets with the last processed block height
...@@ -459,7 +459,7 @@ namespace Breeze.Wallet ...@@ -459,7 +459,7 @@ namespace Breeze.Wallet
} }
/// <inheritdoc /> /// <inheritdoc />
public void ProcessTransaction(Transaction transaction, int? blockHeight = null, uint? blockTime = null) public void ProcessTransaction(Transaction transaction, int? blockHeight = null, Block block = null)
{ {
Console.WriteLine($"transaction notification: tx hash {transaction.GetHash()}, coin type: {this.coinType}"); Console.WriteLine($"transaction notification: tx hash {transaction.GetHash()}, coin type: {this.coinType}");
...@@ -470,7 +470,7 @@ namespace Breeze.Wallet ...@@ -470,7 +470,7 @@ namespace Breeze.Wallet
var utxo = transaction.Outputs.SingleOrDefault(o => pubKey == o.ScriptPubKey); var utxo = transaction.Outputs.SingleOrDefault(o => pubKey == o.ScriptPubKey);
if (utxo != null) if (utxo != null)
{ {
AddTransactionToWallet(transaction.GetHash(), transaction.Time, transaction.Outputs.IndexOf(utxo), utxo.Value, pubKey, blockHeight, blockTime); AddTransactionToWallet(transaction.GetHash(), transaction.Time, transaction.Outputs.IndexOf(utxo), utxo.Value, pubKey, blockHeight, block);
} }
} }
...@@ -486,7 +486,7 @@ namespace Breeze.Wallet ...@@ -486,7 +486,7 @@ namespace Breeze.Wallet
// We first include the keys we don't hold and then we include the keys we do hold but that are for receiving addresses (which would mean the user paid itself). // We first include the keys we don't hold and then we include the keys we do hold but that are for receiving addresses (which would mean the user paid itself).
IEnumerable<TxOut> paidoutto = transaction.Outputs.Where(o => !this.keysLookup.Keys.Contains(o.ScriptPubKey) || (this.keysLookup.ContainsKey(o.ScriptPubKey) && !this.keysLookup[o.ScriptPubKey].IsChangeAddress())); IEnumerable<TxOut> paidoutto = transaction.Outputs.Where(o => !this.keysLookup.Keys.Contains(o.ScriptPubKey) || (this.keysLookup.ContainsKey(o.ScriptPubKey) && !this.keysLookup[o.ScriptPubKey].IsChangeAddress()));
AddTransactionToWallet(transaction.GetHash(), transaction.Time, null, -tTx.Amount, keyToSpend, blockHeight, blockTime, tTx.Id, tTx.Index, paidoutto); AddTransactionToWallet(transaction.GetHash(), transaction.Time, null, -tTx.Amount, keyToSpend, blockHeight, block, tTx.Id, tTx.Index, paidoutto);
} }
} }
...@@ -499,14 +499,15 @@ namespace Breeze.Wallet ...@@ -499,14 +499,15 @@ namespace Breeze.Wallet
/// <param name="amount">The amount.</param> /// <param name="amount">The amount.</param>
/// <param name="script">The script.</param> /// <param name="script">The script.</param>
/// <param name="blockHeight">Height of the block.</param> /// <param name="blockHeight">Height of the block.</param>
/// <param name="blockTime">The block time.</param> /// <param name="block">The block containing the transaction to add.</param>
/// <param name="spendingTransactionId">The id of the transaction containing the output being spent, if this is a spending transaction.</param> /// <param name="spendingTransactionId">The id of the transaction containing the output being spent, if this is a spending transaction.</param>
/// <param name="spendingTransactionIndex">The index of the output in the transaction being referenced, if this is a spending transaction.</param> /// <param name="spendingTransactionIndex">The index of the output in the transaction being referenced, if this is a spending transaction.</param>
private void AddTransactionToWallet(uint256 transactionHash, uint time, int? index, Money amount, Script script, int? blockHeight = null, uint? blockTime = null, uint256 spendingTransactionId = null, int? spendingTransactionIndex = null, IEnumerable<TxOut> paidToOutputs = null) private void AddTransactionToWallet(uint256 transactionHash, uint time, int? index, Money amount, Script script, int? blockHeight = null, Block block = null, uint256 spendingTransactionId = null, int? spendingTransactionIndex = null, IEnumerable<TxOut> paidToOutputs = null)
{ {
// get the collection of transactions to add to. // get the collection of transactions to add to.
this.keysLookup.TryGetValue(script, out HdAddress address); this.keysLookup.TryGetValue(script, out HdAddress address);
var isSpendingTransaction = paidToOutputs != null && paidToOutputs.Any();
var trans = address.Transactions; var trans = address.Transactions;
// if it's the first time we see this transaction // if it's the first time we see this transaction
...@@ -517,13 +518,24 @@ namespace Breeze.Wallet ...@@ -517,13 +518,24 @@ namespace Breeze.Wallet
Amount = amount, Amount = amount,
BlockHeight = blockHeight, BlockHeight = blockHeight,
Id = transactionHash, Id = transactionHash,
CreationTime = DateTimeOffset.FromUnixTimeSeconds(blockTime ?? time), CreationTime = DateTimeOffset.FromUnixTimeSeconds(block?.Header.Time ?? time),
Index = index Index = index
}; };
trans.Add(newTransaction);
// add the Merkle proof to the (non-spending) transaction
if (block != null && !isSpendingTransaction)
{
MerkleBlock merkleBlock = new MerkleBlock(block, new[] { transactionHash });
newTransaction.MerkleProof = new MerkleProof
{
MerkleRoot = block.Header.HashMerkleRoot,
MerklePath = merkleBlock.PartialMerkleTree.Hashes
};
}
// if this is a spending transaction, keep a record of the payments made out to other scripts. // if this is a spending transaction, keep a record of the payments made out to other scripts.
if (paidToOutputs != null && paidToOutputs.Any()) if (isSpendingTransaction)
{ {
List<PaymentDetails> payments = new List<PaymentDetails>(); List<PaymentDetails> payments = new List<PaymentDetails>();
foreach (var paidToOutput in paidToOutputs) foreach (var paidToOutput in paidToOutputs)
...@@ -539,6 +551,8 @@ namespace Breeze.Wallet ...@@ -539,6 +551,8 @@ namespace Breeze.Wallet
newTransaction.Payments = payments; newTransaction.Payments = payments;
} }
trans.Add(newTransaction);
// if this is a spending transaction, mark the spent transaction as such // if this is a spending transaction, mark the spent transaction as such
if (spendingTransactionId != null) if (spendingTransactionId != null)
{ {
...@@ -560,9 +574,9 @@ namespace Breeze.Wallet ...@@ -560,9 +574,9 @@ namespace Breeze.Wallet
} }
// update the block time // update the block time
if (blockTime != null) if (block != null)
{ {
foundTransaction.CreationTime = DateTimeOffset.FromUnixTimeSeconds(blockTime.Value); foundTransaction.CreationTime = DateTimeOffset.FromUnixTimeSeconds(block.Header.Time);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment