Unit Tests from the Core Client

1: 
module Test.Script

Script tests

 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: 
let parseScript (scriptString: string) = 
    let tokens = scriptString.Split([|' '|], StringSplitOptions.RemoveEmptyEntries) |> Array.toList
    let scriptBytes = new MemoryStream()
    let scriptWriter = new BinaryWriter(scriptBytes)

    let intToBytes (i: bigint) =
        let pos = abs i
        let bi = pos.ToByteArray()
        let posTrimIdx = revFind bi (fun b -> b <> 0uy)
        let iTrimIdx = 
            if (bi.[posTrimIdx] &&& 0x80uy) <> 0uy
                then posTrimIdx + 1
                else posTrimIdx
        let bytes = bi.[0..iTrimIdx]
        if i < 0I then
            bytes.[iTrimIdx] <- bytes.[iTrimIdx] ||| 0x80uy
        bytes

    let rec parseOne (tokens: string list) =
        match tokens with 
        | [] -> ignore()
        | token::rest -> 
            let c = token.[0]
            let code = (opCodes |> Map.tryFind (if token.StartsWith("OP_") then token.[3..] else token))
            if code.IsSome then
                scriptWriter.Write(byte code.Value)
            elif c = '\'' then
                let message = ASCIIEncoding.ASCII.GetBytes (token.[1..token.Length-2])
                let len = message.Length
                if len <= 75
                then scriptWriter.Write(byte message.Length)
                else 
                    scriptWriter.Write(0x4dy)
                    scriptWriter.Write(uint16 message.Length)
                scriptWriter.Write(message)
            elif token.StartsWith("0x")
            then
                let hex = Hex.Decode token.[2..]
                scriptWriter.Write(hex)
            else
                let (s, n) = bigint.TryParse token
                assert s
                if n >= 0I && n <= 16I
                then 
                    let code = byte opCodes.[token]
                    scriptWriter.Write(code)
                else
                    let bytes = intToBytes n
                    scriptWriter.Write(byte bytes.Length)
                    scriptWriter.Write(bytes)
            parseOne rest

    parseOne tokens
    scriptBytes.ToArray()

[<TestFixture>]
type ``Given a ScriptRuntime`` ()=
    let validJson = JsonValue.Load(__SOURCE_DIRECTORY__ + "/data/script_valid.json")
    let invalidJson = JsonValue.Load(__SOURCE_DIRECTORY__ + "/data/script_invalid.json")

    let evalScript (sigScript: string) (pubScript: string) = 
        let interpreter = new ScriptRuntime(fun a _ -> a)
        interpreter.Verify(parseScript sigScript, parseScript pubScript)

    [<Test>] 
    member x.``when evaluating scripts from a valid jsonfile, I should not fail.`` () =
        validJson.AsArray() |> Array.iteri(fun i s ->
            if i = 278 then ignore()
            match s with 
            | JsonValue.Array arr ->
                let inScript = arr.[0].AsString()
                let outScript = arr.[1].AsString()
                evalScript inScript outScript |> should equal true
            )

    [<Test>] 
    member x.``when evaluating scripts from a invalid jsonfile, I should fail.`` () =
        for s in invalidJson.AsArray() do
            match s with 
            | JsonValue.Array arr ->
                let inScript = arr.[0].AsString()
                let outScript = arr.[1].AsString()
                evalScript inScript outScript |> should equal false

Signature hash tests

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
[<TestFixture>]
type ``Given a Tx Hashing function`` ()=
    let validJson = JsonValue.Load(__SOURCE_DIRECTORY__ + "/data/sighash.json")

    [<Test>] 
    member x.``when evaluating hashes from a valid json file, I should not fail.`` () =
        for s in validJson.AsArray() do
            match s with
            | JsonValue.Array [| txJ; scriptJ; indexJ; hashTypeJ; resultJ |] ->
            let txHex = Hex.Decode(txJ.AsString())
            let script = Hex.Decode(scriptJ.AsString())
            let index = indexJ.AsInteger()
            let hashType = hashTypeJ.AsInteger()
            let result = resultJ.AsString()
            let tx = ParseByteArray txHex Tx.Parse
            let scriptNoCodeSep = script |> Array.filter(fun b -> b <> 0xabuy)
            let hash = computeTxHash tx index scriptNoCodeSep hashType |> Array.rev
            let hashHex = Hex.ToHexString hash
            hashHex |> should equal result
            | _ -> ignore()

