-
Notifications
You must be signed in to change notification settings - Fork 10
/
ouroboros.go
138 lines (132 loc) · 4.74 KB
/
ouroboros.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package ouroboros
import (
"github.com/cloudstruct/go-ouroboros-network/muxer"
"github.com/cloudstruct/go-ouroboros-network/protocol"
"github.com/cloudstruct/go-ouroboros-network/protocol/blockfetch"
"github.com/cloudstruct/go-ouroboros-network/protocol/chainsync"
"github.com/cloudstruct/go-ouroboros-network/protocol/handshake"
"github.com/cloudstruct/go-ouroboros-network/protocol/keepalive"
"github.com/cloudstruct/go-ouroboros-network/protocol/localtxsubmission"
"net"
)
type Ouroboros struct {
conn net.Conn
networkMagic uint32
server bool
useNodeToNodeProto bool
handshakeComplete bool
muxer *muxer.Muxer
ErrorChan chan error
sendKeepAlives bool
// Mini-protocols
Handshake *handshake.Handshake
ChainSync *chainsync.ChainSync
chainSyncCallbackConfig *chainsync.ChainSyncCallbackConfig
BlockFetch *blockfetch.BlockFetch
blockFetchCallbackConfig *blockfetch.BlockFetchCallbackConfig
KeepAlive *keepalive.KeepAlive
keepAliveCallbackConfig *keepalive.KeepAliveCallbackConfig
LocalTxSubmission *localtxsubmission.LocalTxSubmission
localTxSubmissionCallbackConfig *localtxsubmission.CallbackConfig
}
type OuroborosOptions struct {
Conn net.Conn
NetworkMagic uint32
ErrorChan chan error
Server bool
UseNodeToNodeProtocol bool
SendKeepAlives bool
ChainSyncCallbackConfig *chainsync.ChainSyncCallbackConfig
BlockFetchCallbackConfig *blockfetch.BlockFetchCallbackConfig
KeepAliveCallbackConfig *keepalive.KeepAliveCallbackConfig
LocalTxSubmissionCallbackConfig *localtxsubmission.CallbackConfig
}
func New(options *OuroborosOptions) (*Ouroboros, error) {
o := &Ouroboros{
conn: options.Conn,
networkMagic: options.NetworkMagic,
server: options.Server,
useNodeToNodeProto: options.UseNodeToNodeProtocol,
chainSyncCallbackConfig: options.ChainSyncCallbackConfig,
blockFetchCallbackConfig: options.BlockFetchCallbackConfig,
keepAliveCallbackConfig: options.KeepAliveCallbackConfig,
localTxSubmissionCallbackConfig: options.LocalTxSubmissionCallbackConfig,
ErrorChan: options.ErrorChan,
sendKeepAlives: options.SendKeepAlives,
}
if o.ErrorChan == nil {
o.ErrorChan = make(chan error, 10)
}
if o.conn != nil {
if err := o.setupConnection(); err != nil {
return nil, err
}
}
return o, nil
}
// Convenience function for creating a connection if you didn't provide one when
// calling New()
func (o *Ouroboros) Dial(proto string, address string) error {
conn, err := net.Dial(proto, address)
if err != nil {
return err
}
o.conn = conn
if err := o.setupConnection(); err != nil {
return err
}
return nil
}
func (o *Ouroboros) setupConnection() error {
o.muxer = muxer.New(o.conn)
// Start Goroutine to pass along errors from the muxer
go func() {
err := <-o.muxer.ErrorChan
o.ErrorChan <- err
}()
protoOptions := protocol.ProtocolOptions{
Muxer: o.muxer,
ErrorChan: o.ErrorChan,
}
var protoVersions []uint16
if o.useNodeToNodeProto {
protoVersions = GetProtocolVersionsNtN()
protoOptions.Mode = protocol.ProtocolModeNodeToNode
} else {
protoVersions = GetProtocolVersionsNtC()
protoOptions.Mode = protocol.ProtocolModeNodeToClient
}
if o.server {
protoOptions.Role = protocol.ProtocolRoleServer
} else {
protoOptions.Role = protocol.ProtocolRoleClient
}
// Perform handshake
o.Handshake = handshake.New(protoOptions, protoVersions)
// TODO: figure out better way to signify automatic handshaking and returning the chosen version
if !o.server {
err := o.Handshake.ProposeVersions(protoVersions, o.networkMagic)
if err != nil {
return err
}
}
o.handshakeComplete = <-o.Handshake.Finished
if o.useNodeToNodeProto {
versionNtN := GetProtocolVersionNtN(o.Handshake.Version)
protoOptions.Mode = protocol.ProtocolModeNodeToNode
o.ChainSync = chainsync.New(protoOptions, o.chainSyncCallbackConfig)
o.BlockFetch = blockfetch.New(protoOptions, o.blockFetchCallbackConfig)
if versionNtN.EnableKeepAliveProtocol {
o.KeepAlive = keepalive.New(protoOptions, o.keepAliveCallbackConfig)
if o.sendKeepAlives {
o.KeepAlive.Start()
}
}
} else {
//versionNtC := GetProtocolVersionNtC(o.Handshake.Version)
protoOptions.Mode = protocol.ProtocolModeNodeToClient
o.ChainSync = chainsync.New(protoOptions, o.chainSyncCallbackConfig)
o.LocalTxSubmission = localtxsubmission.New(protoOptions, o.localTxSubmissionCallbackConfig)
}
return nil
}