Skip to content

Commit 59d0f79

Browse files
committed
feat: local-tx-monitor protocol
Fixes #13
1 parent 8ac4dd4 commit 59d0f79

File tree

13 files changed

+997
-3
lines changed

13 files changed

+997
-3
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*.so
66
*.dylib
77
/go-ouroboros-network
8+
/tx-monitor
89

910
# Test binary, built with `go test -c`
1011
*.test

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ ROOT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
55
GO_FILES=$(shell find $(ROOT_DIR) -name '*.go')
66

77
# Gather list of expected binaries
8-
BINARIES=$(shell cd $(ROOT_DIR)/cmd && ls -1)
8+
BINARIES=$(shell cd $(ROOT_DIR)/cmd && ls -1 | grep -v ^common)
99

1010
.PHONY: build mod-tidy clean test
1111

cmd/common/cmdline.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package common
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"os"
7+
)
8+
9+
const (
10+
TESTNET_MAGIC = 1097911063
11+
MAINNET_MAGIC = 764824073
12+
PREPROD_MAGIC = 1
13+
PREVIEW_MAGIC = 2
14+
)
15+
16+
type GlobalFlags struct {
17+
Flagset *flag.FlagSet
18+
Socket string
19+
Address string
20+
UseTls bool
21+
NtnProto bool
22+
NetworkMagic int
23+
Testnet bool
24+
Mainnet bool
25+
Preprod bool
26+
Preview bool
27+
}
28+
29+
func NewGlobalFlags() *GlobalFlags {
30+
f := &GlobalFlags{
31+
Flagset: flag.NewFlagSet(os.Args[0], flag.ExitOnError),
32+
}
33+
f.Flagset.StringVar(&f.Socket, "socket", "", "UNIX socket path to connect to")
34+
f.Flagset.StringVar(&f.Address, "address", "", "TCP address to connect to in address:port format")
35+
f.Flagset.BoolVar(&f.UseTls, "tls", false, "enable TLS")
36+
f.Flagset.BoolVar(&f.NtnProto, "ntn", false, "use node-to-node protocol (defaults to node-to-client)")
37+
f.Flagset.IntVar(&f.NetworkMagic, "network-magic", 0, "network magic value")
38+
f.Flagset.BoolVar(&f.Testnet, "testnet", false, fmt.Sprintf("alias for -network-magic=%d", TESTNET_MAGIC))
39+
f.Flagset.BoolVar(&f.Mainnet, "mainnet", false, fmt.Sprintf("alias for -network-magic=%d", MAINNET_MAGIC))
40+
f.Flagset.BoolVar(&f.Preprod, "preprod", false, fmt.Sprintf("alias for -network-magic=%d", PREPROD_MAGIC))
41+
f.Flagset.BoolVar(&f.Preview, "preview", false, fmt.Sprintf("alias for -network-magic=%d", PREVIEW_MAGIC))
42+
return f
43+
}
44+
45+
func (f *GlobalFlags) Parse() {
46+
if err := f.Flagset.Parse(os.Args[1:]); err != nil {
47+
fmt.Printf("failed to parse command args: %s\n", err)
48+
os.Exit(1)
49+
}
50+
if f.NetworkMagic == 0 {
51+
if f.Testnet {
52+
f.NetworkMagic = TESTNET_MAGIC
53+
} else if f.Mainnet {
54+
f.NetworkMagic = MAINNET_MAGIC
55+
} else if f.Preprod {
56+
f.NetworkMagic = PREPROD_MAGIC
57+
} else if f.Preview {
58+
f.NetworkMagic = PREVIEW_MAGIC
59+
} else {
60+
fmt.Printf("You must specify one of -testnet, -mainnet, -preprod, -preview, or -network-magic\n\n")
61+
f.Flagset.PrintDefaults()
62+
os.Exit(1)
63+
}
64+
}
65+
}

cmd/common/connect.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package common
2+
3+
import (
4+
"crypto/tls"
5+
"fmt"
6+
"net"
7+
"os"
8+
)
9+
10+
func CreateClientConnection(f *GlobalFlags) net.Conn {
11+
var err error
12+
var conn net.Conn
13+
var dialProto string
14+
var dialAddress string
15+
if f.Socket != "" {
16+
dialProto = "unix"
17+
dialAddress = f.Socket
18+
} else if f.Address != "" {
19+
dialProto = "tcp"
20+
dialAddress = f.Address
21+
} else {
22+
fmt.Printf("You must specify one of -socket or -address\n\n")
23+
f.Flagset.PrintDefaults()
24+
os.Exit(1)
25+
}
26+
if f.UseTls {
27+
conn, err = tls.Dial(dialProto, dialAddress, nil)
28+
} else {
29+
conn, err = net.Dial(dialProto, dialAddress)
30+
}
31+
if err != nil {
32+
fmt.Printf("Connection failed: %s\n", err)
33+
os.Exit(1)
34+
}
35+
return conn
36+
}

