1515package main
1616
1717import (
18+ "encoding/hex"
19+ "encoding/json"
1820 "fmt"
21+ "io/ioutil"
1922 "os"
23+ "time"
2024
2125 ouroboros "github.com/blinklabs-io/gouroboros"
26+ "github.com/blinklabs-io/gouroboros/cbor"
2227 "github.com/blinklabs-io/gouroboros/cmd/common"
2328 "github.com/blinklabs-io/gouroboros/protocol/txsubmission"
29+
30+ "golang.org/x/crypto/blake2b"
2431)
2532
2633type txSubmissionFlags struct {
2734 * common.GlobalFlags
35+ txFile string
36+ rawTxFile string
2837}
2938
39+ var txBytes []byte
40+ var txHash [32 ]byte
41+ var sentTx bool
42+ var doneChan chan any
43+
3044func main () {
3145 // Parse commandline
3246 f := txSubmissionFlags {
3347 GlobalFlags : common .NewGlobalFlags (),
3448 }
49+ f .Flagset .StringVar (& f .txFile , "tx-file" , "" , "path to the JSON transaction file to submit" )
50+ f .Flagset .StringVar (& f .rawTxFile , "raw-tx-file" , "" , "path to the raw transaction file to submit" )
3551 f .Parse ()
3652 // Create connection
3753 conn := common .CreateClientConnection (f .GlobalFlags )
@@ -51,18 +67,8 @@ func main() {
5167 ouroboros .WithKeepAlive (true ),
5268 ouroboros .WithTxSubmissionConfig (
5369 txsubmission .NewConfig (
54- txsubmission .WithRequestTxIdsFunc (
55- // TODO: do something more useful
56- func (blocking bool , ack uint16 , req uint16 ) ([]txsubmission.TxIdAndSize , error ) {
57- return []txsubmission.TxIdAndSize {}, nil
58- },
59- ),
60- txsubmission .WithRequestTxsFunc (
61- // TODO: do something more useful
62- func (txIds []txsubmission.TxId ) ([]txsubmission.TxBody , error ) {
63- return []txsubmission.TxBody {}, nil
64- },
65- ),
70+ txsubmission .WithRequestTxIdsFunc (handleRequestTxIds ),
71+ txsubmission .WithRequestTxsFunc (handleRequestTxs ),
6672 ),
6773 ),
6874 )
@@ -71,9 +77,93 @@ func main() {
7177 os .Exit (1 )
7278 }
7379
80+ // Read the transaction file
81+ if f .txFile != "" {
82+ txData , err := ioutil .ReadFile (f .txFile )
83+ if err != nil {
84+ fmt .Printf ("Failed to load transaction file: %s\n " , err )
85+ os .Exit (1 )
86+ }
87+
88+ var jsonData map [string ]string
89+ err = json .Unmarshal (txData , & jsonData )
90+ if err != nil {
91+ fmt .Printf ("failed to parse transaction file: %s\n " , err )
92+ os .Exit (1 )
93+ }
94+
95+ txBytes , err = hex .DecodeString (jsonData ["cborHex" ])
96+ if err != nil {
97+ fmt .Printf ("failed to decode transaction: %s\n " , err )
98+ os .Exit (1 )
99+ }
100+ } else if f .rawTxFile != "" {
101+ txBytes , err = ioutil .ReadFile (f .rawTxFile )
102+ if err != nil {
103+ fmt .Printf ("Failed to load transaction file: %s\n " , err )
104+ os .Exit (1 )
105+ }
106+ } else {
107+ fmt .Printf ("You must specify one of -tx-file or -raw-tx-file\n " )
108+ os .Exit (1 )
109+ }
110+
111+ // Generate TX hash
112+ // Unwrap raw transaction bytes into a CBOR array
113+ var txUnwrap []cbor.RawMessage
114+ if _ , err := cbor .Decode (txBytes , & txUnwrap ); err != nil {
115+ fmt .Printf ("ERROR: failed to unwrap transaction CBOR: %s" , err )
116+ os .Exit (1 )
117+ }
118+ // index 0 is the transaction body
119+ // Store index 0 (transaction body) as byte array
120+ txBody := txUnwrap [0 ]
121+
122+ // Convert the body into a blake2b256 hash string
123+ txHash = blake2b .Sum256 (txBody )
124+
125+ // Create our "done" channel
126+ doneChan = make (chan any )
127+
74128 // Start the TxSubmission activity loop
75129 o .TxSubmission ().Client .Init ()
76130
77- // Wait forever
78- select {}
131+ // Wait until we're done
132+ <- doneChan
133+
134+ fmt .Printf ("Successfully sent transaction %x\n " , txHash )
135+
136+ if err := o .Close (); err != nil {
137+ fmt .Printf ("ERROR: failed to close connection: %s\n " , err )
138+ os .Exit (1 )
139+ }
140+ }
141+
142+ func handleRequestTxIds (blocking bool , ack uint16 , req uint16 ) ([]txsubmission.TxIdAndSize , error ) {
143+ if sentTx {
144+ // Terrible syncronization hack for shutdown
145+ close (doneChan )
146+ time .Sleep (5 * time .Second )
147+ }
148+ ret := []txsubmission.TxIdAndSize {
149+ {
150+ TxId : txsubmission.TxId {
151+ EraId : 5 ,
152+ TxId : txHash ,
153+ },
154+ Size : uint32 (len (txBytes )),
155+ },
156+ }
157+ return ret , nil
158+ }
159+
160+ func handleRequestTxs (txIds []txsubmission.TxId ) ([]txsubmission.TxBody , error ) {
161+ ret := []txsubmission.TxBody {
162+ {
163+ EraId : 5 ,
164+ TxBody : txBytes ,
165+ },
166+ }
167+ sentTx = true
168+ return ret , nil
79169}
0 commit comments