Transaction parsing tests

 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: 
[<TestFixture>]
type ``Given a Tx`` ()=
    let validJson = JsonValue.Load(__SOURCE_DIRECTORY__ + "/data/tx_valid.json")
    let invalidJson = JsonValue.Load(__SOURCE_DIRECTORY__ + "/data/tx_invalid.json")

    [<Test>] 
    member x.``when verifying transactions from a valid json file, I should not fail.`` () =
        for s in validJson.AsArray() do
            match s with
            | JsonValue.Array [| prevInputsJ; txHexJ; flagsJ |] ->
                let txHex = Hex.Decode(txHexJ.AsString())
                let tx = ParseByteArray txHex Tx.Parse
                let prevOutputsMap = new Dictionary<OutPoint, byte[]>(new Mempool.OutpointCompare())
                prevInputsJ.AsArray() |> Array.map(fun p ->
                    match p with
                    | JsonValue.Array [| JsonValue.String prevHashJ; JsonValue.Number index; JsonValue.String script |] ->
                        (new OutPoint(hashFromHex prevHashJ, int index), parseScript script)
                    | _ -> raise (new ArgumentException())
                ) |> Seq.iter(fun (k, v) -> prevOutputsMap.Add(k, v))
                let verified = 
                    tx.TxIns |> Array.mapi(fun i txIn ->
                        let outpoint = txIn.PrevOutPoint
                        let script = prevOutputsMap.[outpoint]
                        let scriptInterpreter = new ScriptRuntime(computeTxHash tx i)
                        scriptInterpreter.Verify(txIn.Script, script)
                    ) |> Seq.forall id
                (flagsJ.AsString() = "NONE" || verified) |> should equal true
            | _ -> ignore()

    [<Test>] 
    member x.``when verifying transactions from an invalid json file, I should not fail.`` () =
        for s in invalidJson.AsArray() do
            match s with
            | JsonValue.Array [| prevInputsJ; txHexJ; flagsJ |] ->
                let txHex = Hex.Decode(txHexJ.AsString())
                let tx = ParseByteArray txHex Tx.Parse
                let prevOutputsMap = new Dictionary<OutPoint, byte[]>(new Mempool.OutpointCompare())
                prevInputsJ.AsArray() |> Array.map(fun p ->
                    match p with
                    | JsonValue.Array [| JsonValue.String prevHashJ; JsonValue.Number index; JsonValue.String script |] ->
                        (new OutPoint(hashFromHex prevHashJ, int index), parseScript script)
                    | _ -> raise (new ArgumentException())
                ) |> Seq.iter(fun (k, v) -> prevOutputsMap.Add(k, v))
                let verified = 
                    tx.TxIns |> Array.mapi(fun i txIn ->
                        let outpoint = txIn.PrevOutPoint
                        let script = prevOutputsMap.[outpoint]
                        let scriptInterpreter = new ScriptRuntime(computeTxHash tx i)
                        scriptInterpreter.Verify(txIn.Script, script)
                    ) |> Seq.forall id
                let ok = (flagsJ.AsString() = "NONE" || verified)
                if ok then
                    printfn "%A" txHexJ
            | _ -> ignore()

Canonical signature tests

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
[<TestFixture>]
type ``Given a Signature file`` ()=
    let validJson = JsonValue.Load(__SOURCE_DIRECTORY__ + "/data/sig_canonical.json")

    [<Test>] 
    member x.``when verifying signatures from a valid json file, I should not fail.`` () =
        for s in validJson.AsArray() do
            let signature = Hex.Decode (s.AsString())
            let r = checkCanonicalSignature signature
            printfn "%A %A" s r

        
        
namespace Test
module Script

from Test
namespace System
namespace System.Collections
namespace System.Collections.Generic
namespace System.IO
namespace System.Text
Multiple items
namespace System.Data

