Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
133 commits
Select commit Hold shift + click to select a range
9714090
Init wire Messages
iteyelmp Jul 6, 2026
9db15e2
Update text
iteyelmp Jul 6, 2026
9292105
fix bugs
iteyelmp Jul 6, 2026
91950ad
fix comment
iteyelmp Jul 9, 2026
a0a8b70
implement RpcConn and XshardConn compatibility layer
iteyelmp Jul 10, 2026
1ec3b32
Delete __init__.py
iteyelmp Jul 13, 2026
15ade28
add MasterConn with master handler registration and dispatch
iteyelmp Jul 13, 2026
57ee95d
Fix the conn abstraction layer
iteyelmp Jul 14, 2026
f065e74
Merge branch 'slave-04' into slave-05
iteyelmp Jul 14, 2026
60f1fa0
fix bug
iteyelmp Jul 14, 2026
5ac4bca
add PeerConn, Dispatcher, and peer routing
iteyelmp Jul 15, 2026
0da214b
fix review bug
iteyelmp Jul 16, 2026
466814f
Merge branch 'slave-04' into slave-05
iteyelmp Jul 16, 2026
d3518ca
fix review bug
iteyelmp Jul 16, 2026
cc35af6
Merge branch 'slave-05' into slave-06
iteyelmp Jul 16, 2026
d38744d
fix review bug
iteyelmp Jul 16, 2026
415badb
fix bugs
iteyelmp Jul 20, 2026
de4ecea
Merge branch 'slave-04' into slave-05
iteyelmp Jul 20, 2026
302940e
Merge branch 'slave-05' into slave-06
iteyelmp Jul 20, 2026
2142437
fix bugs
iteyelmp Jul 20, 2026
7294812
fix comment
iteyelmp Jul 21, 2026
e06cefa
Merge branch 'slave-04' into slave-05
iteyelmp Jul 21, 2026
71f0f50
fix comment
iteyelmp Jul 21, 2026
5f019dd
Merge branch 'slave-05' into slave-06
iteyelmp Jul 21, 2026
6c43288
fix comment
iteyelmp Jul 21, 2026
0990983
Merge remote-tracking branch 'origin/goshard/base' into slave-04
iteyelmp Jul 29, 2026
022d29b
Merge remote-tracking branch 'origin/goshard/base' into slave-04
iteyelmp Aug 4, 2026
03c3826
fix comment
iteyelmp Aug 4, 2026
0f592cc
fix conn lifecycle
iteyelmp Aug 5, 2026
a0e04f7
cleanup xshard connections from pool on close
iteyelmp Aug 5, 2026
dce9199
adjust the directory structure.
iteyelmp Aug 5, 2026
3b96a6d
adjust the directory structure.
iteyelmp Aug 5, 2026
25c28a5
fix bug
iteyelmp Aug 6, 2026
4aafafd
fix bug
iteyelmp Aug 7, 2026
847a67d
fix bug
iteyelmp Aug 10, 2026
ddec213
Merge remote-tracking branch 'origin/goshard/base' into slave-04
iteyelmp Aug 10, 2026
488df43
Merge branch 'slave-04' into slave-05
iteyelmp Aug 10, 2026
13d5ff3
fix bug
iteyelmp Aug 10, 2026
16406d2
Merge branch 'slave-04' into slave-05
iteyelmp Aug 10, 2026
cbb4c53
Adjusting organizational structure
iteyelmp Aug 11, 2026
5da3c2e
Merge branch 'slave-04' into slave-05
iteyelmp Aug 11, 2026
d879987
Repairing conflicts
iteyelmp Aug 11, 2026
e5af81e
Fixing inconsistencies between EOF and Python
iteyelmp Aug 11, 2026
ff7a1b7
Merge branch 'slave-04' into slave-05
iteyelmp Aug 11, 2026
ff29481
Merge branch 'slave-05' into slave-06
iteyelmp Aug 11, 2026
d980b5d
remove opcode
iteyelmp Aug 12, 2026
230da38
Merge branch 'slave-05' into slave-06
iteyelmp Aug 12, 2026
9652bbb
Fix code conflicts
iteyelmp Aug 12, 2026
e7efbbd
remove code
iteyelmp Aug 12, 2026
c5d2036
Reset Architecture
iteyelmp Aug 13, 2026
bf293df
fix bug
iteyelmp Aug 13, 2026
57aba49
fix bug
iteyelmp Aug 13, 2026
3b4f944
fix comment
iteyelmp Aug 13, 2026
e8c299a
Code optimization
iteyelmp Aug 13, 2026
ff272d3
Fix inconsistencies with Python
iteyelmp Aug 13, 2026
1542eef
Fix inconsistencies with Python
iteyelmp Aug 13, 2026
4de6328
Remove XShard
iteyelmp Aug 14, 2026
b4a4b22
init XShard
iteyelmp Aug 14, 2026
d381e8d
Optimize the structure
iteyelmp Aug 14, 2026
5651916
fix comment
iteyelmp Aug 14, 2026
85324b7
Merge branch 'slave-04' into slave-04-1
iteyelmp Aug 14, 2026
575d3a3
fix comment
iteyelmp Aug 14, 2026
2a41078
new architecture
iteyelmp Aug 17, 2026
04e7f0f
fix bug
iteyelmp Aug 17, 2026
2cbb586
fix bug
iteyelmp Aug 18, 2026
8a56dfd
Merge branch 'goshard/base' into slave-04
iteyelmp Aug 18, 2026
7ebeab1
fix bug
iteyelmp Aug 18, 2026
13458d5
Code optimization
iteyelmp Aug 19, 2026
47c8b73
fix bug
iteyelmp Aug 19, 2026
14b5119
fix bug
iteyelmp Aug 19, 2026
3cd1e61
fix bug
iteyelmp Aug 19, 2026
63e938c
Improve readability
iteyelmp Aug 19, 2026
887dc42
remove code
iteyelmp Aug 19, 2026
d4d8406
remove code
iteyelmp Aug 19, 2026
de0d020
remove code
iteyelmp Aug 19, 2026
15582de
remove code and add test
iteyelmp Aug 20, 2026
fa549d3
Merge remote-tracking branch 'origin/slave-04' into slave-04-1
iteyelmp Aug 20, 2026
4077a8b
Resolve merge conflicts
iteyelmp Aug 20, 2026
e1452e4
Adjusting the architecture
iteyelmp Aug 21, 2026
060cacf
Adjusting the architecture
iteyelmp Aug 21, 2026
feea39c
Edit comments
iteyelmp Aug 21, 2026
dc22f1e
Edit comments
iteyelmp Aug 21, 2026
1496809
remove test
iteyelmp Aug 21, 2026
19adef4
fix bug
iteyelmp Aug 24, 2026
425aaea
Merge remote-tracking branch 'origin/slave-04-1' into slave-05
iteyelmp Aug 24, 2026
422368b
fix merge bug
iteyelmp Aug 24, 2026
a194bfc
Merge remote-tracking branch 'origin/slave-05' into slave-06
iteyelmp Aug 25, 2026
0ada1ef
fix merge bug
iteyelmp Aug 25, 2026
2db3e51
fix comment
iteyelmp Aug 25, 2026
1be67af
fix comment
iteyelmp Aug 25, 2026
c9b53f9
fix comment
iteyelmp Aug 25, 2026
eaa0f5e
Code optimization
iteyelmp Aug 26, 2026
eb402ea
Merge remote-tracking branch 'origin/slave-05' into slave-06
iteyelmp Aug 26, 2026
08a16c1
Code optimization
iteyelmp Aug 26, 2026
cb18f12
fix bug
iteyelmp Aug 26, 2026
11fc34d
fix comment
iteyelmp Aug 27, 2026
96529dc
Merge remote-tracking branch 'origin/slave-04' into slave-04-1
iteyelmp Aug 27, 2026
1fdd64e
fix bug
iteyelmp Aug 27, 2026
3e49afd
change public api
iteyelmp Aug 27, 2026
07f073a
Code optimization
iteyelmp Aug 27, 2026
d4afa4a
Merge branch 'goshard/base' into slave-04-1
iteyelmp Aug 27, 2026
b87af6c
add test
iteyelmp Aug 28, 2026
e250440
Merge remote-tracking branch 'origin/slave-04-1' into slave-05
iteyelmp Aug 28, 2026
c7dfe0f
fix comment
iteyelmp Aug 28, 2026
fbca841
Merge remote-tracking branch 'origin/slave-05' into slave-06
iteyelmp Aug 28, 2026
287a4cf
move code
iteyelmp Aug 28, 2026
bc00e0a
fix py bug
iteyelmp Aug 31, 2026
c62bd3d
code optimism
iteyelmp Aug 31, 2026
6ed18f4
fix comment
iteyelmp Sep 2, 2026
ac28ddd
Merge branch 'goshard/base' into slave-04-1
iteyelmp Sep 2, 2026
d9e0ad3
fix test
iteyelmp Sep 2, 2026
679f5a0
Merge remote-tracking branch 'origin/slave-04-1' into slave-05
iteyelmp Sep 2, 2026
8a7a368
Adjust the architecture and split the handler.
iteyelmp Sep 2, 2026
e8e9e4d
Merge remote-tracking branch 'origin/slave-05' into slave-06
iteyelmp Sep 2, 2026
64dcf76
Adjust the architecture
iteyelmp Sep 2, 2026
d029286
To ensure consistent semantics, XShardConn cannot be added if cluster…
iteyelmp Sep 2, 2026
b66de81
fix test comment
iteyelmp Sep 3, 2026
738b945
Merge remote-tracking branch 'origin/slave-04-1' into slave-05
iteyelmp Sep 3, 2026
72166d8
Adjusting the architecture
iteyelmp Sep 3, 2026
b17fa93
Merge remote-tracking branch 'origin/slave-05' into slave-06
iteyelmp Sep 3, 2026
6a38c6c
fix merge error
iteyelmp Sep 3, 2026
bfefa9a
Merge branch 'goshard/base' into slave-05
iteyelmp Sep 4, 2026
6d4696d
Merge remote-tracking branch 'origin/slave-05' into slave-06
iteyelmp Sep 4, 2026
633eea9
fix merge error
iteyelmp Sep 4, 2026
12ee65e
fix comment
iteyelmp Sep 8, 2026
9997d65
fix comment
iteyelmp Sep 8, 2026
b6b7a9e
Merge remote-tracking branch 'origin/slave-05' into slave-06
iteyelmp Sep 8, 2026
d89b50a
fix merge error
iteyelmp Sep 8, 2026
5ae5b39
Merge branch 'goshard/base' into slave-06
iteyelmp Sep 9, 2026
2ba0dfe
Code optimization
iteyelmp Sep 10, 2026
48ff6ae
add test
iteyelmp Sep 10, 2026
a0d0c7b
Merge branch 'goshard/base' into slave-06
iteyelmp Sep 11, 2026
3cf7593
fix merge error
iteyelmp Sep 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 88 additions & 7 deletions qkc/cluster/slave/master_conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@ import (
"github.com/ethereum/go-ethereum/qkc/types"
)