cmd/tx-monitor/main.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package main
2+
3+
import (
4+
"encoding/hex"
5+
"fmt"
6+
"os"
7+
8+
"github.com/cloudstruct/go-ouroboros-network"
9+
"github.com/cloudstruct/go-ouroboros-network/cmd/common"
10+
11+
"github.com/fxamacker/cbor/v2"
12+
"golang.org/x/crypto/blake2b"
13+
)
14+
15+
func main() {
16+
// Parse commandline
17+
f := common.NewGlobalFlags()
18+
f.Parse()
19+
// Create connection
20+
conn := common.CreateClientConnection(f)
21+
errorChan := make(chan error)
22+
go func() {
23+
for {
24+
err := <-errorChan
25+
fmt.Printf("ERROR(async): %s\n", err)
26+
os.Exit(1)
27+
}
28+
}()
29+
o, err := ouroboros.New(
30+
ouroboros.WithConnection(conn),
31+
ouroboros.WithNetworkMagic(uint32(f.NetworkMagic)),
32+
ouroboros.WithErrorChan(errorChan),
33+
ouroboros.WithNodeToNode(f.NtnProto),
34+
ouroboros.WithKeepAlive(true),
35+
)
36+
if err != nil {
37+
fmt.Printf("ERROR: %s\n", err)
38+
os.Exit(1)
39+
}
40+
o.LocalTxMonitor().Client.Start()
41+
42+
capacity, size, numberOfTxs, err := o.LocalTxMonitor().Client.GetSizes()
43+
if err != nil {
44+
fmt.Printf("ERROR(GetSizes): %s\n", err)
45+
os.Exit(1)
46+
}
47+
fmt.Printf("Mempool size/capacity (bytes): %d / %d, TXs: %d\n", size, capacity, numberOfTxs)
48+
49+
fmt.Printf("Transactions:\n\n")
50+
for {
51+
tx, err := o.LocalTxMonitor().Client.NextTx()
52+
if err != nil {
53+
fmt.Printf("ERROR(NextTx): %s\n", err)
54+
os.Exit(1)
55+
}
56+
if tx == nil {
57+
break
58+
}
59+
// Unwrap raw transaction bytes into a CBOR array
60+
var txUnwrap []cbor.RawMessage
61+
if err := cbor.Unmarshal(tx, &txUnwrap); err != nil {
62+
fmt.Printf("ERROR(unwrap): %s\n", err)
63+
os.Exit(1)
64+
}
65+
// index 0 is the transaction body
66+
// Store index 0 (transaction body) as byte array
67+
txBody := txUnwrap[0]
68+
// Convert the body into a blake2b256 hash string
69+
txIdHash := blake2b.Sum256(txBody)
70+
// Encode hash string as byte array to hex string
71+
txIdHex := hex.EncodeToString(txIdHash[:])
72+
fmt.Printf("%s\n", txIdHex)
73+
}
74+
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ go 1.17
55
require (
66
github.com/cloudstruct/go-cardano-ledger v0.4.0
77
github.com/fxamacker/cbor/v2 v2.4.0
8+
golang.org/x/crypto v0.0.0-20220824171710-5757bc0c5503
89
)
910

1011
require (
1112
github.com/x448/float16 v0.8.4 // indirect
12-
golang.org/x/crypto v0.0.0-20220824171710-5757bc0c5503 // indirect
1313
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
1414
)

ouroboros.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/cloudstruct/go-ouroboros-network/protocol/handshake"
2424
"github.com/cloudstruct/go-ouroboros-network/protocol/keepalive"
2525
"github.com/cloudstruct/go-ouroboros-network/protocol/localstatequery"
26+
"github.com/cloudstruct/go-ouroboros-network/protocol/localtxmonitor"
2627
"github.com/cloudstruct/go-ouroboros-network/protocol/localtxsubmission"
2728
"github.com/cloudstruct/go-ouroboros-network/protocol/txsubmission"
2829
)
@@ -50,6 +51,8 @@ type Ouroboros struct {
5051
blockFetchConfig *blockfetch.Config
5152
keepAlive *keepalive.KeepAlive
5253
keepAliveConfig *keepalive.Config
54+
localTxMonitor *localtxmonitor.LocalTxMonitor
55+
localTxMonitorConfig *localtxmonitor.Config
5356
localTxSubmission *localtxsubmission.LocalTxSubmission
5457
localTxSubmissionConfig *localtxsubmission.Config
5558
localStateQuery *localstatequery.LocalStateQuery
@@ -168,6 +171,11 @@ func (o *Ouroboros) KeepAlive() *keepalive.KeepAlive {
168171
return o.keepAlive
169172
}
170173

174+
// LocalTxMonitor returns the local-tx-monitor protocol handler
175+
func (o *Ouroboros) LocalTxMonitor() *localtxmonitor.LocalTxMonitor {
176+
return o.localTxMonitor
177+
}
178+
171179
// LocalTxSubmission returns the local-tx-submission protocol handler
172180
func (o *Ouroboros) LocalTxSubmission() *localtxsubmission.LocalTxSubmission {
173181
return o.localTxSubmission
@@ -297,6 +305,9 @@ func (o *Ouroboros) setupConnection() error {
297305
if versionNtC.EnableLocalQueryProtocol {
298306
o.localStateQuery = localstatequery.New(protoOptions, o.localStateQueryConfig)
299307
}
308+
if versionNtC.EnableLocalTxMonitorProtocol {
309+
o.localTxMonitor = localtxmonitor.New(protoOptions, o.localTxMonitorConfig)
310+
}
300311
}
301312
// Start muxer
302313
diffusionMode := muxer.DiffusionModeInitiator

0 commit comments

Comments
 (0)