--------------------
namespace Microsoft.FSharp.Data
val opCodes : Map<string,int>

Full name: Test.Script.opCodes
Multiple items
module Map

from Microsoft.FSharp.Collections

--------------------
type Map<'Key,'Value (requires comparison)> =
  interface IEnumerable
  interface IComparable
  interface IEnumerable<KeyValuePair<'Key,'Value>>
  interface ICollection<KeyValuePair<'Key,'Value>>
  interface IDictionary<'Key,'Value>
  new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
  member Add : key:'Key * value:'Value -> Map<'Key,'Value>
  member ContainsKey : key:'Key -> bool
  override Equals : obj -> bool
  member Remove : key:'Key -> Map<'Key,'Value>
  ...

Full name: Microsoft.FSharp.Collections.Map<_,_>

--------------------
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
val ofSeq : elements:seq<'Key * 'T> -> Map<'Key,'T> (requires comparison)

Full name: Microsoft.FSharp.Collections.Map.ofSeq
val parseScript : scriptString:string -> byte []

Full name: Test.Script.parseScript
val scriptString : string
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
val tokens : string list
String.Split(params separator: char []) : string []
String.Split(separator: string [], options: StringSplitOptions) : string []
String.Split(separator: char [], options: StringSplitOptions) : string []
String.Split(separator: char [], count: int) : string []
String.Split(separator: string [], count: int, options: StringSplitOptions) : string []
String.Split(separator: char [], count: int, options: StringSplitOptions) : string []
type StringSplitOptions =
  | None = 0
  | RemoveEmptyEntries = 1

Full name: System.StringSplitOptions
field StringSplitOptions.RemoveEmptyEntries = 1
type Array =
  member Clone : unit -> obj
  member CopyTo : array:Array * index:int -> unit + 1 overload
  member GetEnumerator : unit -> IEnumerator
  member GetLength : dimension:int -> int
  member GetLongLength : dimension:int -> int64
  member GetLowerBound : dimension:int -> int
  member GetUpperBound : dimension:int -> int
  member GetValue : params indices:int[] -> obj + 7 overloads
  member Initialize : unit -> unit
  member IsFixedSize : bool
  ...

Full name: System.Array
val toList : array:'T [] -> 'T list

Full name: Microsoft.FSharp.Collections.Array.toList
val scriptBytes : MemoryStream
Multiple items
type MemoryStream =
  inherit Stream
  new : unit -> MemoryStream + 6 overloads
  member CanRead : bool
  member CanSeek : bool
  member CanWrite : bool
  member Capacity : int with get, set
  member Flush : unit -> unit
  member GetBuffer : unit -> byte[]
  member Length : int64
  member Position : int64 with get, set
  member Read : buffer:byte[] * offset:int * count:int -> int
  ...

Full name: System.IO.MemoryStream

--------------------
MemoryStream() : unit
MemoryStream(capacity: int) : unit
MemoryStream(buffer: byte []) : unit
MemoryStream(buffer: byte [], writable: bool) : unit
MemoryStream(buffer: byte [], index: int, count: int) : unit
MemoryStream(buffer: byte [], index: int, count: int, writable: bool) : unit
MemoryStream(buffer: byte [], index: int, count: int, writable: bool, publiclyVisible: bool) : unit
val scriptWriter : BinaryWriter
Multiple items
type BinaryWriter =
  new : output:Stream -> BinaryWriter + 1 overload
  member BaseStream : Stream
  member Close : unit -> unit
  member Dispose : unit -> unit
  member Flush : unit -> unit
  member Seek : offset:int * origin:SeekOrigin -> int64
  member Write : value:bool -> unit + 17 overloads
  static val Null : BinaryWriter

Full name: System.IO.BinaryWriter

--------------------
BinaryWriter(output: Stream) : unit
BinaryWriter(output: Stream, encoding: Encoding) : unit
val intToBytes : (bigint -> byte [])
val i : bigint
type bigint = Numerics.BigInteger

Full name: Microsoft.FSharp.Core.bigint
val pos : bigint
val abs : value:'T -> 'T (requires member Abs)