// PeerResolver resolves the virtual PeerConn a forwarded peer frame is
// addressed to. It is implemented by the composition layer that owns the peer
// registry and injected into MasterConn, which uses it only for frame routing
// — never for request delegation (that is MasterHandler's job).
type PeerResolver interface {
// LookupPeer returns the PeerConn for (clusterPeerID, branch), or nil when
// this slave has none; the frame is then dropped (py: slave.py:131-146
// NULL_CONNECTION).
LookupPeer(clusterPeerID uint64, branch uint32) *PeerConn
}

// MasterHandler handles master requests delegated by MasterConn.
// It is implemented by the composition layer and injected into MasterConn.
type MasterHandler interface {
Expand Down Expand Up @@ -71,8 +82,7 @@ type MasterHandler interface {
GetTotalBalance(req *wire.GetTotalBalanceRequest) (*wire.GetTotalBalanceResponse, error)
}

// MasterConnConfig configures a MasterConn. Conn and Handler are required;
// Logger defaults to log.Root().
// MasterConnConfig configures a MasterConn.
type MasterConnConfig struct {
// Conn is the accepted TCP connection from the master. The slave never
// dials the master (py: MasterServer connects, SlaveServer listens).
Expand All @@ -87,9 +97,19 @@ type MasterConnConfig struct {
LocalID []byte
LocalFullShardIDList []uint32

// ClusterShardIDs is the cluster-wide configured full shard id set
// (py: env.quark_chain_config.get_full_shard_ids()). routeFrame uses it to
// reject frames from a master for a branch outside the global config, which
// is fatal for the connection (py: slave.py:123-129 close_with_error).
ClusterShardIDs []uint32

// Handler handles master requests delegated by MasterConn.
Handler MasterHandler

// PeerResolver resolves forwarded peer frames (cluster_peer_id != 0) to
// their virtual PeerConn. It is consulted by the routing forwarder only.
PeerResolver PeerResolver

// Logger defaults to log.Root() if nil.
Logger log.Logger
}
Expand All @@ -101,8 +121,14 @@ type MasterConn struct {
*conn.BaseConn

handler MasterHandler
peerResolver PeerResolver
localID []byte
localFullShardIDList []uint32

// clusterShardIDs is the cluster-wide configured full shard id set
// (py: env.quark_chain_config.get_full_shard_ids()); a frame for a branch
// outside it closes the connection (see routeFrame).
clusterShardIDs map[uint32]struct{}
}

// NewMasterConn wraps an accepted net.Conn from the master.
Expand All @@ -114,16 +140,35 @@ func NewMasterConn(cfg MasterConnConfig) (*MasterConn, error) {
if cfg.Handler == nil {
return nil, errors.New("master handler must not be nil")
}
if cfg.PeerResolver == nil {
return nil, errors.New("master peer resolver must not be nil")
}
if len(cfg.ClusterShardIDs) == 0 {
return nil, errors.New("cluster shard ids is required")
}
readFrame := func(r io.Reader) (*wire.Frame, error) {
return wire.ReadFrame(r, cfg.MaxPayloadSize)
}

clusterShardIDs := make(map[uint32]struct{}, len(cfg.ClusterShardIDs))
for _, id := range cfg.ClusterShardIDs {
clusterShardIDs[id] = struct{}{}
}

mc := &MasterConn{
handler: cfg.Handler,
peerResolver: cfg.PeerResolver,
localID: append([]byte(nil), cfg.LocalID...),
localFullShardIDList: append([]uint32(nil), cfg.LocalFullShardIDList...),
clusterShardIDs: clusterShardIDs,
}

// Forwarder: route cluster_peer_id != 0 frames to virtual PeerConns.
// routeFrame returns false for master-local traffic so MasterConn handles
// it normally. The forwarder runs on the reader goroutine; it enqueues
// frames without blocking (the PeerConn inbound queue is unbounded).
forwarder := mc.routeFrame

mc.BaseConn = conn.NewBaseConn(conn.Config{
Transport: conn.NewTCPTransport(cfg.Conn, readFrame, wire.WriteFrame),
Serializers: map[byte]*conn.OpSerializer{
Expand Down Expand Up @@ -209,11 +254,8 @@ func NewMasterConn(cfg MasterConnConfig) (*MasterConn, error) {
NonRPCOps: map[byte]struct{}{
byte(wire.ClusterOpDestroyClusterPeerConnectionCommand): {},
},
// Forwarder stays nil: routing peer traffic (cluster_peer_id != 0)
// to virtual PeerConns is PR6 (Dispatcher as the frame consumer).
// Until then, any peer frame (CommandOp opcode) is unregistered and
// closes the connection — MasterConn must not receive peer traffic.
Logger: cfg.Logger,
Forwarder: forwarder,
Logger: cfg.Logger,
})
return mc, nil
}
Expand Down Expand Up @@ -254,6 +296,45 @@ func (mc *MasterConn) SendAddMinorBlockHeaderList(ctx context.Context, req *wire
return r, nil
}

// ── Frame routing ───────────────────────────────────────────────────────

// routeFrame handles frames addressed to virtual peer connections.
// cluster_peer_id == 0 is master-local traffic and returns false so the
// normal MasterConn dispatcher handles it. Peer traffic is validated and
// forwarded to the corresponding PeerConn.
// A branch outside the GLOBAL configured shard set is fatal for the
// connection (py: slave.py:123-129 close_with_error); a branch that is
// globally valid but not owned/created locally, or an unknown peer id,
// follows Python's NULL_CONNECTION semantics (slave.py:131-146): the
// frame is consumed and dropped without closing the connection.
func (mc *MasterConn) routeFrame(frame *wire.Frame) bool {
if frame.Meta.ClusterPeerID == 0 {
return false
}

if _, ok := mc.clusterShardIDs[frame.Meta.Branch]; !ok {
mc.Logger().Error(
"incorrect forwarding branch",
"branch", fmt.Sprintf("0x%x", frame.Meta.Branch),
)
mc.Close()
return true
}

pc := mc.peerResolver.LookupPeer(frame.Meta.ClusterPeerID, frame.Meta.Branch)
if pc == nil {
// Covers both "shard valid globally but not created locally"
// (slave.py:131-134) and "peer not found" (slave.py:136-146): drop,
// keep the connection.
mc.Logger().Warn("dropping frame for unknown virtual peer connection",
"cluster_peer_id", frame.Meta.ClusterPeerID, "branch", frame.Meta.Branch)
return true
}

pc.HandleFrame(frame)
return true
}

// ── topology & shard activation handlers ───────────────────────────────────

// handlePing handles the master's PING.
Expand Down
39 changes: 37 additions & 2 deletions qkc/cluster/slave/master_conn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ func (h *fakeMasterHandler) ConnectToSlaves(req *wire.ConnectToSlavesRequest) (*
return resp, nil
}

// LookupPeer implements PeerResolver. This fake models a slave with no
// PeerConns at all: every lookup misses, so a peer frame follows MasterConn's
// NULL_CONNECTION path (dropped, connection kept). Fakes that own a peer
// registry (fakeSlaveService) shadow this with a real lookup.
func (h *fakeMasterHandler) LookupPeer(uint64, uint32) *PeerConn { return nil }

func (h *fakeMasterHandler) Mine(*wire.MineRequest) (*wire.MineResponse, error) {
return &wire.MineResponse{}, nil
}
Expand Down Expand Up @@ -260,7 +266,9 @@ func newMasterConnWithPeer(t *testing.T, handler *fakeMasterHandler) (*MasterCon
Conn: slaveConn,
LocalID: []byte("go-slave"),
LocalFullShardIDList: []uint32{0x00010001},
ClusterShardIDs: []uint32{0x00010001},
Handler: handler,
PeerResolver: handler,
Logger: log.New(),
})
if err != nil {
Expand All @@ -281,13 +289,26 @@ func newMasterConnWithPeer(t *testing.T, handler *fakeMasterHandler) (*MasterCon
// ── construction ─────────────────────────────────────────────────────────────

func TestMasterConn_ConfigValidation(t *testing.T) {
// Nil conn / nil handler must be rejected.
// Nil conn / nil handler / nil peer resolver must be rejected.
if _, err := NewMasterConn(MasterConnConfig{}); err == nil {
t.Fatal("expected error for nil conn")
}
if _, err := NewMasterConn(MasterConnConfig{Conn: &net.TCPConn{}}); err == nil {
t.Fatal("expected error for nil master handler")
}
if _, err := NewMasterConn(MasterConnConfig{
Conn: &net.TCPConn{},
Handler: &fakeMasterHandler{},
}); err == nil {
t.Fatal("expected error for nil peer resolver")
}
if _, err := NewMasterConn(MasterConnConfig{
Conn: &net.TCPConn{},
Handler: &fakeMasterHandler{},
PeerResolver: &fakeMasterHandler{},
}); err == nil {
t.Fatal("expected error for empty cluster shard ids")
}
}

// TestMasterConn_IdentitySnapshot verifies that LocalID and
Expand All @@ -306,7 +327,9 @@ func TestMasterConn_IdentitySnapshot(t *testing.T) {
Conn: slaveConn,
LocalID: localID,
LocalFullShardIDList: shardList,
ClusterShardIDs: []uint32{0x00010001},
Handler: &fakeMasterHandler{},
PeerResolver: &fakeMasterHandler{},
Logger: log.New(),
})
if err != nil {
Expand Down Expand Up @@ -366,8 +389,10 @@ func TestMasterConn_Ping(t *testing.T) {
t.Fatalf("serialize ping: %v", err)
}
// RPC IDs strictly increase across both pings.
// cluster_peer_id 0 keeps the frame on the master-local path; the
// branch is echoed untouched by the PONG.
if err := peer.send(&wire.Frame{
Meta: wire.ClusterMetadata{},
Meta: wire.ClusterMetadata{Branch: 0x00010001},
Opcode: byte(wire.ClusterOpPing),
RPCID: uint64(i + 1),
Payload: payload,
Expand All @@ -382,6 +407,12 @@ func TestMasterConn_Ping(t *testing.T) {
if resp.RPCID != uint64(i+1) {
t.Fatalf("pong rpc_id: got %d, want %d", resp.RPCID, uint64(i+1))
}
if resp.Meta.ClusterPeerID != 0 {
t.Fatalf("master-local response must keep cluster_peer_id 0, got %d", resp.Meta.ClusterPeerID)
}
if resp.Meta.Branch != 0x00010001 {
t.Fatalf("pong branch: got 0x%x, want 0x%x", resp.Meta.Branch, 0x00010001)
}
var pong wire.PongResponse
if err := serialize.Deserialize(serialize.NewByteBuffer(resp.Payload), &pong); err != nil {
t.Fatalf("deserialize pong: %v", err)
Expand Down Expand Up @@ -761,7 +792,9 @@ func TestMasterConn_SendAddMinorBlockHeader(t *testing.T) {
Conn: clientConn,
LocalID: []byte("slave"),
LocalFullShardIDList: []uint32{0x00010001},
ClusterShardIDs: []uint32{0x00010001},
Handler: &fakeMasterHandler{},
PeerResolver: &fakeMasterHandler{},
Logger: log.New(),
})
if err != nil {
Expand Down Expand Up @@ -849,7 +882,9 @@ func TestMasterConn_SendAddMinorBlockHeaderList(t *testing.T) {
Conn: clientConn,
LocalID: []byte("slave"),
LocalFullShardIDList: []uint32{0x00010001},
ClusterShardIDs: []uint32{0x00010001},
Handler: &fakeMasterHandler{},
PeerResolver: &fakeMasterHandler{},
Logger: log.New(),
})
if err != nil {
Expand Down
Loading