Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
B
Breeze
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
3
Issues
3
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DeStream-public
Breeze
Commits
c3c089a3
Commit
c3c089a3
authored
Apr 30, 2017
by
Jeremy Bokobza
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added synchronization of blocks and transactions into the relevant addresses.
parent
a17f8ca6
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
158 additions
and
6 deletions
+158
-6
IWalletManager.cs
Breeze/src/Breeze.Wallet/IWalletManager.cs
+3
-1
Wallet.cs
Breeze/src/Breeze.Wallet/Wallet.cs
+10
-2
WalletManager.cs
Breeze/src/Breeze.Wallet/WalletManager.cs
+145
-3
No files found.
Breeze/src/Breeze.Wallet/IWalletManager.cs
View file @
c3c089a3
...
@@ -94,6 +94,8 @@ namespace Breeze.Wallet
...
@@ -94,6 +94,8 @@ namespace Breeze.Wallet
/// </summary>
/// </summary>
/// <param name="coinType">The type of coin this transaction relates to.</param>
/// <param name="coinType">The type of coin this transaction relates to.</param>
/// <param name="transaction">The transaction.</param>
/// <param name="transaction">The transaction.</param>
void
ProcessTransaction
(
CoinType
coinType
,
NBitcoin
.
Transaction
transaction
);
/// <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>
void
ProcessTransaction
(
CoinType
coinType
,
NBitcoin
.
Transaction
transaction
,
int
?
blockHeight
=
null
,
uint
?
blockTime
=
null
);
}
}
}
}
Breeze/src/Breeze.Wallet/Wallet.cs
View file @
c3c089a3
...
@@ -210,19 +210,27 @@ namespace Breeze.Wallet
...
@@ -210,19 +210,27 @@ namespace Breeze.Wallet
/// Transaction id.
/// Transaction id.
/// </summary>
/// </summary>
[
JsonProperty
(
PropertyName
=
"id"
)]
[
JsonProperty
(
PropertyName
=
"id"
)]
public
string
Id
{
get
;
set
;
}
[
JsonConverter
(
typeof
(
UInt256JsonConverter
))]
public
uint256
Id
{
get
;
set
;
}
/// <summary>
/// <summary>
/// The transaction amount.
/// The transaction amount.
/// </summary>
/// </summary>
[
JsonProperty
(
PropertyName
=
"amount"
)]
[
JsonProperty
(
PropertyName
=
"amount"
)]
[
JsonConverter
(
typeof
(
MoneyJsonConverter
))]
public
Money
Amount
{
get
;
set
;
}
public
Money
Amount
{
get
;
set
;
}
/// <summary>
/// The index of this scriptPubKey in the transaction it is contained.
/// </summary>
[
JsonProperty
(
PropertyName
=
"index"
)]
public
int
?
Index
{
get
;
set
;
}
/// <summary>
/// <summary>
/// The height of the block including this transaction.
/// The height of the block including this transaction.
/// </summary>
/// </summary>
[
JsonProperty
(
PropertyName
=
"blockHeight"
)]
[
JsonProperty
(
PropertyName
=
"blockHeight"
)]
public
int
BlockHeight
{
get
;
set
;
}
public
int
?
BlockHeight
{
get
;
set
;
}
/// <summary>
/// <summary>
/// Whether this transaction has been confirmed or not.
/// Whether this transaction has been confirmed or not.
...
...
Breeze/src/Breeze.Wallet/WalletManager.cs
View file @
c3c089a3
...
@@ -18,6 +18,10 @@ namespace Breeze.Wallet
...
@@ -18,6 +18,10 @@ namespace Breeze.Wallet
{
{
public
List
<
Wallet
>
Wallets
{
get
;
}
public
List
<
Wallet
>
Wallets
{
get
;
}
public
HashSet
<
Script
>
PubKeys
{
get
;
}
public
HashSet
<
TransactionDetails
>
TrackedTransactions
{
get
;
}
public
WalletManager
()
public
WalletManager
()
{
{
this
.
Wallets
=
new
List
<
Wallet
>();
this
.
Wallets
=
new
List
<
Wallet
>();
...
@@ -27,6 +31,11 @@ namespace Breeze.Wallet
...
@@ -27,6 +31,11 @@ namespace Breeze.Wallet
{
{
this
.
Load
(
this
.
GetWallet
(
path
));
this
.
Load
(
this
.
GetWallet
(
path
));
}
}
// load data in memory for faster lookups
// TODO get the coin type from somewhere else
this
.
PubKeys
=
this
.
LoadKeys
(
CoinType
.
Bitcoin
);
this
.
TrackedTransactions
=
this
.
LoadTransactions
(
CoinType
.
Bitcoin
);
}
}
/// <inheritdoc />
/// <inheritdoc />
...
@@ -184,8 +193,11 @@ namespace Breeze.Wallet
...
@@ -184,8 +193,11 @@ namespace Breeze.Wallet
CreationTime
=
DateTimeOffset
.
Now
CreationTime
=
DateTimeOffset
.
Now
}});
}});
// persists the address to the wallet file
this
.
SaveToFile
(
wallet
);
this
.
SaveToFile
(
wallet
);
// adds the address to the list of tracked addresses
this
.
PubKeys
.
Add
(
address
.
ScriptPubKey
);
return
address
.
ToString
();
return
address
.
ToString
();
}
}
...
@@ -219,6 +231,11 @@ namespace Breeze.Wallet
...
@@ -219,6 +231,11 @@ namespace Breeze.Wallet
{
{
Console
.
WriteLine
(
$"block notification: height:
{
height
}
, block hash:
{
block
.
Header
.
GetHash
()}
, coin type:
{
coinType
}
"
);
Console
.
WriteLine
(
$"block notification: height:
{
height
}
, block hash:
{
block
.
Header
.
GetHash
()}
, coin type:
{
coinType
}
"
);
foreach
(
Transaction
transaction
in
block
.
Transactions
)
{
this
.
ProcessTransaction
(
coinType
,
transaction
,
height
,
block
.
Header
.
Time
);
}
// update the wallets with the last processed block height
// update the wallets with the last processed block height
foreach
(
var
wallet
in
this
.
Wallets
)
foreach
(
var
wallet
in
this
.
Wallets
)
{
{
...
@@ -230,9 +247,88 @@ namespace Breeze.Wallet
...
@@ -230,9 +247,88 @@ namespace Breeze.Wallet
}
}
/// <inheritdoc />
/// <inheritdoc />
public
void
ProcessTransaction
(
CoinType
coinType
,
Transaction
transaction
)
public
void
ProcessTransaction
(
CoinType
coinType
,
Transaction
transaction
,
int
?
blockHeight
=
null
,
uint
?
blockTime
=
null
)
{
{
Console
.
WriteLine
(
$"transaction notification: tx hash
{
transaction
.
GetHash
()}
, coin type:
{
coinType
}
"
);
Console
.
WriteLine
(
$"transaction notification: tx hash
{
transaction
.
GetHash
()}
, coin type:
{
coinType
}
"
);
foreach
(
var
k
in
this
.
PubKeys
)
{
// check if the outputs contain one of our addresses
var
utxo
=
transaction
.
Outputs
.
SingleOrDefault
(
o
=>
k
==
o
.
ScriptPubKey
);
if
(
utxo
!=
null
)
{
AddTransactionToWallet
(
coinType
,
transaction
.
GetHash
(),
transaction
.
Time
,
transaction
.
Outputs
.
IndexOf
(
utxo
),
utxo
.
Value
,
k
,
blockHeight
,
blockTime
);
}
// if the inputs have a reference to a transaction containing one of our scripts
foreach
(
TxIn
input
in
transaction
.
Inputs
.
Where
(
txIn
=>
this
.
TrackedTransactions
.
Any
(
trackedTx
=>
trackedTx
.
Hash
==
txIn
.
PrevOut
.
Hash
)))
{
TransactionDetails
tTx
=
this
.
TrackedTransactions
.
Single
(
trackedTx
=>
trackedTx
.
Hash
==
input
.
PrevOut
.
Hash
);
// compare the index of the output in its original transaction and the index references in the input
if
(
input
.
PrevOut
.
N
==
tTx
.
Index
)
{
AddTransactionToWallet
(
coinType
,
transaction
.
GetHash
(),
transaction
.
Time
,
null
,
-
tTx
.
Amount
,
k
,
blockHeight
,
blockTime
);
}
}
}
}
/// <summary>
/// Adds the transaction to the wallet.
/// </summary>
/// <param name="coinType">Type of the coin.</param>
/// <param name="transactionHash">The transaction hash.</param>
/// <param name="time">The time.</param>
/// <param name="index">The index.</param>
/// <param name="amount">The amount.</param>
/// <param name="script">The script.</param>
/// <param name="blockHeight">Height of the block.</param>
/// <param name="blockTime">The block time.</param>
private
void
AddTransactionToWallet
(
CoinType
coinType
,
uint256
transactionHash
,
uint
time
,
int
?
index
,
Money
amount
,
Script
script
,
int
?
blockHeight
=
null
,
uint
?
blockTime
=
null
)
{
// selects all the transactions we already have in the wallet
var
txs
=
this
.
Wallets
.
SelectMany
(
w
=>
w
.
AccountsRoot
.
Where
(
a
=>
a
.
CoinType
==
coinType
)).
SelectMany
(
a
=>
a
.
Accounts
).
SelectMany
(
a
=>
a
.
ExternalAddresses
).
SelectMany
(
t
=>
t
.
Transactions
);
// add this transaction if it is not in the list
if
(
txs
.
All
(
t
=>
t
.
Id
!=
transactionHash
))
{
foreach
(
var
wallet
in
this
.
Wallets
)
{
foreach
(
var
accountRoot
in
wallet
.
AccountsRoot
.
Where
(
a
=>
a
.
CoinType
==
coinType
))
{
foreach
(
var
account
in
accountRoot
.
Accounts
)
{
foreach
(
var
address
in
account
.
ExternalAddresses
.
Where
(
a
=>
a
.
ScriptPubKey
==
script
))
{
address
.
Transactions
=
address
.
Transactions
.
Concat
(
new
[]
{
new
TransactionData
{
Amount
=
amount
,
BlockHeight
=
blockHeight
,
Confirmed
=
blockHeight
.
HasValue
,
Id
=
transactionHash
,
CreationTime
=
DateTimeOffset
.
FromUnixTimeMilliseconds
(
blockTime
??
time
),
Index
=
index
}
});
}
}
}
}
this
.
TrackedTransactions
.
Add
(
new
TransactionDetails
{
Hash
=
transactionHash
,
Index
=
index
,
Amount
=
amount
});
}
}
}
/// <inheritdoc />
/// <inheritdoc />
...
@@ -375,5 +471,51 @@ namespace Breeze.Wallet
...
@@ -375,5 +471,51 @@ namespace Breeze.Wallet
return
$"
{
Environment
.
GetEnvironmentVariable
(
"HOME"
)}
/.breeze"
;
return
$"
{
Environment
.
GetEnvironmentVariable
(
"HOME"
)}
/.breeze"
;
}
}
/// <summary>
/// Loads the script pub key we're tracking for faster lookups.
/// </summary>
/// <param name="coinType">Type of the coin.</param>
/// <returns></returns>
private
HashSet
<
Script
>
LoadKeys
(
CoinType
coinType
)
{
return
new
HashSet
<
Script
>(
this
.
Wallets
.
SelectMany
(
w
=>
w
.
AccountsRoot
.
Where
(
a
=>
a
.
CoinType
==
coinType
)).
SelectMany
(
a
=>
a
.
Accounts
).
SelectMany
(
a
=>
a
.
ExternalAddresses
).
Select
(
s
=>
s
.
ScriptPubKey
));
// uncomment the following for testing on a random address
// Select(t => (new BitcoinPubKeyAddress(t.Address, Network.Main)).ScriptPubKey));
}
/// <summary>
/// Loads the transactions we're tracking in memory for faster lookups.
/// </summary>
/// <param name="coinType">Type of the coin.</param>
/// <returns></returns>
private
HashSet
<
TransactionDetails
>
LoadTransactions
(
CoinType
coinType
)
{
return
new
HashSet
<
TransactionDetails
>(
this
.
Wallets
.
SelectMany
(
w
=>
w
.
AccountsRoot
.
Where
(
a
=>
a
.
CoinType
==
coinType
)).
SelectMany
(
a
=>
a
.
Accounts
).
SelectMany
(
a
=>
a
.
ExternalAddresses
).
SelectMany
(
t
=>
t
.
Transactions
).
Select
(
t
=>
new
TransactionDetails
{
Hash
=
t
.
Id
,
Index
=
t
.
Index
,
Amount
=
t
.
Amount
}));
}
}
public
class
TransactionDetails
{
public
uint256
Hash
{
get
;
set
;
}
public
int
?
Index
{
get
;
set
;
}
public
Money
Amount
{
get
;
internal
set
;
}
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment