summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bip-0158/gentestvectors.go380
-rw-r--r--bip-0158/testnet-19.json (renamed from bip-0158/testnet-20.json)15
2 files changed, 165 insertions, 230 deletions
diff --git a/bip-0158/gentestvectors.go b/bip-0158/gentestvectors.go
index deaf2c7..472f8c1 100644
--- a/bip-0158/gentestvectors.go
+++ b/bip-0158/gentestvectors.go
@@ -15,13 +15,15 @@ import (
"io"
"io/ioutil"
"os"
- "path"
+ "path/filepath"
- "github.com/roasbeef/btcd/chaincfg/chainhash"
- "github.com/roasbeef/btcd/rpcclient"
- "github.com/roasbeef/btcd/wire"
- "github.com/roasbeef/btcutil/gcs"
- "github.com/roasbeef/btcutil/gcs/builder"
+ "github.com/btcsuite/btcd/blockchain"
+ "github.com/btcsuite/btcd/chaincfg/chainhash"
+ "github.com/btcsuite/btcd/rpcclient"
+ "github.com/btcsuite/btcd/wire"
+ "github.com/btcsuite/btcutil"
+ "github.com/btcsuite/btcutil/gcs/builder"
+ "github.com/davecgh/go-spew/spew"
)
var (
@@ -29,13 +31,19 @@ var (
// vectors. Any new entries must be added in sorted order.
testBlockHeights = []testBlockCase{
{0, "Genesis block"},
- {1, "Extended filter is empty"},
{2, ""},
{3, ""},
{926485, "Duplicate pushdata 913bcc2be49cb534c20474c4dee1e9c4c317e7eb"},
{987876, "Coinbase tx has unparseable output script"},
{1263442, "Includes witness data"},
}
+
+ defaultBtcdDir = btcutil.AppDataDir("btcd", false)
+ defaultBtcdRPCCertFile = filepath.Join(defaultBtcdDir, "rpc.cert")
+)
+
+const (
+ fp = 19
)
type testBlockCase struct {
@@ -86,41 +94,78 @@ func (w *JSONTestWriter) Close() error {
return err
}
-func main() {
- err := os.Mkdir("gcstestvectors", os.ModeDir|0755)
- if err != nil { // Don't overwrite existing output if any
- fmt.Println("Couldn't create directory: ", err)
- return
- }
- files := make([]*JSONTestWriter, 33)
- prevBasicHeaders := make([]chainhash.Hash, 33)
- prevExtHeaders := make([]chainhash.Hash, 33)
- for i := 1; i <= 32; i++ { // Min 1 bit of collision space, max 32
- fName := fmt.Sprintf("gcstestvectors/testnet-%02d.json", i)
- file, err := os.Create(fName)
- if err != nil {
- fmt.Println("Error creating output file: ", err.Error())
- return
+func fetchPrevOutputScripts(client *rpcclient.Client, block *wire.MsgBlock) ([][]byte, error) {
+ var prevScripts [][]byte
+
+ txCache := make(map[chainhash.Hash]*wire.MsgTx)
+ for _, tx := range block.Transactions {
+ if blockchain.IsCoinBaseTx(tx) {
+ continue
}
- defer file.Close()
- writer := &JSONTestWriter{writer: file}
- defer writer.Close()
+ for _, txIn := range tx.TxIn {
+ prevOp := txIn.PreviousOutPoint
- err = writer.WriteComment("Block Height,Block Hash,Block,Previous Basic Header,Previous Ext Header,Basic Filter,Ext Filter,Basic Header,Ext Header,Notes")
- if err != nil {
- fmt.Println("Error writing to output file: ", err.Error())
- return
+ tx, ok := txCache[prevOp.Hash]
+ if !ok {
+ originTx, err := client.GetRawTransaction(
+ &prevOp.Hash,
+ )
+ if err != nil {
+ return nil, fmt.Errorf("unable to get "+
+ "txid=%v: %v", prevOp.Hash, err)
+ }
+
+ txCache[prevOp.Hash] = originTx.MsgTx()
+
+ tx = originTx.MsgTx()
+ }
+
+ index := prevOp.Index
+
+ prevScripts = append(
+ prevScripts, tx.TxOut[index].PkScript,
+ )
}
+ }
- files[i] = writer
+ return prevScripts, nil
+}
+
+func main() {
+ var (
+ writerFile *JSONTestWriter
+ prevBasicHeader chainhash.Hash
+ )
+ fName := fmt.Sprintf("testnet-%02d.json", fp)
+ file, err := os.Create(fName)
+ if err != nil {
+ fmt.Println("Error creating output file: ", err.Error())
+ return
+ }
+ defer file.Close()
+
+ writer := &JSONTestWriter{
+ writer: file,
+ }
+ defer writer.Close()
+
+ err = writer.WriteComment("Block Height,Block Hash,Block," +
+ "[Prev Output Scripts for Block],Previous Basic Header," +
+ "Basic Filter,Basic Header,Notes")
+ if err != nil {
+ fmt.Println("Error writing to output file: ", err.Error())
+ return
}
- cert, err := ioutil.ReadFile(
- path.Join(os.Getenv("HOME"), "/.btcd/rpc.cert"))
+
+ writerFile = writer
+
+ cert, err := ioutil.ReadFile(defaultBtcdRPCCertFile)
if err != nil {
fmt.Println("Couldn't read RPC cert: ", err.Error())
return
}
+
conf := rpcclient.ConnConfig{
Host: "127.0.0.1:18334",
Endpoint: "ws",
@@ -134,19 +179,20 @@ func main() {
return
}
- var testBlockIndex int = 0
+ var testBlockIndex int
for height := 0; testBlockIndex < len(testBlockHeights); height++ {
- fmt.Printf("Height: %d\n", height)
blockHash, err := client.GetBlockHash(int64(height))
if err != nil {
fmt.Println("Couldn't get block hash: ", err.Error())
return
}
+
block, err := client.GetBlock(blockHash)
if err != nil {
fmt.Println("Couldn't get block hash: ", err.Error())
return
}
+
var blockBuf bytes.Buffer
err = block.Serialize(&blockBuf)
if err != nil {
@@ -154,208 +200,98 @@ func main() {
return
}
blockBytes := blockBuf.Bytes()
- for i := 1; i <= 32; i++ {
- basicFilter, err := buildBasicFilter(block, uint8(i))
- if err != nil {
- fmt.Println("Error generating basic filter: ", err.Error())
- return
- }
- basicHeader, err := builder.MakeHeaderForFilter(basicFilter,
- prevBasicHeaders[i])
- if err != nil {
- fmt.Println("Error generating header for filter: ", err.Error())
- return
- }
- if basicFilter == nil {
- basicFilter = &gcs.Filter{}
- }
- extFilter, err := buildExtFilter(block, uint8(i))
- if err != nil {
- fmt.Println("Error generating ext filter: ", err.Error())
- return
- }
- extHeader, err := builder.MakeHeaderForFilter(extFilter,
- prevExtHeaders[i])
- if err != nil {
- fmt.Println("Error generating header for filter: ", err.Error())
- return
- }
- if extFilter == nil {
- extFilter = &gcs.Filter{}
- }
- if i == builder.DefaultP { // This is the default filter size so we can check against the server's info
- filter, err := client.GetCFilter(blockHash, wire.GCSFilterRegular)
- if err != nil {
- fmt.Println("Error getting basic filter: ", err.Error())
- return
- }
- nBytes, err := basicFilter.NBytes()
- if err != nil {
- fmt.Println("Couldn't get NBytes(): ", err)
- return
- }
- if !bytes.Equal(filter.Data, nBytes) {
- // Don't error on empty filters
- fmt.Println("Basic filter doesn't match!\n", filter.Data, "\n", nBytes)
- return
- }
- filter, err = client.GetCFilter(blockHash, wire.GCSFilterExtended)
- if err != nil {
- fmt.Println("Error getting extended filter: ", err.Error())
- return
- }
- nBytes, err = extFilter.NBytes()
- if err != nil {
- fmt.Println("Couldn't get NBytes(): ", err)
- return
- }
- if !bytes.Equal(filter.Data, nBytes) {
- fmt.Println("Extended filter doesn't match!")
- return
- }
- header, err := client.GetCFilterHeader(blockHash, wire.GCSFilterRegular)
- if err != nil {
- fmt.Println("Error getting basic header: ", err.Error())
- return
- }
- if !bytes.Equal(header.PrevFilterHeader[:], basicHeader[:]) {
- fmt.Println("Basic header doesn't match!")
- return
- }
- header, err = client.GetCFilterHeader(blockHash, wire.GCSFilterExtended)
- if err != nil {
- fmt.Println("Error getting extended header: ", err.Error())
- return
- }
- if !bytes.Equal(header.PrevFilterHeader[:], extHeader[:]) {
- fmt.Println("Extended header doesn't match!")
- return
- }
- fmt.Println("Verified against server")
- }
- if uint32(height) == testBlockHeights[testBlockIndex].height {
- var bfBytes []byte
- var efBytes []byte
- bfBytes, err = basicFilter.NBytes()
- if err != nil {
- fmt.Println("Couldn't get NBytes(): ", err)
- return
- }
- efBytes, err = extFilter.NBytes()
- if err != nil {
- fmt.Println("Couldn't get NBytes(): ", err)
- return
- }
- row := []interface{}{
- height,
- blockHash.String(),
- hex.EncodeToString(blockBytes),
- prevBasicHeaders[i].String(),
- prevExtHeaders[i].String(),
- hex.EncodeToString(bfBytes),
- hex.EncodeToString(efBytes),
- basicHeader.String(),
- extHeader.String(),
- testBlockHeights[testBlockIndex].comment,
- }
- err = files[i].WriteTestCase(row)
- if err != nil {
- fmt.Println("Error writing test case to output: ", err.Error())
- return
- }
- }
- prevBasicHeaders[i] = basicHeader
- prevExtHeaders[i] = extHeader
+ prevOutputScripts, err := fetchPrevOutputScripts(client, block)
+ if err != nil {
+ fmt.Println("Couldn't fetch prev output scipts: ", err)
+ return
}
- if uint32(height) == testBlockHeights[testBlockIndex].height {
- testBlockIndex++
+ basicFilter, err := builder.BuildBasicFilter(block, prevOutputScripts)
+ if err != nil {
+ fmt.Println("Error generating basic filter: ", err.Error())
+ return
+ }
+ basicHeader, err := builder.MakeHeaderForFilter(basicFilter, prevBasicHeader)
+ if err != nil {
+ fmt.Println("Error generating header for filter: ", err.Error())
+ return
}
- }
-}
-// buildBasicFilter builds a basic GCS filter from a block. A basic GCS filter
-// will contain all the previous outpoints spent within a block, as well as the
-// data pushes within all the outputs created within a block. p is specified as
-// an argument in order to create test vectors with various values for p.
-func buildBasicFilter(block *wire.MsgBlock, p uint8) (*gcs.Filter, error) {
- blockHash := block.BlockHash()
- b := builder.WithKeyHashP(&blockHash, p)
-
- // If the filter had an issue with the specified key, then we force it
- // to bubble up here by calling the Key() function.
- _, err := b.Key()
- if err != nil {
- return nil, err
- }
+ // We'll now ensure that we've constructed the same filter as
+ // the chain server we're fetching blocks form.
+ filter, err := client.GetCFilter(
+ blockHash, wire.GCSFilterRegular,
+ )
+ if err != nil {
+ fmt.Println("Error getting basic filter: ",
+ err.Error())
+ return
+ }
- // In order to build a basic filter, we'll range over the entire block,
- // adding the outpoint data as well as the data pushes within the
- // pkScript.
- for i, tx := range block.Transactions {
- // First we'll compute the bash of the transaction and add that
- // directly to the filter.
- txHash := tx.TxHash()
- b.AddHash(&txHash)
-
- // Skip the inputs for the coinbase transaction
- if i != 0 {
- // Each each txin, we'll add a serialized version of
- // the txid:index to the filters data slices.
- for _, txIn := range tx.TxIn {
- b.AddOutPoint(txIn.PreviousOutPoint)
- }
+ nBytes, err := basicFilter.NBytes()
+ if err != nil {
+ fmt.Println("Couldn't get NBytes(): ", err)
+ return
+ }
+ if !bytes.Equal(filter.Data, nBytes) {
+ // Don't error on empty filters
+ fmt.Printf("basic filter doesn't match: generated "+
+ "%x, rpc returns %x, block %v", nBytes,
+ filter.Data, spew.Sdump(block))
+ return
}
- // For each output in a transaction, we'll add each of the
- // individual data pushes within the script.
- for _, txOut := range tx.TxOut {
- b.AddEntry(txOut.PkScript)
+ header, err := client.GetCFilterHeader(
+ blockHash, wire.GCSFilterRegular,
+ )
+ if err != nil {
+ fmt.Println("Error getting basic header: ", err.Error())
+ return
+ }
+ if !bytes.Equal(header.PrevFilterHeader[:], basicHeader[:]) {
+ fmt.Println("Basic header doesn't match!")
+ return
}
- }
- return b.Build()
-}
+ if height%1000 == 0 {
+ fmt.Printf("Verified height %v against server\n", height)
+ }
-// buildExtFilter builds an extended GCS filter from a block. An extended
-// filter supplements a regular basic filter by include all the _witness_ data
-// found within a block. This includes all the data pushes within any signature
-// scripts as well as each element of an input's witness stack. Additionally,
-// the _hashes_ of each transaction are also inserted into the filter. p is
-// specified as an argument in order to create test vectors with various values
-// for p.
-func buildExtFilter(block *wire.MsgBlock, p uint8) (*gcs.Filter, error) {
- blockHash := block.BlockHash()
- b := builder.WithKeyHashP(&blockHash, p)
-
- // If the filter had an issue with the specified key, then we force it
- // to bubble up here by calling the Key() function.
- _, err := b.Key()
- if err != nil {
- return nil, err
- }
+ if uint32(height) == testBlockHeights[testBlockIndex].height {
+ var bfBytes []byte
+ bfBytes, err = basicFilter.NBytes()
+ if err != nil {
+ fmt.Println("Couldn't get NBytes(): ", err)
+ return
+ }
- // In order to build an extended filter, we add the hash of each
- // transaction as well as each piece of witness data included in both
- // the sigScript and the witness stack of an input.
- for i, tx := range block.Transactions {
- // Skip the inputs for the coinbase transaction
- if i != 0 {
- // Next, for each input, we'll add the sigScript (if
- // it's present), and also the witness stack (if it's
- // present)
- for _, txIn := range tx.TxIn {
- if txIn.SignatureScript != nil {
- b.AddScript(txIn.SignatureScript)
- }
+ prevScriptStrings := make([]string, len(prevOutputScripts))
+ for i, prevScript := range prevOutputScripts {
+ prevScriptStrings[i] = hex.EncodeToString(prevScript)
+ }
- if len(txIn.Witness) != 0 {
- b.AddWitness(txIn.Witness)
- }
+ row := []interface{}{
+ height,
+ blockHash.String(),
+ hex.EncodeToString(blockBytes),
+ prevScriptStrings,
+ prevBasicHeader.String(),
+ hex.EncodeToString(bfBytes),
+ basicHeader.String(),
+ testBlockHeights[testBlockIndex].comment,
+ }
+ err = writerFile.WriteTestCase(row)
+ if err != nil {
+ fmt.Println("Error writing test case to output: ", err.Error())
+ return
}
}
- }
- return b.Build()
+ prevBasicHeader = basicHeader
+
+ if uint32(height) == testBlockHeights[testBlockIndex].height {
+ testBlockIndex++
+ }
+ }
}
diff --git a/bip-0158/testnet-20.json b/bip-0158/testnet-19.json
index a768b49..2f00728 100644
--- a/bip-0158/testnet-20.json
+++ b/bip-0158/testnet-19.json
@@ -1,10 +1,9 @@
[
-["Block Height,Block Hash,Block,Previous Basic Header,Previous Ext Header,Basic Filter,Ext Filter,Basic Header,Ext Header,Notes"],
-[0,"000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943","0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff001d1aa4ae180101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000","0000000000000000000000000000000000000000000000000000000000000000","0000000000000000000000000000000000000000000000000000000000000000","0285c7cdbe33a0","00","c0589c7f567cffaf7bc0c9f6ad61710b78d3c1afef5d65a2a08e8a753173aa54","753e0d1c28585269ab770b166ca2cd1b32f9bc918750547941ed4849d5a80ba8","Genesis block"],
-[1,"00000000b873e79784647a6c82962c70d228557d24a747ea4d1b8bbe878e1206","0100000043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea330900000000bac8b0fa927c0ac8234287e33c5f74d38d354820e24756ad709d7038fc5f31f020e7494dffff001d03e4b6720101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0420e7494d017f062f503253482fffffffff0100f2052a010000002321021aeaf2f8638a129a3156fbe7e5ef635226b0bafd495ff03afe2c843d7e3a4b51ac00000000","c0589c7f567cffaf7bc0c9f6ad61710b78d3c1afef5d65a2a08e8a753173aa54","753e0d1c28585269ab770b166ca2cd1b32f9bc918750547941ed4849d5a80ba8","026929d09bee00","00","81e4f3e934488be62758f0b88037aa558262da3190ca018329997a319a0f8b5b","31b674ab635e074717329dabdb25d3cb0e14cb2526000cc2cedac7b5f2595110","Extended filter is empty"],
-[2,"000000006c02c8ea6e4ff69651f7fcde348fb9d557a06e6957b65552002a7820","0100000006128e87be8b1b4dea47a7247d5528d2702c96826c7a648497e773b800000000e241352e3bec0a95a6217e10c3abb54adfa05abb12c126695595580fb92e222032e7494dffff001d00d235340101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0432e7494d010e062f503253482fffffffff0100f2052a010000002321038a7f6ef1c8ca0c588aa53fa860128077c9e6c11e6830f4d7ee4e763a56b7718fac00000000","81e4f3e934488be62758f0b88037aa558262da3190ca018329997a319a0f8b5b","31b674ab635e074717329dabdb25d3cb0e14cb2526000cc2cedac7b5f2595110","0278fc41168ec0","00","ec48f9f8a625bd8adb2d2684867a05baafebf935553e0b78b386da98179dcf49","0dd53b407c3f242f1838e39e2fc0cfb89cdca27de07ec230568a08d1872f9e01",""],
-[3,"000000008b896e272758da5297bcd98fdc6d97c9b765ecec401e286dc1fdbe10","0100000020782a005255b657696ea057d5b98f34defcf75196f64f6eeac8026c0000000041ba5afc532aae03151b8aa87b65e1594f97504a768e010c98c0add79216247186e7494dffff001d058dc2b60101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0486e7494d0151062f503253482fffffffff0100f2052a01000000232103f6d9ff4c12959445ca5549c811683bf9c88e637b222dd2e0311154c4c85cf423ac00000000","ec48f9f8a625bd8adb2d2684867a05baafebf935553e0b78b386da98179dcf49","0dd53b407c3f242f1838e39e2fc0cfb89cdca27de07ec230568a08d1872f9e01","022ce4b3256540","00","060b7e1be150cc3cabd9e96b00af217132b387f31fd2bd9adfb0c7f5a09a3356","5b2a59bc476d52b45de1398ee34ed10d0cccd2a4b19ba502a456c7356b35be0d",""],
-[926485,"000000000000015d6077a411a8f5cc95caf775ccf11c54e27df75ce58d187313","0000002060bbab0edbf3ef8a49608ee326f8fd75c473b7e3982095e2d100000000000000c30134f8c9b6d2470488d7a67a888f6fa12f8692e0c3411fbfb92f0f68f67eedae03ca57ef13021acc22dc4105010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2f0315230e0004ae03ca57043e3d1e1d0c8796bf579aef0c0000000000122f4e696e6a61506f6f6c2f5345475749542fffffffff038427a112000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9ed5c748e121c0fe146d973a4ac26fa4a68b0549d46ee22d25f50a5e46fe1b377ee00000000000000002952534b424c4f434b3acd16772ad61a3c5f00287480b720f6035d5e54c9efc71be94bb5e3727f10909001200000000000000000000000000000000000000000000000000000000000000000000000000100000000010145310e878941a1b2bc2d33797ee4d89d95eaaf2e13488063a2aa9a74490f510a0100000023220020b6744de4f6ec63cc92f7c220cdefeeb1b1bed2b66c8e5706d80ec247d37e65a1ffffffff01002d3101000000001976a9143ebc40e411ed3c76f86711507ab952300890397288ac0400473044022001dd489a5d4e2fbd8a3ade27177f6b49296ba7695c40dbbe650ea83f106415fd02200b23a0602d8ff1bdf79dee118205fc7e9b40672bf31563e5741feb53fb86388501483045022100f88f040e90cc5dc6c6189d04718376ac19ed996bf9e4a3c29c3718d90ffd27180220761711f16c9e3a44f71aab55cbc0634907a1fa8bb635d971a9a01d368727bea10169522103b3623117e988b76aaabe3d63f56a4fc88b228a71e64c4cc551d1204822fe85cb2103dd823066e096f72ed617a41d3ca56717db335b1ea47a1b4c5c9dbdd0963acba621033d7c89bd9da29fa8d44db7906a9778b53121f72191184a9fee785c39180e4be153ae00000000010000000120925534261de4dcebb1ed5ab1b62bfe7a3ef968fb111dc2c910adfebc6e3bdf010000006b483045022100f50198f5ae66211a4f485190abe4dc7accdabe3bc214ebc9ea7069b97097d46e0220316a70a03014887086e335fc1b48358d46cd6bdc9af3b57c109c94af76fc915101210316cff587a01a2736d5e12e53551b18d73780b83c3bfb4fcf209c869b11b6415effffffff0220a10700000000001976a91450333046115eaa0ac9e0216565f945070e44573988ac2e7cd01a000000001976a914c01a7ca16b47be50cbdbc60724f701d52d75156688ac00000000010000000203a25f58630d7a1ea52550365fd2156683f56daf6ca73a4b4bbd097e66516322010000006a47304402204efc3d70e4ca3049c2a425025edf22d5ca355f9ec899dbfbbeeb2268533a0f2b02204780d3739653035af4814ea52e1396d021953f948c29754edd0ee537364603dc012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff03a25f58630d7a1ea52550365fd2156683f56daf6ca73a4b4bbd097e66516322000000006a47304402202d96defdc5b4af71d6ba28c9a6042c2d5ee7bc6de565d4db84ef517445626e03022022da80320e9e489c8f41b74833dfb6a54a4eb5087cdb46eb663eef0b25caa526012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff0200e1f5050000000017a914b7e6f7ff8658b2d1fb107e3d7be7af4742e6b1b3876f88fc00000000001976a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac0000000001000000043ffd60d3818431c495b89be84afac205d5d1ed663009291c560758bbd0a66df5010000006b483045022100f344607de9df42049688dcae8ff1db34c0c7cd25ec05516e30d2bc8f12ac9b2f022060b648f6a21745ea6d9782e17bcc4277b5808326488a1f40d41e125879723d3a012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffffa5379401cce30f84731ef1ba65ce27edf2cc7ce57704507ebe8714aa16a96b92010000006a473044022020c37a63bf4d7f564c2192528709b6a38ab8271bd96898c6c2e335e5208661580220435c6f1ad4d9305d2c0a818b2feb5e45d443f2f162c0f61953a14d097fd07064012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff70e731e193235ff12c3184510895731a099112ffca4b00246c60003c40f843ce000000006a473044022053760f74c29a879e30a17b5f03a5bb057a5751a39f86fa6ecdedc36a1b7db04c022041d41c9b95f00d2d10a0373322a9025dba66c942196bc9d8adeb0e12d3024728012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff66b7a71b3e50379c8e85fc18fe3f1a408fc985f257036c34702ba205cef09f6f000000006a4730440220499bf9e2db3db6e930228d0661395f65431acae466634d098612fd80b08459ee022040e069fc9e3c60009f521cef54c38aadbd1251aee37940e6018aadb10f194d6a012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff0200e1f5050000000017a9148fc37ad460fdfbd2b44fe446f6e3071a4f64faa6878f447f0b000000001976a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac00000000","5c169b91332e661a4ebf684d6dffcf64aa139e1e736096ce462609b2e0783c55","5f3cd111e10ed28b7c2bc138fe4bc62e5df1cdc292c010b78c84e5111a5daaa6","16040c63f7ddea293f2d9c13690c0ba7b2910228c38b0fe542ce525021e49b598ada05f83bb9c37c711a02b1850265991c34c4fea6261d22a4b84596c0","0e6651beff00ee7a3be424a90e98450727b304558434c8d53781d469131ad21d399376c151ca28","c8f83ffbc9781c2bd4b7e3c055e888b00d3e2fea14e93b3c4f3adee86b063374","61f8ee615258981089be9f98337f53f44b14cc1532aa469a348fdee547117b80","Duplicate pushdata 913bcc2be49cb534c20474c4dee1e9c4c317e7eb"],
-[987876,"0000000000000c00901f2049055e2a437c819d79a3d54fd63e6af796cd7b8a79","000000202694f74969fdb542090e95a56bc8aa2d646e27033850e32f1c5f000000000000f7e53676b3f12d5beb524ed617f2d25f5a93b5f4f52c1ba2678260d72712f8dd0a6dfe5740257e1a4b1768960101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1603e4120ff9c30a1c216900002f424d4920546573742fffffff0001205fa012000000001e76a914c486de584a735ec2f22da7cd9681614681f92173d83d0aa68688ac00000000","37bf9e681888b3cd204ca4e0c995aad68cd0ecb86bdf19dd0fa2e72dbabcda28","c4c5051dd741c11840ef3f11fb4f372a16bb5aac1dc66576e89e8e6835d667e0","021016dc7a6a20","00","156e9bf3ec5be367f0a829858e9ee182cc3a6531bedced491a52fcfed841c6cb","cab50aab93410cb150fd761f2067a909d35c8a9c0114578efd9590e2d381ee02","Coinbase tx has unparseable output script"],
-[1263442,"000000006f27ddfe1dd680044a34548f41bed47eba9e6f0b310da21423bc5f33","000000201c8d1a529c39a396db2db234d5ec152fa651a2872966daccbde028b400000000083f14492679151dbfaa1a825ef4c18518e780c1f91044180280a7d33f4a98ff5f45765aaddc001d38333b9a02010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff230352471300fe5f45765afe94690a000963676d696e6572343208000000000000000000ffffffff024423a804000000001976a914f2c25ac3d59f3d674b1d1d0a25c27339aaac0ba688ac0000000000000000266a24aa21a9edcb26cb3052426b9ebb4d19c819ef87c19677bbf3a7c46ef0855bd1b2abe83491012000000000000000000000000000000000000000000000000000000000000000000000000002000000000101d20978463906ba4ff5e7192494b88dd5eb0de85d900ab253af909106faa22cc5010000000004000000014777ff000000000016001446c29eabe8208a33aa1023c741fa79aa92e881ff0347304402207d7ca96134f2bcfdd6b536536fdd39ad17793632016936f777ebb32c22943fda02206014d2fb8a6aa58279797f861042ba604ebd2f8f61e5bddbd9d3be5a245047b201004b632103eeaeba7ce5dc2470221e9517fb498e8d6bd4e73b85b8be655196972eb9ccd5566754b2752103a40b74d43df244799d041f32ce1ad515a6cd99501701540e38750d883ae21d3a68ac00000000","da6984906c48525f1d800b0e9b480b5fde1a3a32ad7e4cac6a0566d86b9b01a5","7820f3d2397d77068f0f0c824c4f403db89682e5ab6e82d027cb84d7beb8a08c","06970f05e70c2ec63508cdf07609cb8434","03049063c6b4e9a028","5a369775edcb1dcde9bbc88f0897bd3fd9ab0317d2906e8c10b62641c2104c54","73cee3d4b37b689f5da7251f175ff4630f2c142d7399b407d5cac65bc593b68d","Includes witness data"]
+["Block Height,Block Hash,Block,[Prev Output Scripts for Block],Previous Basic Header,Basic Filter,Basic Header,Notes"],
+[0,"000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943","0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff001d1aa4ae180101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000",[],"0000000000000000000000000000000000000000000000000000000000000000","019dfca8","21584579b7eb08997773e5aeff3a7f932700042d0ed2a6129012b7d7ae81b750","Genesis block"],
+[2,"000000006c02c8ea6e4ff69651f7fcde348fb9d557a06e6957b65552002a7820","0100000006128e87be8b1b4dea47a7247d5528d2702c96826c7a648497e773b800000000e241352e3bec0a95a6217e10c3abb54adfa05abb12c126695595580fb92e222032e7494dffff001d00d235340101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0432e7494d010e062f503253482fffffffff0100f2052a010000002321038a7f6ef1c8ca0c588aa53fa860128077c9e6c11e6830f4d7ee4e763a56b7718fac00000000",[],"d7bdac13a59d745b1add0d2ce852f1a0442e8945fc1bf3848d3cbffd88c24fe1","0174a170","186afd11ef2b5e7e3504f2e8cbf8df28a1fd251fe53d60dff8b1467d1b386cf0",""],
+[3,"000000008b896e272758da5297bcd98fdc6d97c9b765ecec401e286dc1fdbe10","0100000020782a005255b657696ea057d5b98f34defcf75196f64f6eeac8026c0000000041ba5afc532aae03151b8aa87b65e1594f97504a768e010c98c0add79216247186e7494dffff001d058dc2b60101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e0486e7494d0151062f503253482fffffffff0100f2052a01000000232103f6d9ff4c12959445ca5549c811683bf9c88e637b222dd2e0311154c4c85cf423ac00000000",[],"186afd11ef2b5e7e3504f2e8cbf8df28a1fd251fe53d60dff8b1467d1b386cf0","016cf7a0","8d63aadf5ab7257cb6d2316a57b16f517bff1c6388f124ec4c04af1212729d2a",""],
+[926485,"000000000000015d6077a411a8f5cc95caf775ccf11c54e27df75ce58d187313","0000002060bbab0edbf3ef8a49608ee326f8fd75c473b7e3982095e2d100000000000000c30134f8c9b6d2470488d7a67a888f6fa12f8692e0c3411fbfb92f0f68f67eedae03ca57ef13021acc22dc4105010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2f0315230e0004ae03ca57043e3d1e1d0c8796bf579aef0c0000000000122f4e696e6a61506f6f6c2f5345475749542fffffffff038427a112000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9ed5c748e121c0fe146d973a4ac26fa4a68b0549d46ee22d25f50a5e46fe1b377ee00000000000000002952534b424c4f434b3acd16772ad61a3c5f00287480b720f6035d5e54c9efc71be94bb5e3727f10909001200000000000000000000000000000000000000000000000000000000000000000000000000100000000010145310e878941a1b2bc2d33797ee4d89d95eaaf2e13488063a2aa9a74490f510a0100000023220020b6744de4f6ec63cc92f7c220cdefeeb1b1bed2b66c8e5706d80ec247d37e65a1ffffffff01002d3101000000001976a9143ebc40e411ed3c76f86711507ab952300890397288ac0400473044022001dd489a5d4e2fbd8a3ade27177f6b49296ba7695c40dbbe650ea83f106415fd02200b23a0602d8ff1bdf79dee118205fc7e9b40672bf31563e5741feb53fb86388501483045022100f88f040e90cc5dc6c6189d04718376ac19ed996bf9e4a3c29c3718d90ffd27180220761711f16c9e3a44f71aab55cbc0634907a1fa8bb635d971a9a01d368727bea10169522103b3623117e988b76aaabe3d63f56a4fc88b228a71e64c4cc551d1204822fe85cb2103dd823066e096f72ed617a41d3ca56717db335b1ea47a1b4c5c9dbdd0963acba621033d7c89bd9da29fa8d44db7906a9778b53121f72191184a9fee785c39180e4be153ae00000000010000000120925534261de4dcebb1ed5ab1b62bfe7a3ef968fb111dc2c910adfebc6e3bdf010000006b483045022100f50198f5ae66211a4f485190abe4dc7accdabe3bc214ebc9ea7069b97097d46e0220316a70a03014887086e335fc1b48358d46cd6bdc9af3b57c109c94af76fc915101210316cff587a01a2736d5e12e53551b18d73780b83c3bfb4fcf209c869b11b6415effffffff0220a10700000000001976a91450333046115eaa0ac9e0216565f945070e44573988ac2e7cd01a000000001976a914c01a7ca16b47be50cbdbc60724f701d52d75156688ac00000000010000000203a25f58630d7a1ea52550365fd2156683f56daf6ca73a4b4bbd097e66516322010000006a47304402204efc3d70e4ca3049c2a425025edf22d5ca355f9ec899dbfbbeeb2268533a0f2b02204780d3739653035af4814ea52e1396d021953f948c29754edd0ee537364603dc012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff03a25f58630d7a1ea52550365fd2156683f56daf6ca73a4b4bbd097e66516322000000006a47304402202d96defdc5b4af71d6ba28c9a6042c2d5ee7bc6de565d4db84ef517445626e03022022da80320e9e489c8f41b74833dfb6a54a4eb5087cdb46eb663eef0b25caa526012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff0200e1f5050000000017a914b7e6f7ff8658b2d1fb107e3d7be7af4742e6b1b3876f88fc00000000001976a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac0000000001000000043ffd60d3818431c495b89be84afac205d5d1ed663009291c560758bbd0a66df5010000006b483045022100f344607de9df42049688dcae8ff1db34c0c7cd25ec05516e30d2bc8f12ac9b2f022060b648f6a21745ea6d9782e17bcc4277b5808326488a1f40d41e125879723d3a012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffffa5379401cce30f84731ef1ba65ce27edf2cc7ce57704507ebe8714aa16a96b92010000006a473044022020c37a63bf4d7f564c2192528709b6a38ab8271bd96898c6c2e335e5208661580220435c6f1ad4d9305d2c0a818b2feb5e45d443f2f162c0f61953a14d097fd07064012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff70e731e193235ff12c3184510895731a099112ffca4b00246c60003c40f843ce000000006a473044022053760f74c29a879e30a17b5f03a5bb057a5751a39f86fa6ecdedc36a1b7db04c022041d41c9b95f00d2d10a0373322a9025dba66c942196bc9d8adeb0e12d3024728012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff66b7a71b3e50379c8e85fc18fe3f1a408fc985f257036c34702ba205cef09f6f000000006a4730440220499bf9e2db3db6e930228d0661395f65431acae466634d098612fd80b08459ee022040e069fc9e3c60009f521cef54c38aadbd1251aee37940e6018aadb10f194d6a012103f7a897e4dbecab2264b21917f90664ea8256189ea725d28740cf7ba5d85b5763ffffffff0200e1f5050000000017a9148fc37ad460fdfbd2b44fe446f6e3071a4f64faa6878f447f0b000000001976a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac00000000",["a914feb8a29635c56d9cd913122f90678756bf23887687","76a914c01a7ca16b47be50cbdbc60724f701d52d75156688ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac","76a914913bcc2be49cb534c20474c4dee1e9c4c317e7eb88ac"],"da49977ba1ee0d620a2c4f8f646b03cd0d230f5c6c994722e3ba884889f0be1a","09027acea61b6cc3fb33f5d52f7d088a6b2f75d234e89ca800","4cd9dd007a325199102f1fc0b7d77ca25ee3c84d46018c4353ecfcb56c0d3e7a","Duplicate pushdata 913bcc2be49cb534c20474c4dee1e9c4c317e7eb"],
+[987876,"0000000000000c00901f2049055e2a437c819d79a3d54fd63e6af796cd7b8a79","000000202694f74969fdb542090e95a56bc8aa2d646e27033850e32f1c5f000000000000f7e53676b3f12d5beb524ed617f2d25f5a93b5f4f52c1ba2678260d72712f8dd0a6dfe5740257e1a4b1768960101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1603e4120ff9c30a1c216900002f424d4920546573742fffffff0001205fa012000000001e76a914c486de584a735ec2f22da7cd9681614681f92173d83d0aa68688ac00000000",[],"e9d729b72d533c29abe5276d5cf6c152f3723f10efe000b1e0c9ca5265a8beb6","010c0b40","e6137ae5a8424c40da1e5023c16975cc97b09300b4c050e6b1c713add3836c40","Coinbase tx has unparseable output script"],
+[1263442,"000000006f27ddfe1dd680044a34548f41bed47eba9e6f0b310da21423bc5f33","000000201c8d1a529c39a396db2db234d5ec152fa651a2872966daccbde028b400000000083f14492679151dbfaa1a825ef4c18518e780c1f91044180280a7d33f4a98ff5f45765aaddc001d38333b9a02010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff230352471300fe5f45765afe94690a000963676d696e6572343208000000000000000000ffffffff024423a804000000001976a914f2c25ac3d59f3d674b1d1d0a25c27339aaac0ba688ac0000000000000000266a24aa21a9edcb26cb3052426b9ebb4d19c819ef87c19677bbf3a7c46ef0855bd1b2abe83491012000000000000000000000000000000000000000000000000000000000000000000000000002000000000101d20978463906ba4ff5e7192494b88dd5eb0de85d900ab253af909106faa22cc5010000000004000000014777ff000000000016001446c29eabe8208a33aa1023c741fa79aa92e881ff0347304402207d7ca96134f2bcfdd6b536536fdd39ad17793632016936f777ebb32c22943fda02206014d2fb8a6aa58279797f861042ba604ebd2f8f61e5bddbd9d3be5a245047b201004b632103eeaeba7ce5dc2470221e9517fb498e8d6bd4e73b85b8be655196972eb9ccd5566754b2752103a40b74d43df244799d041f32ce1ad515a6cd99501701540e38750d883ae21d3a68ac00000000",["002027a5000c7917f785d8fc6e5a55adfca8717ecb973ebb7743849ff956d896a7ed"],"a4a4d6c6034da8aa06f01fe71f1fffbd79e032006b07f6c7a2c60a66aa310c01","0385acb4f0fe889ef0","3588f34fbbc11640f9ed40b2a66a4e096215d50389691309c1dac74d4268aa81","Includes witness data"]
]