github.com/deso-protocol/core@v1.2.9/scripts/mempool/mempool_dumper.go (about)

     1  package main
     2  
     3  import (
     4  	"bufio"
     5  	"encoding/hex"
     6  	"flag"
     7  	"fmt"
     8  	"github.com/btcsuite/btcd/addrmgr"
     9  	"log"
    10  	"net"
    11  	"os"
    12  	"strings"
    13  	"time"
    14  
    15  	"github.com/davecgh/go-spew/spew"
    16  	"github.com/deso-protocol/core/lib"
    17  	"github.com/golang/glog"
    18  )
    19  
    20  var (
    21  	flagNode = flag.String(
    22  		"node", "",
    23  		"When dumping, should be pointed at a JSON API. E.g.: "+
    24  			"https://api.bitclout.com. When loading, should "+
    25  			"be pointed at a protocol port. E.g.: 127.0.0.1:17000")
    26  
    27  	flagCommand = flag.String(
    28  		"command", "",
    29  		"Must be dump or load. When dump is specified, txns "+
    30  			"are downloaded from the JSON API node and raw txn hex "+
    31  			"is printed. When load is specified, txns are read from "+
    32  			"stdin and injected into the protocol node specified.")
    33  
    34  	flagDiffNode = flag.String(
    35  		"diff_node", "",
    36  		"A node to diff against. When set, "+
    37  			"this should be a protocol port and --node must be a JSON port.")
    38  )
    39  
    40  func main() {
    41  	flag.Parse()
    42  
    43  	// Set up logging.
    44  	log.Println("To log output on commandline, run with -alsologtostderr")
    45  	glog.CopyStandardLogTo("INFO")
    46  
    47  	if *flagNode == "" {
    48  		panic("--node is required and must be a " +
    49  			"JSON API when dumping or a protocol port when loading")
    50  	}
    51  
    52  	// Set up the to node as a peer
    53  	netAddrss, err := lib.IPToNetAddr(*flagNode, addrmgr.New("", net.LookupIP), &lib.DeSoMainnetParams)
    54  	if err != nil {
    55  		panic(err)
    56  	}
    57  
    58  	netAddr2 := net.TCPAddr{
    59  		IP:   netAddrss.IP,
    60  		Port: int(netAddrss.Port),
    61  	}
    62  	conn, err := net.DialTimeout(netAddr2.Network(), netAddr2.String(), lib.DeSoMainnetParams.DialTimeout)
    63  	if err != nil {
    64  		panic(err)
    65  	}
    66  
    67  	messagesFromPeer := make(chan *lib.ServerMessage)
    68  	peer := lib.NewPeer(conn, true, netAddrss, true,
    69  		10000, 0, &lib.DeSoMainnetParams,
    70  		messagesFromPeer, nil, nil)
    71  	time.Sleep(1 * time.Second)
    72  	if err := peer.NegotiateVersion(lib.DeSoMainnetParams.VersionNegotiationTimeout); err != nil {
    73  		panic(err)
    74  	}
    75  
    76  	// As a test, send a GetHeaders request and see if we get it back
    77  	if *flagCommand == "get_headers" {
    78  		time.Sleep(1 * time.Second)
    79  		peer.WriteDeSoMessage(&lib.MsgDeSoGetHeaders{
    80  			StopHash: lib.MustDecodeHexBlockHash("0000000000000000000000000000000000000000000000000000000000000000"),
    81  			BlockLocator: []*lib.BlockHash{
    82  				lib.MustDecodeHexBlockHash("0000000000f70d7a6dce5502eddb40772fc4b6b1e54e809b21bd38c6bd447e05"),
    83  				lib.MustDecodeHexBlockHash("0000000000c49db46a5ba1a9d35dfd870c791ea6b695c49e522fe9a7c0f308e8"),
    84  				lib.MustDecodeHexBlockHash("0000000000597c8ebfe3122c2aa003b6dc0fd67e97e6b4cae437517dd2f500a4"),
    85  				lib.MustDecodeHexBlockHash("0000000000da97c2b70bbd5af7d707ff7772ac7064e4946b1aebf5b863902723"),
    86  				lib.MustDecodeHexBlockHash("000000000083a5ef8c0df071362668f1b1bd764f02ef4aeebf25a9f54f721189"),
    87  				lib.MustDecodeHexBlockHash("0000000000f0636590f0d1a1d163edac52611269c56cf1601a27c182af2b7752"),
    88  				lib.MustDecodeHexBlockHash("0000000000fd9249bd4f89e12e74b3107e11694b1b5dadf61af08f1218943861"),
    89  				lib.MustDecodeHexBlockHash("00000000006ad067641de4bd55218fbf2b3b260054a2d8a1a2ca0843199f89ea"),
    90  				lib.MustDecodeHexBlockHash("0000000000e0f41c722d853639b1f9aefd7ac7613f249e6f71c41349b4e03ff3"),
    91  				lib.MustDecodeHexBlockHash("0000000000b0add5db4833d26406625925c5ef4d3097bbee67037723a3f8e391"),
    92  				lib.MustDecodeHexBlockHash("00000000001662747a5f03db9d6551a72250cc32747597b004bf95f328bae57e"),
    93  				lib.MustDecodeHexBlockHash("0000000000d6267bca36f88efa9e6947bbe36149d378fd9464e72db48dc22dca"),
    94  				lib.MustDecodeHexBlockHash("00000000006f422c0bd7f4154cb3a6173e2e7cf2fc10c63ca75c1aeeb9b1d563"),
    95  				lib.MustDecodeHexBlockHash("00000000007da3b19ddcf04c57b3c936ec1dcaa6c21214c33aa256afced22aca"),
    96  				lib.MustDecodeHexBlockHash("00000000003802f3a2fc4fa3775780d704486b65b9ed56b67f6d4c3335a7b9b5"),
    97  				lib.MustDecodeHexBlockHash("00000000009552ebd611e4f9d8c2cb4f08d8f17da2b739979604a2a0743d433d"),
    98  				lib.MustDecodeHexBlockHash("0000000000060c2df58fca53b083dc0b6879a49aa69e5c9c6d12ec7e6e8c8890"),
    99  				lib.MustDecodeHexBlockHash("0000000000032f0ab25daa56eab3000dda92ce52a128ca57e8cb17bb8c1e2ced"),
   100  				lib.MustDecodeHexBlockHash("00000000007b2444f17f8fcf216c52f32d4c0e374c4598957443c20209e7e39b"),
   101  				lib.MustDecodeHexBlockHash("00000000008df3db9dda88e1f2dada964e28e0c05030861eaf351a875cf154bb"),
   102  				lib.MustDecodeHexBlockHash("00000000006bff73eea66c748c089fe384b76fddf24b0830abad8343e2c53813"),
   103  				lib.MustDecodeHexBlockHash("0000000000830059a9eb948f3ed3996ff93efb642d09a71744327ceafe9e10ea"),
   104  				lib.MustDecodeHexBlockHash("0000000000a5da7ccb9a3e6824dedc31ed112cdd22cc2ca9d1e98992deb97225"),
   105  				lib.MustDecodeHexBlockHash("000000004a9facc6804cb39cdf5f1c2360dc372d4e532dccd5c3489671eacd29"),
   106  				lib.MustDecodeHexBlockHash("5567c45b7b83b604f9ff5cb5e88dfc9ad7d5a1dd5818dd19e6d02466f47cbd62"),
   107  			},
   108  		})
   109  
   110  		log.Println("Sent GetHeaders message. Waiting for response")
   111  
   112  		// There should be a single inv that comes back
   113  		for {
   114  			msg, err := peer.ReadDeSoMessage()
   115  			if err != nil {
   116  				panic(err)
   117  			}
   118  			fmt.Println(msg.GetMsgType())
   119  		}
   120  	} else if *flagCommand == "dump" {
   121  		time.Sleep(1 * time.Second)
   122  		peer.WriteDeSoMessage(&lib.MsgDeSoMempool{})
   123  		log.Println("Sent Mempool message. Waiting for big inv")
   124  
   125  		// There should be a single inv that comes back
   126  		for {
   127  			msg, err := peer.ReadDeSoMessage()
   128  			if err != nil {
   129  				panic(err)
   130  			}
   131  			if msg.GetMsgType() == lib.MsgTypeInv {
   132  				invMsg := msg.(*lib.MsgDeSoInv)
   133  				if len(invMsg.InvList) == 0 {
   134  					log.Println("Ignoringing empty INV")
   135  					continue
   136  				}
   137  				if invMsg.InvList[0].Type == lib.InvTypeBlock {
   138  					log.Println("Ignoring BLOCK INV")
   139  					continue
   140  				}
   141  				log.Println("Processing inv of size ", len(invMsg.InvList))
   142  				hashesToRequest := []*lib.BlockHash{}
   143  				for _, inv := range invMsg.InvList {
   144  					if inv.Type == lib.InvTypeTx {
   145  						hashesToRequest = append(hashesToRequest, &inv.Hash)
   146  					}
   147  				}
   148  
   149  				// Now we have all the hashes, request the txn.
   150  				getTxns := &lib.MsgDeSoGetTransactions{}
   151  				getTxns.HashList = hashesToRequest
   152  
   153  				// Fetch all the txns back from the node
   154  				peer.WriteDeSoMessage(getTxns)
   155  				time.Sleep(100 * time.Millisecond)
   156  
   157  			} else if msg.GetMsgType() == lib.MsgTypeTransactionBundle {
   158  				txBundle := msg.(*lib.MsgDeSoTransactionBundle)
   159  				log.Println("Processing txn bundle of size ", len(txBundle.Transactions))
   160  				for _, tx := range txBundle.Transactions {
   161  					bb, _ := tx.ToBytes(false /*preSignature*/)
   162  					fmt.Printf("%v,%v,%v\n", tx.TxnMeta.GetTxnType(), tx.Hash(), hex.EncodeToString(bb))
   163  				}
   164  
   165  				time.Sleep(1)
   166  				peer.Disconnect()
   167  				break
   168  			}
   169  		}
   170  	} else if *flagCommand == "load" {
   171  		scanner := bufio.NewScanner(os.Stdin)
   172  		buf := make([]byte, 0, 64*1024)
   173  		scanner.Buffer(buf, 250*1024*1024)
   174  		txnBundle := &lib.MsgDeSoTransactionBundle{}
   175  		getTxnMsg := &lib.MsgDeSoGetTransactions{}
   176  		for scanner.Scan() {
   177  			txnHex := scanner.Text()
   178  
   179  			parts := strings.Split(txnHex, ",")
   180  			if len(parts) != 1 {
   181  				txnHex = parts[2]
   182  			}
   183  
   184  			bb, err := hex.DecodeString(txnHex)
   185  			if err != nil {
   186  				panic(err)
   187  			}
   188  			txn := &lib.MsgDeSoTxn{}
   189  			if err := txn.FromBytes(bb); err != nil {
   190  				glog.Error(err)
   191  				continue
   192  			}
   193  
   194  			txnBundle.Transactions = append(txnBundle.Transactions, txn)
   195  
   196  			getTxnMsg.HashList = append(getTxnMsg.HashList, txn.Hash())
   197  		}
   198  		if err := scanner.Err(); err != nil {
   199  			panic(err)
   200  		}
   201  
   202  		fmt.Println(len(txnBundle.Transactions))
   203  
   204  		// Write all the messages to the node
   205  		peer.WriteDeSoMessage(txnBundle)
   206  
   207  		// Fetch all the txns back from the node
   208  		peer.WriteDeSoMessage(getTxnMsg)
   209  
   210  		for {
   211  			msg, err := peer.ReadDeSoMessage()
   212  			if err != nil {
   213  				panic(err)
   214  			}
   215  			txnsFound := make(map[lib.BlockHash]*lib.MsgDeSoTxn)
   216  			if msg.GetMsgType() == lib.MsgTypeTransactionBundle {
   217  				for _, txn := range msg.(*lib.MsgDeSoTransactionBundle).Transactions {
   218  					txnsFound[*txn.Hash()] = txn
   219  				}
   220  
   221  				summary := make(map[lib.TxnType]int64)
   222  				for _, txn := range txnBundle.Transactions {
   223  					if _, exists := txnsFound[*txn.Hash()]; !exists {
   224  						glog.Infof("NOT LOADED: %v %v", txn.TxnMeta.GetTxnType(), txn.Hash())
   225  						bb, err := txn.ToBytes(false)
   226  						if err != nil {
   227  							panic(err)
   228  						}
   229  						glog.V(1).Infof("TXN HEX: %v", hex.EncodeToString(bb))
   230  						glog.V(2).Infof("DETAILS: %v", spew.Sdump(txn))
   231  
   232  						val, _ := summary[txn.TxnMeta.GetTxnType()]
   233  						summary[txn.TxnMeta.GetTxnType()] = val + 1
   234  					}
   235  				}
   236  				glog.Info("Summary of missing txns: ", spew.Sdump(summary))
   237  				break
   238  			}
   239  		}
   240  
   241  		peer.Disconnect()
   242  
   243  	} else {
   244  		fmt.Println("Command must be 'dump' or 'load'")
   245  		os.Exit(0)
   246  	}
   247  }