Full name: Microsoft.FSharp.Core.Operators.abs
val bi : byte []
Numerics.BigInteger.ToByteArray() : byte []
val posTrimIdx : int
val iTrimIdx : int
val bytes : byte []
val parseOne : (string list -> unit)
type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
val token : string
val rest : string list
val c : char
val code : int option
val tryFind : key:'Key -> table:Map<'Key,'T> -> 'T option (requires comparison)

Full name: Microsoft.FSharp.Collections.Map.tryFind
String.StartsWith(value: string) : bool
String.StartsWith(value: string, comparisonType: StringComparison) : bool
String.StartsWith(value: string, ignoreCase: bool, culture: Globalization.CultureInfo) : bool
property Option.IsSome: bool
BinaryWriter.Write(value: string) : unit
   (+0 other overloads)
BinaryWriter.Write(value: float32) : unit
   (+0 other overloads)
BinaryWriter.Write(value: uint64) : unit
   (+0 other overloads)
BinaryWriter.Write(value: int64) : unit
   (+0 other overloads)
BinaryWriter.Write(value: uint32) : unit
   (+0 other overloads)
BinaryWriter.Write(value: int) : unit
   (+0 other overloads)
BinaryWriter.Write(value: uint16) : unit
   (+0 other overloads)
BinaryWriter.Write(value: int16) : unit
   (+0 other overloads)
BinaryWriter.Write(value: decimal) : unit
   (+0 other overloads)
BinaryWriter.Write(value: float) : unit
   (+0 other overloads)
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
property Option.Value: int
val message : byte []
Multiple items
type ASCIIEncoding =
  inherit Encoding
  new : unit -> ASCIIEncoding
  member GetByteCount : chars:string -> int + 2 overloads
  member GetBytes : chars:char * charCount:int * bytes:byte * byteCount:int -> int + 2 overloads
  member GetCharCount : bytes:byte * count:int -> int + 1 overload
  member GetChars : bytes:byte * byteCount:int * chars:char * charCount:int -> int + 1 overload
  member GetDecoder : unit -> Decoder
  member GetEncoder : unit -> Encoder
  member GetMaxByteCount : charCount:int -> int
  member GetMaxCharCount : byteCount:int -> int
  member GetString : bytes:byte[] * byteIndex:int * byteCount:int -> string
  ...

Full name: System.Text.ASCIIEncoding

--------------------
ASCIIEncoding() : unit
property Encoding.ASCII: Encoding
Encoding.GetBytes(s: string) : byte []
Encoding.GetBytes(chars: char []) : byte []
Encoding.GetBytes(chars: char [], index: int, count: int) : byte []
Encoding.GetBytes(chars: nativeptr<char>, charCount: int, bytes: nativeptr<byte>, byteCount: int) : int
Encoding.GetBytes(s: string, charIndex: int, charCount: int, bytes: byte [], byteIndex: int) : int
Encoding.GetBytes(chars: char [], charIndex: int, charCount: int, bytes: byte [], byteIndex: int) : int
property String.Length: int
val len : int
property Array.Length: int
Multiple items
val uint16 : value:'T -> uint16 (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.uint16

--------------------
type uint16 = UInt16

