4 people like it.
Like the snippet!
Using NBitcoin to create private BlockChain with F# (FSharp)
This is just an initial example / tech-demo.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
|
#if INTERACTIVE
#I "./../packages/NBitcoin/lib/net45/"
#I "./../packages/Newtonsoft.Json/lib/net45"
#r "NBitcoin.dll"
#r "Newtonsoft.Json.dll"
#else
module BlockChain
#endif
open System
open NBitcoin
open NBitcoin.Protocol
// -------------- GENERAL BLOCKCHAIN NETWORK SETTINGS -------------- //
let network =
// Select your network
// Network.Main
// Network.Test
// Or create your own:
let builder = NetworkBuilder()
builder.CopyFrom Network.Main
let genesis = Network.Main.GetGenesis()
//builder.SetGenesis( {genesis.Header.UpdateTime with Ti }
builder.SetName("MyBlockChain").BuildAndRegister()
/// Generate a new wallet private key for a new user as byte array
let getNewPrivateKey() = Key().ToBytes()
/// Create BitcoinSecret from byte array
let getSecret(bytes:byte[]) = BitcoinSecret(Key(bytes), network)
// --------- CUSTOM BLOCKCHAIN AND ITS COMPLEXITY --------- //
/// Complexity of valid mining. Genesis is having 10.
/// But this comes down to how much resources you are willing to
/// spend to validate blockchain. Note: Some part of blockchain
/// security comes from the fact that valid hashes are not so easy
/// to calculate, making the generation of alternative valid blockchain slow.
let leadingZeros = "0000"
/// Validation of blockchain hashes.
type BlockChainCheck =
/// No validation
| NoWork
/// Validation of leadingZeros amount only
| EasyWork
/// Default Bitcoin level validation
| CorrectWork
/// The normal bitcoin validation is leading zeros in hashcodes.
/// Normal mining taking a lot of resources. So this is more
/// lightweight option to mining (with less zeros).
type ChainedBlock with
/// Re-implementation of Validate()
member cb.ValidateEasy(network:Network) =
let genesis = cb.Height = 0
if (not genesis) && cb.Previous = null then false
else
let heightCorrect = genesis || cb.Height = cb.Previous.Height + 1
let genesisCorrect =
(not genesis) || cb.HashBlock = network.GetGenesis().GetHash()
let hashPrevCorrect =
genesis || cb.Header.HashPrevBlock = cb.Previous.HashBlock
let hashCorrect = cb.HashBlock = cb.Header.GetHash()
let workCorrect =
genesis || cb.Header.GetHash().ToString().StartsWith leadingZeros
heightCorrect && genesisCorrect && hashPrevCorrect
&& hashCorrect && workCorrect
type ChainBase with
/// Re-implementation of Validate()
member cb.ValidateEasy(network:Network, ?fullChain) =
let tip = cb.Tip
if tip = null then false
else
match fullChain with
| None | Some true ->
let anyFails =
tip.EnumerateToGenesis()
|> Seq.exists(fun block -> not(block.ValidateEasy network))
not anyFails
| Some false ->
tip.ValidateEasy network
/// This will mine the correct hash.
/// Performance is not optimized: if you would really want to do
/// mining, you would probably want to use some more parallel algorithm.
let ``mine to correct`` checkType (chain:ConcurrentChain) (block:Block) =
let validation =
match checkType with
| NoWork -> fun (cb:ChainedBlock) -> true
| EasyWork -> fun cb -> cb.ValidateEasy network
| CorrectWork -> fun cb -> cb.Validate network
let rec mine nonce =
block.Header.Nonce <- nonce
let headerBlock =
ChainedBlock(block.Header, block.Header.GetHash(),
chain.GetBlock(block.Header.HashPrevBlock))
if validation headerBlock then ()
else mine (nonce+1u)
mine 0u
/// Attach a block to chain
let ``attach to chain`` (checkType:BlockChainCheck) (chain:ConcurrentChain) (block:Block) =
let header = block.Header
header.HashPrevBlock <- chain.Tip.HashBlock
header.Bits <-
//header.GetWorkRequired(network, chain.Tip)
chain.Tip.GetWorkRequired(network)
header.BlockTime <- DateTimeOffset.UtcNow
header.Nonce <- RandomUtils.GetUInt32()
//header.UpdateTime(network, chain.Tip)
block.UpdateMerkleRoot()
``mine to correct`` checkType chain block
chain.SetTip header |> ignore
chain.GetBlock(header.GetHash())
/// Attach a bunch of transactions to a new block
let ``to new block`` txs =
let block = Block()
txs |> Seq.iter (block.AddTransaction >> ignore)
block.UpdateMerkleRoot()
block
// --------- TRANSACTIONS --------- //
/// No fees on our custom block-chain
/// Consifer adding some fee when you want users to do the mining.
let noFees = Unchecked.defaultof<FeeRate>
let txBuilder() =
let b = TransactionBuilder()
b.StandardTransactionPolicy.MinRelayTxFee <- FeeRate.Zero
b
/// Coinbase transaction is a transaction to generate money to our system.
let ``give money`` (toUser:BitcoinSecret) (sum:int) =
let money = Money sum
let coin =
Coin( // Coins for sums, ColoredCoins for assets
// This is a coinbase / generation transaction, so prev hash is zero:
OutPoint(), TxOut(money, toUser.PubKey.ScriptPubKey)
)
let builder = txBuilder()
let tx =
builder
//.IssueAsset(toUser, OpenAsset.AssetMoney(asset.AssetId, quantity))
.AddCoins([| (coin :> ICoin) |])
.AddKeys(toUser)
.Send(toUser, money)
.SetChange(toUser.GetAddress())
.BuildTransaction(true)
if not tx.IsCoinBase then
failwith "Was not a coinbase transaction"
let ok, errs = builder.Verify(tx, noFees)
match ok with
| true -> tx
| false -> failwith(String.Join(",", errs))
/// Normal transaction to transfer money / asset from user to next user.
/// Needs outpoint (coins) from previous transaction to make a block chain.
let ``spend money`` (coins:Coin list) (fromUser:BitcoinSecret) (toUser:BitcoinPubKeyAddress) (sum:int) =
let money = Money sum
let fees = Money.Zero
let coinsArr =
coins
|> List.filter(fun c -> c.TxOut.IsTo fromUser)
|> List.map(fun c -> c :> ICoin) |> List.toArray
let builder = txBuilder()
let tx =
builder
.AddCoins(coinsArr)
.AddKeys(fromUser)
.Send(toUser, (money - fees))
.SendFees(fees)
.SetChange(fromUser.GetAddress())
.BuildTransaction(true)
let ok, errs = builder.Verify(tx, noFees)
match ok with
| true -> tx
| false -> failwith(String.Join(",", errs))
// --------- SOME HELPER FUNCTIONS --------- //
/// Create a new user
let makeUser() =
let user = BitcoinSecret(Key(), network)
Console.WriteLine "Store users private key to a cold dry place and never show it to anyone:"
network |> user.PrivateKey.GetWif |> Console.WriteLine
user
/// Get users coins from transaction
let ``fetch coins of`` dest (tx:Transaction) =
tx.Outputs
|> Seq.mapi(fun idx op -> idx,op)
|> Seq.filter(fun (_,op) -> op.Value > Money.Zero && op.IsTo(dest))
|> Seq.map(fun (idx,op) ->
Coin(OutPoint(tx, idx), op)
) |> Seq.toList
let ``save tracker`` filename (tracker:NBitcoin.SPV.Tracker) =
let filterBefore = tracker.CreateBloomFilter(0.005)
use fileStream = System.IO.File.Create filename
tracker.Save fileStream
let ``load tracker`` filename =
let tracker =
filename |> System.IO.File.OpenRead
|> NBitcoin.SPV.Tracker.Load
if not(tracker.Validate()) then failwith "Not valid tracker"
else tracker
let ``save chain`` filename (chain:ConcurrentChain) =
use fileStream = System.IO.File.Create filename
chain.WriteTo (BitcoinStream(fileStream, true))
let ``load chain`` filename =
let chain = new ConcurrentChain(network)
filename |> System.IO.File.ReadAllBytes |> chain.Load
// if not(chain.Validate network) then failwith "Not valid"
if not(chain.ValidateEasy network) then failwith "Not valid chain"
else chain
// --------- TESTING --------- //
let testing() =
// A block chain, and a tracker
let chain = new ConcurrentChain(network)
let tracker = NBitcoin.SPV.Tracker()
// make some users
let thomas = makeUser()
let antero = makeUser()
let john = makeUser()
tracker.Add thomas
tracker.Add antero
tracker.Add john
// Make Block 1 with transactions and add it to chain
let coinbase1 = ``give money`` thomas 1000
let coins1 = coinbase1 |> ``fetch coins of`` thomas
let transfer1 =
``spend money`` coins1 thomas (antero.GetAddress()) 500
let coins2 = transfer1 |> ``fetch coins of`` thomas
let transfer2 = ``spend money`` coins2 thomas (john.GetAddress()) 300
let block1 =
[coinbase1; transfer1; transfer2]
|> ``to new block``
let chained1 =
block1 |> ``attach to chain`` BlockChainCheck.EasyWork chain
block1.Transactions |> Seq.iter (fun tx ->
tracker.NotifyTransaction(tx, chained1, block1) |> ignore)
// Check that chain and the tracker are valid:
let ``chain ok`` = chain.ValidateEasy network
let ``tracker ok`` = tracker.Validate()
let transactions1 = tracker.GetWalletTransactions chain
//transactions1.GetSpendableCoins()
//transactions1.Summary.Confirmed
// Thomas: 200, Antero: 500, John: 300
// Make Block 2 with transactions and add it to chain
let coinbase2 = ``give money`` thomas 100
let coins3 = transfer1 |> ``fetch coins of`` antero
let transfer3 = ``spend money`` coins3 antero (john.GetAddress()) 500
let coins4 =
(transfer2 |> ``fetch coins of`` thomas) @
(coinbase2 |> ``fetch coins of`` thomas)
let transfer4 =
``spend money`` coins4 thomas (john.GetAddress()) 250
//let coins5 = transfer4 |> ``fetch coins of`` thomas
let block2 =
[coinbase2; transfer3; transfer4]
|> ``to new block``
let chained2 =
block2 |> ``attach to chain`` BlockChainCheck.EasyWork chain
block2.Transactions |> Seq.iter (fun tx ->
tracker.NotifyTransaction(tx, chained2, block2) |> ignore)
// Check the validity of the chain and the tracker
let ``chain still ok`` = chain.ValidateEasy network
let ``tracker still ok`` = tracker.Validate()
let transactions2 = tracker.GetWalletTransactions chain
let ``available coins`` = transactions2.GetSpendableCoins() |> Seq.toList
// transactions2.Count
// transactions2 |> Seq.map(fun b -> b.Balance, b.Transaction.GetHash())
// |> Seq.toArray
// ``available coins`` |> List.map(fun v -> v.Amount) |> List.sum
// ``available coins``
// transactions2.Summary.Confirmed
// Thomas: 50, John: 250+500+300
``save tracker`` @"c:\tracker.dat" tracker
``save chain`` @"c:\chain.dat" chain
// let tracker2 = ``load tracker`` @"c:\tracker.dat"
// let chain2 = ``load chain`` @"c:\chain.dat"
// Some resources:
// Article: https://www.codeproject.com/articles/835098/nbitcoin-build-them-all
// A video: https://www.youtube.com/watch?v=_160oMzblY8
|
namespace System
namespace NBitcoin
namespace NBitcoin.Protocol
val network : Network
Full name: Script.network
val builder : NetworkBuilder
Multiple items
type NetworkBuilder =
new : unit -> NetworkBuilder
member AddAlias : alias:string -> NetworkBuilder
member AddDNSSeeds : seeds:IEnumerable<DNSSeedData> -> NetworkBuilder
member AddSeeds : seeds:IEnumerable<NetworkAddress> -> NetworkBuilder
member BuildAndRegister : unit -> Network
member CopyFrom : network:Network -> unit
member SetBase58Bytes : type:Base58Type * bytes:byte[] -> NetworkBuilder
member SetConsensus : consensus:Consensus -> NetworkBuilder
member SetGenesis : genesis:Block -> NetworkBuilder
member SetMagic : magic:uint32 -> NetworkBuilder
...
Full name: NBitcoin.NetworkBuilder
--------------------
NetworkBuilder() : unit
NetworkBuilder.CopyFrom(network: Network) : unit
type Network =
val _MagicBytes : byte[]
member AlertPubKey : PubKey
member Consensus : Consensus
member CreateAssetId : base58:string -> BitcoinAssetId
member CreateBase58Data : type:Base58Type * base58:string -> Base58Data
member CreateBitcoinAddress : base58:string -> BitcoinAddress + 1 overload
member CreateBitcoinExtKey : key:ExtKey -> BitcoinExtKey + 1 overload
member CreateBitcoinExtPubKey : pubkey:ExtPubKey -> BitcoinExtPubKey
member CreateBitcoinScriptAddress : base58:string -> BitcoinScriptAddress
member CreateBitcoinSecret : base58:string -> BitcoinSecret + 1 overload
...
Full name: NBitcoin.Network
property Network.Main: Network
val genesis : Block
Network.GetGenesis() : Block
NetworkBuilder.SetName(name: string) : NetworkBuilder
val getNewPrivateKey : unit -> byte []
Full name: Script.getNewPrivateKey
Generate a new wallet private key for a new user as byte array
Multiple items
type Key =
new : unit -> Key + 2 overloads
member Derivate : cc:byte[] * nChild:uint32 * ccChild:byte[] -> Key
member GetBitcoinSecret : network:Network -> BitcoinSecret
member GetEncryptedBitcoinSecret : password:string * network:Network -> BitcoinEncryptedSecretNoEC
member GetWif : network:Network -> BitcoinSecret
member IsCompressed : bool with get, set
member PubKey : PubKey
member ReadWrite : stream:BitcoinStream -> unit
member ScriptPubKey : Script
member Sign : hash:uint256 -> ECDSASignature + 1 overload
...
Full name: NBitcoin.Key
--------------------
Key() : unit
Key(fCompressedIn: bool) : unit
Key(data: byte [], ?count: int, ?fCompressedIn: bool) : unit
val getSecret : bytes:byte [] -> BitcoinSecret
Full name: Script.getSecret
Create BitcoinSecret from byte array
val bytes : byte []
Multiple items
val byte : value:'T -> byte (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.byte
--------------------
type byte = Byte
Full name: Microsoft.FSharp.Core.byte
Multiple items
type BitcoinSecret =
inherit Base58Data
new : key:Key * network:Network -> BitcoinSecret + 1 overload
member Copy : compressed:Nullable<bool> -> BitcoinSecret
member Encrypt : password:string -> BitcoinEncryptedSecret
member GetAddress : unit -> BitcoinPubKeyAddress
member IsCompressed : bool
member PrivateKey : Key
member PubKey : PubKey
member PubKeyHash : KeyId
member ScriptPubKey : Script
member Type : Base58Type
Full name: NBitcoin.BitcoinSecret
--------------------
BitcoinSecret(key: Key, network: Network) : unit
BitcoinSecret(base58: string, ?expectedAddress: Network) : unit
val leadingZeros : string
Full name: Script.leadingZeros
Complexity of valid mining. Genesis is having 10.
But this comes down to how much resources you are willing to
spend to validate blockchain. Note: Some part of blockchain
security comes from the fact that valid hashes are not so easy
to calculate, making the generation of alternative valid blockchain slow.
type BlockChainCheck =
| NoWork
| EasyWork
| CorrectWork
Full name: Script.BlockChainCheck
Validation of blockchain hashes.
union case BlockChainCheck.NoWork: BlockChainCheck
No validation
union case BlockChainCheck.EasyWork: BlockChainCheck
Validation of leadingZeros amount only
union case BlockChainCheck.CorrectWork: BlockChainCheck
Default Bitcoin level validation
Multiple items
type ChainedBlock =
new : header:BlockHeader * height:int -> ChainedBlock + 1 overload
member ChainWork : uint256
member CheckProofOfWorkAndTarget : network:Network -> bool + 1 overload
member EnumerateToGenesis : unit -> IEnumerable<ChainedBlock>
member Equals : obj:obj -> bool
member FindAncestorOrSelf : height:int -> ChainedBlock + 1 overload
member FindFork : block:ChainedBlock -> ChainedBlock
member GetAncestor : height:int -> ChainedBlock
member GetHashCode : unit -> int
member GetLocator : unit -> BlockLocator
...
Full name: NBitcoin.ChainedBlock
--------------------
ChainedBlock(header: BlockHeader, height: int) : unit
ChainedBlock(header: BlockHeader, headerHash: uint256, previous: ChainedBlock) : unit
val cb : ChainedBlock
member ChainedBlock.ValidateEasy : network:Network -> bool
Full name: Script.ValidateEasy
Re-implementation of Validate()
val network : Network
val genesis : bool
property ChainedBlock.Height: int
val not : value:bool -> bool
Full name: Microsoft.FSharp.Core.Operators.not
property ChainedBlock.Previous: ChainedBlock
val heightCorrect : bool
val genesisCorrect : bool
property ChainedBlock.HashBlock: uint256
val hashPrevCorrect : bool
property ChainedBlock.Header: BlockHeader
property BlockHeader.HashPrevBlock: uint256
val hashCorrect : bool
BlockHeader.GetHash() : uint256
val workCorrect : bool
type ChainBase =
member Contains : hash:uint256 -> bool + 1 overload
member EnumerateAfter : blockHash:uint256 -> IEnumerable<ChainedBlock> + 1 overload
member EnumerateToTip : block:ChainedBlock -> IEnumerable<ChainedBlock> + 1 overload
member FindFork : chain:ChainBase -> ChainedBlock + 2 overloads
member Genesis : ChainedBlock
member GetBlock : id:uint256 -> ChainedBlock + 1 overload
member GetWorkRequired : network:Network * height:int -> Target
member Height : int
member SameTip : chain:ChainBase -> bool
member SetTip : otherChain:ChainBase -> ChainedBlock + 2 overloads
...
Full name: NBitcoin.ChainBase
val cb : ChainBase
member ChainBase.ValidateEasy : network:Network * ?fullChain:bool -> bool
Full name: Script.ValidateEasy
Re-implementation of Validate()
val fullChain : bool option
val tip : ChainedBlock
property ChainBase.Tip: ChainedBlock
union case Option.None: Option<'T>
union case Option.Some: Value: 'T -> Option<'T>
val anyFails : bool
ChainedBlock.EnumerateToGenesis() : Collections.Generic.IEnumerable<ChainedBlock>
module Seq
from Microsoft.FSharp.Collections
val exists : predicate:('T -> bool) -> source:seq<'T> -> bool
Full name: Microsoft.FSharp.Collections.Seq.exists
val block : ChainedBlock
member ChainedBlock.ValidateEasy : network:Network -> bool
Re-implementation of Validate()
val ( mine to correct ) : checkType:BlockChainCheck -> chain:ConcurrentChain -> block:Block -> unit
Full name: Script.( mine to correct )
This will mine the correct hash.
Performance is not optimized: if you would really want to do
mining, you would probably want to use some more parallel algorithm.
val checkType : BlockChainCheck
val chain : ConcurrentChain
Multiple items
type ConcurrentChain =
inherit ChainBase
new : unit -> ConcurrentChain + 3 overloads
member Clone : unit -> ConcurrentChain
member GetBlock : id:uint256 -> ChainedBlock + 1 overload
member Height : int
member Load : chain:byte[] -> unit + 2 overloads
member SetTip : block:ChainedBlock -> ChainedBlock
member Tip : ChainedBlock
member ToBytes : unit -> byte[]
member ToString : unit -> string
member WriteTo : stream:Stream -> unit + 1 overload
Full name: NBitcoin.ConcurrentChain
--------------------
ConcurrentChain() : unit
ConcurrentChain(genesis: BlockHeader) : unit
ConcurrentChain(network: Network) : unit
ConcurrentChain(bytes: byte []) : unit
val block : Block
Multiple items
type Block =
new : unit -> Block + 2 overloads
member AddTransaction : tx:Transaction -> Transaction
member Check : unit -> bool
member CheckMerkleRoot : unit -> bool
member CheckProofOfWork : unit -> bool
member CreateNextBlockWithCoinbase : address:BitcoinAddress * height:int -> Block + 3 overloads
member Filter : [<ParamArray>] txIds:uint256[] -> MerkleBlock + 1 overload
member GetHash : unit -> uint256
member GetMerkleRoot : unit -> MerkleNode
member Header : BlockHeader
...
Full name: NBitcoin.Block
--------------------
Block() : unit
Block(blockHeader: BlockHeader) : unit
Block(bytes: byte []) : unit
val validation : (ChainedBlock -> bool)
ChainedBlock.Validate(network: Network) : bool
val mine : (uint32 -> unit)
val nonce : uint32
property Block.Header: BlockHeader
property BlockHeader.Nonce: uint32
val headerBlock : ChainedBlock
ConcurrentChain.GetBlock(height: int) : ChainedBlock
ConcurrentChain.GetBlock(id: uint256) : ChainedBlock
val ( attach to chain ) : checkType:BlockChainCheck -> chain:ConcurrentChain -> block:Block -> ChainedBlock
Full name: Script.( attach to chain )
Attach a block to chain
val header : BlockHeader
property ConcurrentChain.Tip: ChainedBlock
property BlockHeader.Bits: Target
ChainedBlock.GetWorkRequired(consensus: Consensus) : Target
ChainedBlock.GetWorkRequired(network: Network) : Target
property BlockHeader.BlockTime: DateTimeOffset
Multiple items
type DateTimeOffset =
struct
new : dateTime:DateTime -> DateTimeOffset + 5 overloads
member Add : timeSpan:TimeSpan -> DateTimeOffset
member AddDays : days:float -> DateTimeOffset
member AddHours : hours:float -> DateTimeOffset
member AddMilliseconds : milliseconds:float -> DateTimeOffset
member AddMinutes : minutes:float -> DateTimeOffset
member AddMonths : months:int -> DateTimeOffset
member AddSeconds : seconds:float -> DateTimeOffset
member AddTicks : ticks:int64 -> DateTimeOffset
member AddYears : years:int -> DateTimeOffset
...
end
Full name: System.DateTimeOffset
--------------------
DateTimeOffset()
DateTimeOffset(dateTime: DateTime) : unit
DateTimeOffset(ticks: int64, offset: TimeSpan) : unit
DateTimeOffset(dateTime: DateTime, offset: TimeSpan) : unit
DateTimeOffset(year: int, month: int, day: int, hour: int, minute: int, second: int, offset: TimeSpan) : unit
DateTimeOffset(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, offset: TimeSpan) : unit
DateTimeOffset(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, calendar: Globalization.Calendar, offset: TimeSpan) : unit
property DateTimeOffset.UtcNow: DateTimeOffset
Multiple items
type RandomUtils =
new : unit -> RandomUtils
static member AddEntropy : data:string -> unit + 1 overload
static member GetBytes : length:int -> byte[] + 1 overload
static member GetInt32 : unit -> int
static member GetInt64 : unit -> int64
static member GetUInt32 : unit -> uint32
static member GetUInt64 : unit -> uint64
static member Random : IRandom with get, set
Full name: NBitcoin.RandomUtils
--------------------
RandomUtils() : unit
RandomUtils.GetUInt32() : uint32
Block.UpdateMerkleRoot() : unit
ChainBase.SetTip(header: BlockHeader) : bool
ChainBase.SetTip(otherChain: ChainBase) : ChainedBlock
ConcurrentChain.SetTip(block: ChainedBlock) : ChainedBlock
val ignore : value:'T -> unit
Full name: Microsoft.FSharp.Core.Operators.ignore
val ( to new block ) : txs:seq<#Transaction> -> Block
Full name: Script.( to new block )
Attach a bunch of transactions to a new block
val txs : seq<#Transaction>
val iter : action:('T -> unit) -> source:seq<'T> -> unit
Full name: Microsoft.FSharp.Collections.Seq.iter
Block.AddTransaction(tx: Transaction) : Transaction
val noFees : FeeRate
Full name: Script.noFees
No fees on our custom block-chain
Consifer adding some fee when you want users to do the mining.
module Unchecked
from Microsoft.FSharp.Core.Operators
val defaultof<'T> : 'T
Full name: Microsoft.FSharp.Core.Operators.Unchecked.defaultof
Multiple items
type FeeRate =
new : feePerK:Money -> FeeRate + 1 overload
member CompareTo : other:FeeRate -> int + 1 overload
member Equals : obj:obj -> bool + 1 overload
member FeePerK : Money
member GetFee : size:int -> Money + 1 overload
member GetHashCode : unit -> int
member ToString : unit -> string
static member Max : left:FeeRate * right:FeeRate -> FeeRate
static member Min : left:FeeRate * right:FeeRate -> FeeRate
static member Zero : FeeRate
Full name: NBitcoin.FeeRate
--------------------
FeeRate(feePerK: Money) : unit
FeeRate(feePaid: Money, size: int) : unit
val txBuilder : unit -> TransactionBuilder
Full name: Script.txBuilder
val b : TransactionBuilder
Multiple items
type TransactionBuilder =
new : unit -> TransactionBuilder + 1 overload
member AddCoins : [<ParamArray>] coins:ICoin[] -> TransactionBuilder + 2 overloads
member AddKeys : [<ParamArray>] keys:ISecret[] -> TransactionBuilder + 1 overload
member AddKnownRedeems : [<ParamArray>] knownRedeems:Script[] -> TransactionBuilder
member AddKnownSignature : pubKey:PubKey * signature:TransactionSignature -> TransactionBuilder + 1 overload
member BuildTransaction : sign:bool -> Transaction + 1 overload
member Check : tx:Transaction -> TransactionPolicyError[] + 2 overloads
member CoinFinder : Func<OutPoint, ICoin> with get, set
member CoinSelector : ICoinSelector with get, set
member CombineSignatures : [<ParamArray>] transactions:Transaction[] -> Transaction
...
Full name: NBitcoin.TransactionBuilder
--------------------
TransactionBuilder() : unit
TransactionBuilder(seed: int) : unit
property TransactionBuilder.StandardTransactionPolicy: Policy.StandardTransactionPolicy
property Policy.StandardTransactionPolicy.MinRelayTxFee: FeeRate
property FeeRate.Zero: FeeRate
val ( give money ) : toUser:BitcoinSecret -> sum:int -> Transaction
Full name: Script.( give money )
Coinbase transaction is a transaction to generate money to our system.
val toUser : BitcoinSecret
val sum : int
Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
val money : Money
Multiple items
type Money =
new : satoshis:int -> Money + 4 overloads
member Abs : unit -> Money
member Almost : amount:Money * dust:Money -> bool + 1 overload
member CompareTo : other:Money -> int + 1 overload
member Equals : other:Money -> bool + 1 overload
member GetHashCode : unit -> int
member Satoshi : int64 with get, set
member Split : parts:int -> IEnumerable<Money>
member ToDecimal : unit:MoneyUnit -> decimal
member ToString : unit -> string + 1 overload
...
Full name: NBitcoin.Money
--------------------
Money(satoshis: int) : unit
Money(satoshis: uint32) : unit
Money(satoshis: int64) : unit
Money(satoshis: uint64) : unit
Money(amount: decimal, unit: MoneyUnit) : unit
val coin : Coin
Multiple items
type Coin =
new : unit -> Coin + 5 overloads
member Amount : Money with get, set
member CanGetScriptCode : bool
member GetHashVersion : unit -> HashVersion
member GetScriptCode : unit -> Script
member Outpoint : OutPoint with get, set
member ScriptPubKey : Script with get, set
member ToColoredCoin : asset:AssetMoney -> ColoredCoin + 2 overloads
member ToScriptCoin : redeemScript:Script -> ScriptCoin
member TxOut : TxOut with get, set
Full name: NBitcoin.Coin
--------------------
Coin() : unit
Coin(txOut: IndexedTxOut) : unit
Coin(fromOutpoint: OutPoint, fromTxOut: TxOut) : unit
Coin(fromTx: Transaction, fromOutputIndex: uint32) : unit
Coin(fromTx: Transaction, fromOutput: TxOut) : unit
Coin(fromTxHash: uint256, fromOutputIndex: uint32, amount: Money, scriptPubKey: Script) : unit
Multiple items
type OutPoint =
new : unit -> OutPoint + 5 overloads
member Equals : obj:obj -> bool
member GetHashCode : unit -> int
member Hash : uint256 with get, set
member IsNull : bool
member N : uint32 with get, set
member ReadWrite : stream:BitcoinStream -> unit
member ToString : unit -> string
static member Parse : str:string -> OutPoint
static member TryParse : str:string * result:OutPoint -> bool
Full name: NBitcoin.OutPoint
--------------------
OutPoint() : unit
OutPoint(outpoint: OutPoint) : unit
OutPoint(hashIn: uint256, nIn: uint32) : unit
OutPoint(hashIn: uint256, nIn: int) : unit
OutPoint(tx: Transaction, i: uint32) : unit
OutPoint(tx: Transaction, i: int) : unit
Multiple items
type TxOut =
new : unit -> TxOut + 2 overloads
member GetDustThreshold : minRelayTxFee:FeeRate -> Money
member IsDust : minRelayTxFee:FeeRate -> bool
member IsTo : destination:IDestination -> bool
member ReadWrite : stream:BitcoinStream -> unit
member ScriptPubKey : Script with get, set
member Value : Money with get, set
static member Parse : hex:string -> TxOut
Full name: NBitcoin.TxOut
--------------------
TxOut() : unit
TxOut(value: Money, destination: IDestination) : unit
TxOut(value: Money, scriptPubKey: Script) : unit
property BitcoinSecret.PubKey: PubKey
property PubKey.ScriptPubKey: Script
val builder : TransactionBuilder
val tx : Transaction
type ICoin =
member Amount : IMoney
member CanGetScriptCode : bool
member GetHashVersion : unit -> HashVersion
member GetScriptCode : unit -> Script
member Outpoint : OutPoint
member TxOut : TxOut
Full name: NBitcoin.ICoin
BitcoinSecret.GetAddress() : BitcoinPubKeyAddress
property Transaction.IsCoinBase: bool
val failwith : message:string -> 'T
Full name: Microsoft.FSharp.Core.Operators.failwith
val ok : bool
val errs : Policy.TransactionPolicyError []
TransactionBuilder.Verify(tx: Transaction) : bool
TransactionBuilder.Verify(tx: Transaction, errors: byref<Policy.TransactionPolicyError []>) : bool
TransactionBuilder.Verify(tx: Transaction, expectedFeeRate: FeeRate) : bool
TransactionBuilder.Verify(tx: Transaction, expectedFees: Money) : bool
TransactionBuilder.Verify(tx: Transaction, expectedFeeRate: FeeRate, errors: byref<Policy.TransactionPolicyError []>) : bool
TransactionBuilder.Verify(tx: Transaction, expectedFees: Money, errors: byref<Policy.TransactionPolicyError []>) : bool
Multiple items
type String =
new : value:char -> string + 7 overloads
member Chars : int -> char
member Clone : unit -> obj
member CompareTo : value:obj -> int + 1 overload
member Contains : value:string -> bool
member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
member EndsWith : value:string -> bool + 2 overloads
member Equals : obj:obj -> bool + 2 overloads
member GetEnumerator : unit -> CharEnumerator
member GetHashCode : unit -> int
...
Full name: System.String
--------------------
String(value: nativeptr<char>) : unit
String(value: nativeptr<sbyte>) : unit
String(value: char []) : unit
String(c: char, count: int) : unit
String(value: nativeptr<char>, startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
String(value: char [], startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Text.Encoding) : unit
String.Join(separator: string, values: Collections.Generic.IEnumerable<string>) : string
String.Join<'T>(separator: string, values: Collections.Generic.IEnumerable<'T>) : string
String.Join(separator: string, [<ParamArray>] values: obj []) : string
String.Join(separator: string, [<ParamArray>] value: string []) : string
String.Join(separator: string, value: string [], startIndex: int, count: int) : string
val ( spend money ) : coins:Coin list -> fromUser:BitcoinSecret -> toUser:BitcoinPubKeyAddress -> sum:int -> Transaction
Full name: Script.( spend money )
Normal transaction to transfer money / asset from user to next user.
Needs outpoint (coins) from previous transaction to make a block chain.
val coins : Coin list
type 'T list = List<'T>
Full name: Microsoft.FSharp.Collections.list<_>
val fromUser : BitcoinSecret
val toUser : BitcoinPubKeyAddress
Multiple items
type BitcoinPubKeyAddress =
inherit BitcoinAddress
new : base58:string * ?expectedNetwork:Network -> BitcoinPubKeyAddress + 1 overload
member Hash : KeyId
member Type : Base58Type
member VerifyMessage : message:string * signature:string -> bool
Full name: NBitcoin.BitcoinPubKeyAddress
--------------------
BitcoinPubKeyAddress(base58: string, ?expectedNetwork: Network) : unit
BitcoinPubKeyAddress(keyId: KeyId, network: Network) : unit
val fees : Money
property Money.Zero: Money
val coinsArr : ICoin []
Multiple items
module List
from Microsoft.FSharp.Collections
--------------------
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
interface IEnumerable
interface IEnumerable<'T>
member GetSlice : startIndex:int option * endIndex:int option -> 'T list
member Head : 'T
member IsEmpty : bool
member Item : index:int -> 'T with get
member Length : int
member Tail : 'T list
static member Cons : head:'T * tail:'T list -> 'T list
static member Empty : 'T list
Full name: Microsoft.FSharp.Collections.List<_>
val filter : predicate:('T -> bool) -> list:'T list -> 'T list
Full name: Microsoft.FSharp.Collections.List.filter
val c : Coin
property Coin.TxOut: TxOut
TxOut.IsTo(destination: IDestination) : bool
val map : mapping:('T -> 'U) -> list:'T list -> 'U list
Full name: Microsoft.FSharp.Collections.List.map
val toArray : list:'T list -> 'T []
Full name: Microsoft.FSharp.Collections.List.toArray
val makeUser : unit -> BitcoinSecret
Full name: Script.makeUser
Create a new user
val user : BitcoinSecret
type Console =
static member BackgroundColor : ConsoleColor with get, set
static member Beep : unit -> unit + 1 overload
static member BufferHeight : int with get, set
static member BufferWidth : int with get, set
static member CapsLock : bool
static member Clear : unit -> unit
static member CursorLeft : int with get, set
static member CursorSize : int with get, set
static member CursorTop : int with get, set
static member CursorVisible : bool with get, set
...
Full name: System.Console
Console.WriteLine() : unit
(+0 other overloads)
Console.WriteLine(value: string) : unit
(+0 other overloads)
Console.WriteLine(value: obj) : unit
(+0 other overloads)
Console.WriteLine(value: uint64) : unit
(+0 other overloads)
Console.WriteLine(value: int64) : unit
(+0 other overloads)
Console.WriteLine(value: uint32) : unit
(+0 other overloads)
Console.WriteLine(value: int) : unit
(+0 other overloads)
Console.WriteLine(value: float32) : unit
(+0 other overloads)
Console.WriteLine(value: float) : unit
(+0 other overloads)
Console.WriteLine(value: decimal) : unit
(+0 other overloads)
property BitcoinSecret.PrivateKey: Key
Key.GetWif(network: Network) : BitcoinSecret
val ( fetch coins of ) : dest:IDestination -> tx:Transaction -> Coin list
Full name: Script.( fetch coins of )
Get users coins from transaction
val dest : IDestination
Multiple items
type Transaction =
new : unit -> Transaction + 2 overloads
member AddInput : in:TxIn -> TxIn + 1 overload
member AddOutput : out:TxOut -> TxOut + 2 overloads
member CacheHashes : unit -> unit
member CalculateSequenceLocks : prevHeights:int[] * block:ChainedBlock * ?flags:LockTimeFlags -> SequenceLock
member Check : unit -> TransactionCheckResult
member CheckSequenceLocks : prevHeights:int[] * block:ChainedBlock * ?flags:LockTimeFlags -> bool
member Clone : cloneCache:bool -> Transaction
member CreatePayload : unit -> TxPayload
member GetFee : spentCoins:ICoin[] -> Money
...
nested type LockTimeFlags
Full name: NBitcoin.Transaction
--------------------
Transaction() : unit
Transaction(bytes: byte []) : unit
Transaction(hex: string, ?version: ProtocolVersion) : unit
property Transaction.Outputs: TxOutList
val mapi : mapping:(int -> 'T -> 'U) -> source:seq<'T> -> seq<'U>
Full name: Microsoft.FSharp.Collections.Seq.mapi
val idx : int
val op : TxOut
val filter : predicate:('T -> bool) -> source:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Collections.Seq.filter
property TxOut.Value: Money
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>
Full name: Microsoft.FSharp.Collections.Seq.map
val toList : source:seq<'T> -> 'T list
Full name: Microsoft.FSharp.Collections.Seq.toList
val ( save tracker ) : filename:string -> tracker:SPV.Tracker -> unit
Full name: Script.( save tracker )
val filename : string
val tracker : SPV.Tracker
namespace NBitcoin.SPV
Multiple items
type Tracker =
new : unit -> Tracker
member Add : destination:IDestination * ?isRedeemScript:bool * ?isInternal:bool * ?filter:string * ?wallet:string -> unit + 1 overload
member CreateBloomFilter : fp:float * ?flags:BloomFlags -> BloomFilter
member GetDataToTrack : ?filter:string -> IEnumerable<byte[]>
member GetKnownTransaction : txId:uint256 -> Transaction
member GetWalletTransactions : chain:ChainBase * ?wallet:string -> WalletTransactionsCollection
member NotifyTransaction : transaction:Transaction -> bool + 2 overloads
member Save : stream:Stream -> unit
member UpdateTweak : unit -> unit
member Validate : unit -> bool
...
nested type IOperation
nested type NewTrackerOperation
Full name: NBitcoin.SPV.Tracker
--------------------
SPV.Tracker() : unit
val filterBefore : BloomFilter
SPV.Tracker.CreateBloomFilter(fp: float, ?flags: BloomFlags) : BloomFilter
val fileStream : IO.FileStream
namespace System.IO
type File =
static member AppendAllLines : path:string * contents:IEnumerable<string> -> unit + 1 overload
static member AppendAllText : path:string * contents:string -> unit + 1 overload
static member AppendText : path:string -> StreamWriter
static member Copy : sourceFileName:string * destFileName:string -> unit + 1 overload
static member Create : path:string -> FileStream + 3 overloads
static member CreateText : path:string -> StreamWriter
static member Decrypt : path:string -> unit
static member Delete : path:string -> unit
static member Encrypt : path:string -> unit
static member Exists : path:string -> bool
...
Full name: System.IO.File
IO.File.Create(path: string) : IO.FileStream
IO.File.Create(path: string, bufferSize: int) : IO.FileStream
IO.File.Create(path: string, bufferSize: int, options: IO.FileOptions) : IO.FileStream
IO.File.Create(path: string, bufferSize: int, options: IO.FileOptions, fileSecurity: Security.AccessControl.FileSecurity) : IO.FileStream
SPV.Tracker.Save(stream: IO.Stream) : unit
val ( load tracker ) : filename:string -> SPV.Tracker
Full name: Script.( load tracker )
IO.File.OpenRead(path: string) : IO.FileStream
SPV.Tracker.Load(stream: IO.Stream) : SPV.Tracker
SPV.Tracker.Validate() : bool
val ( save chain ) : filename:string -> chain:ConcurrentChain -> unit
Full name: Script.( save chain )
ConcurrentChain.WriteTo(stream: BitcoinStream) : unit
ConcurrentChain.WriteTo(stream: IO.Stream) : unit
Multiple items
type BitcoinStream =
new : bytes:byte[] -> BitcoinStream + 1 overload
member BigEndianScope : unit -> IDisposable
member CopyParameters : stream:BitcoinStream -> unit
member Counter : PerformanceCounter
member Inner : Stream
member IsBigEndian : bool with get, set
member MaxArraySize : int with get, set
member ProtocolVersion : ProtocolVersion with get, set
member ProtocolVersionScope : version:ProtocolVersion -> IDisposable
member ReadCancellationToken : CancellationToken with get, set
...
Full name: NBitcoin.BitcoinStream
--------------------
BitcoinStream(bytes: byte []) : unit
BitcoinStream(inner: IO.Stream, serializing: bool) : unit
val ( load chain ) : filename:string -> ConcurrentChain
Full name: Script.( load chain )
IO.File.ReadAllBytes(path: string) : byte []
ConcurrentChain.Load(stream: BitcoinStream) : unit
ConcurrentChain.Load(stream: IO.Stream) : unit
ConcurrentChain.Load(chain: byte []) : unit
member ChainBase.ValidateEasy : network:Network * ?fullChain:bool -> bool
Re-implementation of Validate()
val testing : unit -> unit
Full name: Script.testing
val thomas : BitcoinSecret
val antero : BitcoinSecret
val john : BitcoinSecret
SPV.Tracker.Add(scriptPubKey: Script, ?isRedeemScript: bool, ?isInternal: bool, ?filter: string, ?wallet: string) : bool
SPV.Tracker.Add(destination: IDestination, ?isRedeemScript: bool, ?isInternal: bool, ?filter: string, ?wallet: string) : unit
val coinbase1 : Transaction
val coins1 : Coin list
val transfer1 : Transaction
val coins2 : Coin list
val transfer2 : Transaction
val block1 : Block
val chained1 : ChainedBlock
property Block.Transactions: Collections.Generic.List<Transaction>
SPV.Tracker.NotifyTransaction(transaction: Transaction) : bool
SPV.Tracker.NotifyTransaction(transaction: Transaction, chainedBlock: ChainedBlock, proof: MerkleBlock) : bool
SPV.Tracker.NotifyTransaction(transaction: Transaction, chainedBlock: ChainedBlock, block: Block) : bool
val ( chain ok ) : bool
val ( tracker ok ) : bool
val transactions1 : SPV.WalletTransactionsCollection
SPV.Tracker.GetWalletTransactions(chain: ChainBase, ?wallet: string) : SPV.WalletTransactionsCollection
val coinbase2 : Transaction
val coins3 : Coin list
val transfer3 : Transaction
val coins4 : Coin list
val transfer4 : Transaction
val block2 : Block
val chained2 : ChainedBlock
val ( chain still ok ) : bool
val ( tracker still ok ) : bool
val transactions2 : SPV.WalletTransactionsCollection
val ( available coins ) : Coin list
SPV.WalletTransactionsCollection.GetSpendableCoins() : Collections.Generic.IEnumerable<Coin>
More information