Skip to content

Commit 265dc3d

Browse files
committed
Chain-sync mini-protocol (part 2)
* basic support for parsing Shelley blocks * skeleton for parsing post-Shelley blocks * switch to callback model for chain-sync * implement FindIntersect * flesh out chain-sync state machine
1 parent 7205236 commit 265dc3d

File tree

13 files changed

+372
-183
lines changed

13 files changed

+372
-183
lines changed

block/allegra.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package block
2+
3+
const (
4+
BLOCK_TYPE_ALLEGRA = 4
5+
)

block/alonzo.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package block
2+
3+
const (
4+
BLOCK_TYPE_ALONZO = 5
5+
)

protocol/common/block.go renamed to block/bryon.go

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
package common
1+
package block
22

3-
import (
4-
"encoding/hex"
3+
const (
4+
BLOCK_TYPE_BYRON_EBB = 0
5+
BLOCK_TYPE_BYRON_MAIN = 1
56
)
67

78
type ByronMainBlockHeader struct {
@@ -93,18 +94,6 @@ type ByronEpochBoundaryBlock struct {
9394
Extra []interface{}
9495
}
9596

96-
type Blake2b256 [32]byte
97-
98-
func (b Blake2b256) String() string {
99-
return hex.EncodeToString([]byte(b[:]))
100-
}
101-
102-
type Blake2b224 [28]byte
103-
104-
func (b Blake2b224) String() string {
105-
return hex.EncodeToString([]byte(b[:]))
106-
}
107-
10897
/*
10998
blake2b-256 = bytes .size 32
11099
@@ -127,6 +116,6 @@ stakeholderid = blake2b-224
127116
// genesisHash = [ ]
128117
// blockHash = [ int ]
129118
// blockBody = bstr
130-
// heade rSlot = word64
119+
// headerSlot = word64
131120
// headerBlockNo = word64
132121
// headerBodyHash = int

block/common.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package block
2+
3+
import (
4+
"encoding/hex"
5+
)
6+
7+
type Blake2b256 [32]byte
8+
9+
func (b Blake2b256) String() string {
10+
return hex.EncodeToString([]byte(b[:]))
11+
}
12+
13+
type Blake2b224 [28]byte
14+
15+
func (b Blake2b224) String() string {
16+
return hex.EncodeToString([]byte(b[:]))
17+
}

block/mary.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package block
2+
3+
const (
4+
BLOCK_TYPE_MARY = 3
5+
)

block/shelley.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package block
2+
3+
import (
4+
"github.com/fxamacker/cbor/v2"
5+
)
6+
7+
const (
8+
BLOCK_TYPE_SHELLEY = 2
9+
)
10+
11+
type ShelleyBlock struct {
12+
// Tells the CBOR decoder to convert to/from a struct and a CBOR array
13+
_ struct{} `cbor:",toarray"`
14+
Header ShelleyBlockHeader
15+
// TODO: create structure for transaction bodies that accounts for
16+
// map with bytestring keys for staking reward withdrawals
17+
TransactionBodies []cbor.RawMessage
18+
TransactionWitnessSets interface{}
19+
TransactionMetadataSet interface{}
20+
}
21+
22+
type ShelleyBlockHeader struct {
23+
// Tells the CBOR decoder to convert to/from a struct and a CBOR array
24+
_ struct{} `cbor:",toarray"`
25+
Body struct {
26+
// Tells the CBOR decoder to convert to/from a struct and a CBOR array
27+
_ struct{} `cbor:",toarray"`
28+
BlockNumber uint64
29+
Slot uint64
30+
PrevHash Blake2b256
31+
IssuerVkey interface{}
32+
VrfKey interface{}
33+
NonceVrf interface{}
34+
LeaderVrf interface{}
35+
BlockBodySize uint32
36+
BlockBodyHash Blake2b256
37+
HotVkey interface{}
38+
SequenceNumber uint32
39+
KesPeriod uint32
40+
Sigma interface{}
41+
OperationalCertNum uint
42+
ProtocolVersion interface{}
43+
}
44+
Signature interface{}
45+
}

cmd/go-ouroboros-network/main.go

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ package main
22

33
import (
44
"crypto/tls"
5+
"encoding/hex"
56
"flag"
67
"fmt"
78
"github.com/cloudstruct/go-ouroboros-network"
9+
"github.com/cloudstruct/go-ouroboros-network/block"
810
"github.com/cloudstruct/go-ouroboros-network/protocol/chainsync"
9-
"github.com/cloudstruct/go-ouroboros-network/protocol/common"
1011
"github.com/cloudstruct/go-ouroboros-network/utils"
1112
"io"
1213
"net"
@@ -27,6 +28,12 @@ type cmdFlags struct {
2728
mainnet bool
2829
}
2930

31+
type chainSyncState struct {
32+
readyForNextBlockChan chan bool
33+
}
34+
35+
var syncState chainSyncState
36+
3037
func main() {
3138
f := cmdFlags{}
3239
flag.StringVar(&f.socket, "socket", "", "UNIX socket path to connect to")
@@ -75,6 +82,14 @@ func main() {
7582
oOpts := &ouroboros.OuroborosOptions{
7683
Conn: conn,
7784
NetworkMagic: uint32(f.networkMagic),
85+
ChainSyncCallbackConfig: &chainsync.ChainSyncCallbackConfig{
86+
AwaitReplyFunc: chainSyncAwaitReplyHandler,
87+
RollBackwardFunc: chainSyncRollBackwardHandler,
88+
RollForwardFunc: chainSyncRollForwardHandler,
89+
IntersectFoundFunc: chainSyncIntersectFoundHandler,
90+
IntersectNotFoundFunc: chainSyncIntersectNotFoundHandler,
91+
DoneFunc: chainSyncDoneHandler,
92+
},
7893
}
7994
o, err := ouroboros.New(oOpts)
8095
if err != nil {
@@ -89,22 +104,68 @@ func main() {
89104
}
90105
}()
91106
// Test chain-sync
107+
syncState.readyForNextBlockChan = make(chan bool, 0)
108+
secondToLastByronSlot := 1598398
109+
//lastByronBlockHash, _ := hex.DecodeString("7e16781b40ebf8b6da18f7b5e8ade855d6738095ef2f1c58c77e88b6e45997a4")
110+
secondToLastByronBlockHash, _ := hex.DecodeString("8542ae6166cc4affadefd44585488fef9a02aee7914e1e387ce5f7a33e6569c5")
111+
if err := o.ChainSync.FindIntersect([]interface{}{[]interface{}{secondToLastByronSlot, secondToLastByronBlockHash}}); err != nil {
112+
fmt.Printf("ERROR: FindIntersect: %s\n", err)
113+
os.Exit(1)
114+
}
115+
// Wait until ready for next block
116+
<-syncState.readyForNextBlockChan
92117
for {
93-
resp, err := o.ChainSync.RequestNext()
118+
err := o.ChainSync.RequestNext()
94119
if err != nil {
95-
fmt.Printf("ERROR: %s\n", err)
120+
fmt.Printf("ERROR: RequestNext: %s\n", err)
96121
os.Exit(1)
97122
}
98123
//fmt.Printf("resp = %#v, err = %#v\n", resp, err)
99-
switch resp.BlockType {
100-
case chainsync.BLOCK_TYPE_BYRON_EBB:
101-
fmt.Printf("found Byron EBB block\n")
102-
case chainsync.BLOCK_TYPE_BYRON_MAIN:
103-
block := resp.Block.(common.ByronMainBlock)
104-
fmt.Printf("epoch = %d, slot = %d, prevBlock = %s\n", block.Header.ConsensusData.SlotId.Epoch, block.Header.ConsensusData.SlotId.Slot, block.Header.PrevBlock)
105-
default:
106-
fmt.Printf("unsupported (so far) block type %d\n", resp.BlockType)
107-
fmt.Printf("%s\n", utils.DumpCborStructure(resp.Block, ""))
108-
}
124+
// Wait until ready for next block
125+
<-syncState.readyForNextBlockChan
126+
}
127+
}
128+
129+
func chainSyncAwaitReplyHandler() error {
130+
return nil
131+
}
132+
133+
func chainSyncRollBackwardHandler(point interface{}, tip interface{}) error {
134+
fmt.Printf("roll backward: point = %#v, tip = %#v\n", point, tip)
135+
syncState.readyForNextBlockChan <- true
136+
return nil
137+
}
138+
139+
func chainSyncRollForwardHandler(blockType uint, blockData interface{}) error {
140+
switch blockType {
141+
case block.BLOCK_TYPE_BYRON_EBB:
142+
fmt.Printf("found Byron EBB block\n")
143+
case block.BLOCK_TYPE_BYRON_MAIN:
144+
b := blockData.(block.ByronMainBlock)
145+
fmt.Printf("era = Byron, epoch = %d, slot = %d, prevBlock = %s\n", b.Header.ConsensusData.SlotId.Epoch, b.Header.ConsensusData.SlotId.Slot, b.Header.PrevBlock)
146+
case block.BLOCK_TYPE_SHELLEY:
147+
b := blockData.(block.ShelleyBlock)
148+
fmt.Printf("era = Shelley, slot = %d, block_no = %d, prevHash = %s\n", b.Header.Body.Slot, b.Header.Body.BlockNumber, b.Header.Body.PrevHash)
149+
default:
150+
fmt.Printf("unsupported (so far) block type %d\n", blockType)
151+
fmt.Printf("%s\n", utils.DumpCborStructure(blockData, ""))
109152
}
153+
syncState.readyForNextBlockChan <- true
154+
return nil
155+
}
156+
157+
func chainSyncIntersectFoundHandler(point interface{}, tip interface{}) error {
158+
fmt.Printf("found intersect: point = %#v, tip = %#v\n", point, tip)
159+
syncState.readyForNextBlockChan <- true
160+
return nil
161+
}
162+
163+
func chainSyncIntersectNotFoundHandler() error {
164+
fmt.Printf("ERROR: failed to find intersection\n")
165+
os.Exit(1)
166+
return nil
167+
}
168+
169+
func chainSyncDoneHandler() error {
170+
return nil
110171
}

ouroboros.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,28 @@ type Ouroboros struct {
1818
muxer *muxer.Muxer
1919
ErrorChan chan error
2020
// Mini-protocols
21-
Handshake *handshake.Handshake
22-
ChainSync *chainsync.ChainSync
21+
Handshake *handshake.Handshake
22+
ChainSync *chainsync.ChainSync
23+
chainSyncCallbackConfig *chainsync.ChainSyncCallbackConfig
2324
}
2425

2526
type OuroborosOptions struct {
2627
Conn io.ReadWriteCloser
2728
NetworkMagic uint32
2829
// Whether to wait for the other side to initiate the handshake. This is useful
2930
// for servers
30-
WaitForHandshake bool
31-
UseNodeToNodeProtocol bool
31+
WaitForHandshake bool
32+
UseNodeToNodeProtocol bool
33+
ChainSyncCallbackConfig *chainsync.ChainSyncCallbackConfig
3234
}
3335

3436
func New(options *OuroborosOptions) (*Ouroboros, error) {
3537
o := &Ouroboros{
36-
conn: options.Conn,
37-
networkMagic: options.NetworkMagic,
38-
waitForHandshake: options.WaitForHandshake,
39-
ErrorChan: make(chan error, 10),
38+
conn: options.Conn,
39+
networkMagic: options.NetworkMagic,
40+
waitForHandshake: options.WaitForHandshake,
41+
chainSyncCallbackConfig: options.ChainSyncCallbackConfig,
42+
ErrorChan: make(chan error, 10),
4043
}
4144
if o.conn != nil {
4245
if err := o.setupConnection(); err != nil {
@@ -79,6 +82,6 @@ func (o *Ouroboros) setupConnection() error {
7982
o.handshakeComplete = <-o.Handshake.Finished
8083
fmt.Printf("negotiated protocol version %d\n", o.Handshake.Version)
8184
// TODO: register additional mini-protocols
82-
o.ChainSync = chainsync.New(o.muxer, o.ErrorChan, o.useNodeToNodeProto)
85+
o.ChainSync = chainsync.New(o.muxer, o.ErrorChan, o.useNodeToNodeProto, o.chainSyncCallbackConfig)
8386
return nil
8487
}

0 commit comments

Comments
 (0)