Full name: Microsoft.FSharp.Core.uint16
val hex : obj
val s : bool
val n : Numerics.BigInteger
Numerics.BigInteger.TryParse(value: string, result: byref<Numerics.BigInteger>) : bool
Numerics.BigInteger.TryParse(value: string, style: Globalization.NumberStyles, provider: IFormatProvider, result: byref<Numerics.BigInteger>) : bool
val code : byte
MemoryStream.ToArray() : byte []
val validJson : obj
val invalidJson : obj
val evalScript : (string -> string -> 'a)
val sigScript : string
val pubScript : string
val interpreter : obj
val x : Given a ScriptRuntime
member Given a ScriptRuntime.( when evaluating scripts from a valid jsonfile, I should not fail. ) : unit -> unit

Full name: Test.Script.Given a ScriptRuntime.( when evaluating scripts from a valid jsonfile, I should not fail. )
val iteri : action:(int -> 'T -> unit) -> array:'T [] -> unit

Full name: Microsoft.FSharp.Collections.Array.iteri
val i : int
val s : obj
member Given a ScriptRuntime.( when evaluating scripts from a invalid jsonfile, I should fail. ) : unit -> unit

Full name: Test.Script.Given a ScriptRuntime.( when evaluating scripts from a invalid jsonfile, I should fail. )
val x : Given a Tx Hashing function
member Given a Tx Hashing function.( when evaluating hashes from a valid json file, I should not fail. ) : unit -> unit

Full name: Test.Script.Given a Tx Hashing function.( when evaluating hashes from a valid json file, I should not fail. )
val filter : predicate:('T -> bool) -> array:'T [] -> 'T []

Full name: Microsoft.FSharp.Collections.Array.filter
val hash : obj:'T -> int (requires equality)

Full name: Microsoft.FSharp.Core.Operators.hash
val rev : array:'T [] -> 'T []

Full name: Microsoft.FSharp.Collections.Array.rev
val x : Given a Tx
member Given a Tx.( when verifying transactions from a valid json file, I should not fail. ) : unit -> unit

Full name: Test.Script.Given a Tx.( when verifying transactions from a valid json file, I should not fail. )
Multiple items
type Dictionary<'TKey,'TValue> =
  new : unit -> Dictionary<'TKey, 'TValue> + 5 overloads
  member Add : key:'TKey * value:'TValue -> unit
  member Clear : unit -> unit
  member Comparer : IEqualityComparer<'TKey>
  member ContainsKey : key:'TKey -> bool
  member ContainsValue : value:'TValue -> bool
  member Count : int
  member GetEnumerator : unit -> Enumerator<'TKey, 'TValue>
  member GetObjectData : info:SerializationInfo * context:StreamingContext -> unit
  member Item : 'TKey -> 'TValue with get, set
  ...
  nested type Enumerator
  nested type KeyCollection
  nested type ValueCollection

Full name: System.Collections.Generic.Dictionary<_,_>

--------------------
Dictionary() : unit
Dictionary(capacity: int) : unit
Dictionary(comparer: IEqualityComparer<'TKey>) : unit
Dictionary(dictionary: IDictionary<'TKey,'TValue>) : unit
Dictionary(capacity: int, comparer: IEqualityComparer<'TKey>) : unit
Dictionary(dictionary: IDictionary<'TKey,'TValue>, comparer: IEqualityComparer<'TKey>) : unit
val map : mapping:('T -> 'U) -> array:'T [] -> 'U []

Full name: Microsoft.FSharp.Collections.Array.map
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: Encoding) : unit
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 raise : exn:Exception -> 'T

Full name: Microsoft.FSharp.Core.Operators.raise
Multiple items
type ArgumentException =
  inherit SystemException
  new : unit -> ArgumentException + 4 overloads
  member GetObjectData : info:SerializationInfo * context:StreamingContext -> unit
  member Message : string
  member ParamName : string

Full name: System.ArgumentException

--------------------
ArgumentException() : unit
ArgumentException(message: string) : unit
ArgumentException(message: string, innerException: exn) : unit
ArgumentException(message: string, paramName: string) : unit
ArgumentException(message: string, paramName: string, innerException: exn) : unit
module Seq

from Microsoft.FSharp.Collections
val iter : action:('T -> unit) -> source:seq<'T> -> unit

Full name: Microsoft.FSharp.Collections.Seq.iter
val mapi : mapping:(int -> 'T -> 'U) -> array:'T [] -> 'U []

Full name: Microsoft.FSharp.Collections.Array.mapi
val forall : predicate:('T -> bool) -> source:seq<'T> -> bool

Full name: Microsoft.FSharp.Collections.Seq.forall
val id : x:'T -> 'T

Full name: Microsoft.FSharp.Core.Operators.id
member Given a Tx.( when verifying transactions from an invalid json file, I should not fail. ) : unit -> unit

Full name: Test.Script.Given a Tx.( when verifying transactions from an invalid json file, I should not fail. )
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val x : Given a Signature file
member Given a Signature file.( when verifying signatures from a valid json file, I should not fail. ) : unit -> unit

Full name: Test.Script.Given a Signature file.( when verifying signatures from a valid json file, I should not fail. )
val signature : obj
val r : obj