@@ -10,103 +10,110 @@ package main
10
10
import (
11
11
"bytes"
12
12
"encoding/hex"
13
+ "encoding/json"
13
14
"fmt"
15
+ "io"
14
16
"io/ioutil"
15
17
"os"
16
18
"path"
17
19
18
- "github.com/roasbeef/btcd/chaincfg"
19
20
"github.com/roasbeef/btcd/chaincfg/chainhash"
20
21
"github.com/roasbeef/btcd/rpcclient"
21
22
"github.com/roasbeef/btcd/wire"
22
23
"github.com/roasbeef/btcutil/gcs"
23
24
"github.com/roasbeef/btcutil/gcs/builder"
24
25
)
25
26
27
+ var (
28
+ // testBlockHeights are the heights of the blocks to include in the test
29
+ // vectors. Any new entries must be added in sorted order.
30
+ testBlockHeights = []testBlockCase {
31
+ {0 , "Genesis block" },
32
+ {1 , "Extended filter is empty" },
33
+ {2 , "" },
34
+ {3 , "" },
35
+ {926485 , "Duplicate pushdata 913bcc2be49cb534c20474c4dee1e9c4c317e7eb" },
36
+ {987876 , "Coinbase tx has unparseable output script" },
37
+ {1263442 , "Includes witness data" },
38
+ }
39
+ )
40
+
41
+ type testBlockCase struct {
42
+ height uint32
43
+ comment string
44
+ }
45
+
46
+ type JSONTestWriter struct {
47
+ writer io.Writer
48
+ firstRowWritten bool
49
+ }
50
+
51
+ func NewJSONTestWriter (writer io.Writer ) * JSONTestWriter {
52
+ return & JSONTestWriter {writer : writer }
53
+ }
54
+
55
+ func (w * JSONTestWriter ) WriteComment (comment string ) error {
56
+ return w .WriteTestCase ([]interface {}{comment })
57
+ }
58
+
59
+ func (w * JSONTestWriter ) WriteTestCase (row []interface {}) error {
60
+ var err error
61
+ if w .firstRowWritten {
62
+ _ , err = io .WriteString (w .writer , ",\n " )
63
+ } else {
64
+ _ , err = io .WriteString (w .writer , "[\n " )
65
+ w .firstRowWritten = true
66
+ }
67
+ if err != nil {
68
+ return err
69
+ }
70
+
71
+ rowBytes , err := json .Marshal (row )
72
+ if err != nil {
73
+ return err
74
+ }
75
+
76
+ _ , err = w .writer .Write (rowBytes )
77
+ return err
78
+ }
79
+
80
+ func (w * JSONTestWriter ) Close () error {
81
+ if ! w .firstRowWritten {
82
+ return nil
83
+ }
84
+
85
+ _ , err := io .WriteString (w .writer , "\n ]\n " )
86
+ return err
87
+ }
88
+
26
89
func main () {
27
90
err := os .Mkdir ("gcstestvectors" , os .ModeDir | 0755 )
28
91
if err != nil { // Don't overwrite existing output if any
29
92
fmt .Println ("Couldn't create directory: " , err )
30
93
return
31
94
}
32
- files := make ([]* os. File , 33 )
95
+ files := make ([]* JSONTestWriter , 33 )
33
96
prevBasicHeaders := make ([]chainhash.Hash , 33 )
34
97
prevExtHeaders := make ([]chainhash.Hash , 33 )
35
98
for i := 1 ; i <= 32 ; i ++ { // Min 1 bit of collision space, max 32
36
- var blockBuf bytes.Buffer
37
- fName := fmt .Sprintf ("gcstestvectors/testnet-%02d.csv" , i )
99
+ fName := fmt .Sprintf ("gcstestvectors/testnet-%02d.json" , i )
38
100
file , err := os .Create (fName )
39
101
if err != nil {
40
- fmt .Println ("Error creating CSV file: " , err .Error ())
41
- return
42
- }
43
- _ , err = file .WriteString ("Block Height,Block Hash,Block,Previous Basic Header,Previous Ext Header,Basic Filter,Ext Filter,Basic Header,Ext Header\n " )
44
- if err != nil {
45
- fmt .Println ("Error writing to CSV file: " , err .Error ())
46
- return
47
- }
48
- files [i ] = file
49
- basicFilter , err := buildBasicFilter (
50
- chaincfg .TestNet3Params .GenesisBlock , uint8 (i ))
51
- if err != nil {
52
- fmt .Println ("Error generating basic filter: " , err .Error ())
53
- return
54
- }
55
- prevBasicHeaders [i ], err = builder .MakeHeaderForFilter (basicFilter ,
56
- chaincfg .TestNet3Params .GenesisBlock .Header .PrevBlock )
57
- if err != nil {
58
- fmt .Println ("Error generating header for filter: " , err .Error ())
59
- return
60
- }
61
- if basicFilter == nil {
62
- basicFilter = & gcs.Filter {}
63
- }
64
- extFilter , err := buildExtFilter (
65
- chaincfg .TestNet3Params .GenesisBlock , uint8 (i ))
66
- if err != nil {
67
- fmt .Println ("Error generating ext filter: " , err .Error ())
68
- return
69
- }
70
- prevExtHeaders [i ], err = builder .MakeHeaderForFilter (extFilter ,
71
- chaincfg .TestNet3Params .GenesisBlock .Header .PrevBlock )
72
- if err != nil {
73
- fmt .Println ("Error generating header for filter: " , err .Error ())
102
+ fmt .Println ("Error creating output file: " , err .Error ())
74
103
return
75
104
}
76
- if extFilter == nil {
77
- extFilter = & gcs.Filter {}
78
- }
79
- err = chaincfg .TestNet3Params .GenesisBlock .Serialize (& blockBuf )
80
- if err != nil {
81
- fmt .Println ("Error serializing block to buffer: " , err .Error ())
82
- return
83
- }
84
- bfBytes , err := basicFilter .NBytes ()
85
- if err != nil {
86
- fmt .Println ("Couldn't get NBytes(): " , err )
87
- return
88
- }
89
- efBytes , err := extFilter .NBytes ()
90
- if err != nil {
91
- fmt .Println ("Couldn't get NBytes(): " , err )
92
- return
93
- }
94
- err = writeCSVRow (
95
- file ,
96
- 0 , // Height
97
- * chaincfg .TestNet3Params .GenesisHash ,
98
- blockBuf .Bytes (),
99
- chaincfg .TestNet3Params .GenesisBlock .Header .PrevBlock ,
100
- chaincfg .TestNet3Params .GenesisBlock .Header .PrevBlock ,
101
- bfBytes ,
102
- efBytes ,
103
- prevBasicHeaders [i ],
104
- prevExtHeaders [i ],
105
- )
105
+ defer file .Close ()
106
+
107
+ writer := & JSONTestWriter {writer : file }
108
+ defer writer .Close ()
109
+
110
+ err = writer .WriteComment ("Block Height,Block Hash,Block,Previous Basic Header,Previous Ext Header,Basic Filter,Ext Filter,Basic Header,Ext Header,Notes" )
106
111
if err != nil {
107
- fmt .Println ("Error writing to CSV file: " , err .Error ())
112
+ fmt .Println ("Error writing to output file: " , err .Error ())
108
113
return
109
114
}
115
+
116
+ files [i ] = writer
110
117
}
111
118
cert , err := ioutil .ReadFile (
112
119
path .Join (os .Getenv ("HOME" ), "/.btcd/rpc.cert" ))
@@ -126,7 +133,9 @@ func main() {
126
133
fmt .Println ("Couldn't create a new client: " , err .Error ())
127
134
return
128
135
}
129
- for height := 1 ; height < 988000 ; height ++ {
136
+
137
+ var testBlockIndex int = 0
138
+ for height := 0 ; testBlockIndex < len (testBlockHeights ); height ++ {
130
139
fmt .Printf ("Height: %d\n " , height )
131
140
blockHash , err := client .GetBlockHash (int64 (height ))
132
141
if err != nil {
@@ -224,62 +233,46 @@ func main() {
224
233
}
225
234
fmt .Println ("Verified against server" )
226
235
}
227
- switch height {
228
- case 1 , 2 , 3 , 926485 , 987876 : // Blocks for test cases
236
+
237
+ if uint32 ( height ) == testBlockHeights [ testBlockIndex ]. height {
229
238
var bfBytes []byte
230
239
var efBytes []byte
231
- if basicFilter .N () > 0 {
232
- bfBytes , err = basicFilter .NBytes ()
233
- if err != nil {
234
- fmt .Println ("Couldn't get NBytes(): " , err )
235
- return
236
- }
240
+ bfBytes , err = basicFilter .NBytes ()
241
+ if err != nil {
242
+ fmt .Println ("Couldn't get NBytes(): " , err )
243
+ return
237
244
}
238
- if extFilter .N () > 0 { // Exclude special case for block 987876
239
- efBytes , err = extFilter .NBytes ()
240
- if err != nil {
241
- fmt .Println ("Couldn't get NBytes(): " , err )
242
- return
243
- }
245
+ efBytes , err = extFilter .NBytes ()
246
+ if err != nil {
247
+ fmt .Println ("Couldn't get NBytes(): " , err )
248
+ return
244
249
}
245
- writeCSVRow (
246
- files [i ],
250
+ row := []interface {}{
247
251
height ,
248
- * blockHash ,
249
- blockBytes ,
250
- prevBasicHeaders [i ],
251
- prevExtHeaders [i ],
252
- bfBytes ,
253
- efBytes ,
254
- basicHeader ,
255
- extHeader )
252
+ blockHash .String (),
253
+ hex .EncodeToString (blockBytes ),
254
+ prevBasicHeaders [i ].String (),
255
+ prevExtHeaders [i ].String (),
256
+ hex .EncodeToString (bfBytes ),
257
+ hex .EncodeToString (efBytes ),
258
+ basicHeader .String (),
259
+ extHeader .String (),
260
+ testBlockHeights [testBlockIndex ].comment ,
261
+ }
262
+ err = files [i ].WriteTestCase (row )
263
+ if err != nil {
264
+ fmt .Println ("Error writing test case to output: " , err .Error ())
265
+ return
266
+ }
256
267
}
257
268
prevBasicHeaders [i ] = basicHeader
258
269
prevExtHeaders [i ] = extHeader
259
270
}
260
- }
261
- }
262
271
263
- // writeCSVRow writes a test vector to a CSV file.
264
- func writeCSVRow (file * os.File , height int , blockHash chainhash.Hash ,
265
- blockBytes []byte , prevBasicHeader , prevExtHeader chainhash.Hash ,
266
- basicFilter , extFilter []byte , basicHeader , extHeader chainhash.Hash ) error {
267
- row := fmt .Sprintf ("%d,%s,%s,%s,%s,%s,%s,%s,%s\n " ,
268
- height ,
269
- blockHash .String (),
270
- hex .EncodeToString (blockBytes ),
271
- prevBasicHeader .String (),
272
- prevExtHeader .String (),
273
- hex .EncodeToString (basicFilter ),
274
- hex .EncodeToString (extFilter ),
275
- basicHeader .String (),
276
- extHeader .String (),
277
- )
278
- _ , err := file .WriteString (row )
279
- if err != nil {
280
- return err
272
+ if uint32 (height ) == testBlockHeights [testBlockIndex ].height {
273
+ testBlockIndex ++
274
+ }
281
275
}
282
- return nil
283
276
}
284
277
285
278
// buildBasicFilter builds a basic GCS filter from a block. A basic GCS filter
0 commit comments