Discovery Neo Oclib

This commit is contained in:
mr
2026-05-27 16:17:00 +02:00
parent 7f951afd41
commit 6ce6e6fe7d
20 changed files with 1436 additions and 1133 deletions
+8
View File
@@ -66,6 +66,10 @@ type Heartbeat struct {
// MembershipEvents carries SWIM events piggybacked on this heartbeat.
// Events are forwarded infection-style until HopsLeft reaches 0.
MembershipEvents []MemberEvent `json:"membership_events,omitempty"`
// PendingContact lists peer IDs for which this node has undelivered critical
// DTN entries. Indexers maintain an inverted index so those peers can
// discover who is waiting for them when they reconnect.
PendingContact []string `json:"pending_contact,omitempty"`
}
// SearchPeerRequest is sent by a node to an indexer via ProtocolSearchPeer.
@@ -134,6 +138,10 @@ type HeartbeatResponse struct {
// MembershipEvents carries SWIM events piggybacked on this response.
// The node should forward them to its other indexers (infection-style).
MembershipEvents []MemberEvent `json:"membership_events,omitempty"`
// PendingCallers lists peer IDs that have undelivered critical DTN messages
// for the receiving node, as recorded by this indexer. On receipt the node
// should initiate contact with each caller so it can flush its DTN cache.
PendingCallers []string `json:"pending_callers,omitempty"`
}
// ComputeIndexerScore computes a composite quality score [0, 100] for the connecting peer.
+33 -12
View File
@@ -29,7 +29,7 @@ var retryRunning atomic.Bool
// peer has at least 3 chances to respond or refute the suspicion signal.
const suspectTimeout = 3 * RecommendedHeartbeatInterval
func ConnectToIndexers(h host.Host, minIndexer int, maxIndexer int, recordFn ...func() json.RawMessage) error {
func ConnectToIndexers(h host.Host, minIndexer int, maxIndexer int, hooks ...HeartbeatHooks) error {
TimeWatcher = time.Now().UTC()
logger := oclib.GetLogger()
@@ -71,7 +71,7 @@ func ConnectToIndexers(h host.Host, minIndexer int, maxIndexer int, recordFn ...
// Start long-lived heartbeat to seed indexers. The single goroutine follows
// all subsequent StaticIndexers changes.
SendHeartbeat(context.Background(), ProtocolHeartbeat, conf.GetConfig().Name,
h, Indexers, 20*time.Second, maxIndexer, recordFn...)
h, Indexers, 20*time.Second, maxIndexer, hooks...)
// Watch for inbound connections: if a peer connects to us and our pool has
// room, probe it first to confirm it supports ProtocolHeartbeat (i.e. it is
@@ -270,17 +270,29 @@ func handleSuggestions(d *Directory, from string, suggestions []pp.AddrInfo) {
}
}
// HeartbeatHooks carries optional callbacks injected into the heartbeat loop.
type HeartbeatHooks struct {
// RecordFn returns a fresh signed PeerRecord for embedding in each heartbeat.
RecordFn func() json.RawMessage
// PendingContactFn returns the list of peer IDs for which the caller has
// undelivered critical DTN entries. Called on every tick.
PendingContactFn func() []string
// OnPendingCallers is invoked when an indexer response contains peer IDs
// that have undelivered messages for us. The caller should initiate contact
// with each of them so they can flush their DTN cache.
OnPendingCallers func(callerPeerIDs []string)
}
// SendHeartbeat starts a goroutine that sends periodic heartbeats to peers.
// recordFn, when provided, is called on each tick and its output is embedded in
// the heartbeat as a fresh signed PeerRecord so the receiving indexer can
// republish it to the DHT without an extra round-trip.
// Pass no recordFn (or nil) for indexer→indexer / native heartbeats.
func SendHeartbeat(ctx context.Context, proto protocol.ID, name string, h host.Host, directory *Directory, interval time.Duration, maxPool int, recordFn ...func() json.RawMessage) {
// hooks.RecordFn, when set, is called on each tick and its output is embedded
// in the heartbeat as a fresh signed PeerRecord.
// Pass an empty HeartbeatHooks (or none) for indexer→indexer / native heartbeats.
func SendHeartbeat(ctx context.Context, proto protocol.ID, name string, h host.Host, directory *Directory, interval time.Duration, maxPool int, hooks ...HeartbeatHooks) {
logger := oclib.GetLogger()
isIndexerHB := directory == Indexers
var recFn func() json.RawMessage
if len(recordFn) > 0 {
recFn = recordFn[0]
var hk HeartbeatHooks
if len(hooks) > 0 {
hk = hooks[0]
}
go func() {
logger.Info().Str("proto", string(proto)).Int("peers", len(directory.Addrs)).Msg("heartbeat started")
@@ -306,8 +318,11 @@ func SendHeartbeat(ctx context.Context, proto protocol.ID, name string, h host.H
IndexersBinded: addrs,
Need: need,
}
if recFn != nil {
baseHB.Record = recFn()
if hk.RecordFn != nil {
baseHB.Record = hk.RecordFn()
}
if hk.PendingContactFn != nil {
baseHB.PendingContact = hk.PendingContactFn()
}
// Piggyback SWIM membership events on every outgoing heartbeat batch.
// All peers in the pool receive the same events this tick.
@@ -550,6 +565,12 @@ func SendHeartbeat(ctx context.Context, proto protocol.ID, name string, h host.H
handleSuggestions(directory, ai.Info.ID.String(), resp.Suggestions)
}
// PendingCallers: peers that have undelivered DTN messages for us.
// Signal the DTN layer so it can flush immediately when it reaches them.
if resp != nil && len(resp.PendingCallers) > 0 && hk.OnPendingCallers != nil {
hk.OnPendingCallers(resp.PendingCallers)
}
// Handle SuggestMigrate: indexer is overloaded and wants us to move.
if resp != nil && resp.SuggestMigrate && isIndexerHB {
nonSeedCount := 0
+7 -2
View File
@@ -261,7 +261,10 @@ func (ix *LongLivedStreamRecordedService[T]) HandleHeartbeat(s network.Stream) {
}
func CheckHeartbeat(h host.Host, s network.Stream, dec *json.Decoder, streams map[pp.ID]HeartBeatStreamed, lock *sync.RWMutex, maxNodes int) (*pp.ID, *Heartbeat, error) {
if len(h.Network().Peers()) >= maxNodes {
// Use the heartbeat stream count, not h.Network().Peers(), which includes
// upstream indexer connections, short-lived protocol streams (publish/get/probe),
// and zombie libp2p connections whose heartbeat stream has already been GC'd.
if len(streams) >= maxNodes {
return nil, nil, fmt.Errorf("too many connections, try another indexer")
}
var hb Heartbeat
@@ -285,9 +288,11 @@ func CheckHeartbeat(h host.Host, s network.Stream, dec *json.Decoder, streams ma
// E: measure the indexer's own subnet diversity, not the node's view.
diversity := getOwnDiversityRate(h)
// fillRate: fraction of indexer capacity used — higher = more peers trust this indexer.
// Use heartbeat stream count (same as fill rate reported to nodes), not
// h.Network().Peers() which inflates the count with upstream/probe connections.
fillRate := 0.0
if maxNodes > 0 {
fillRate = float64(len(h.Network().Peers())) / float64(maxNodes)
fillRate = float64(len(streams)) / float64(maxNodes)
if fillRate > 1 {
fillRate = 1
}
+4 -4
View File
@@ -184,11 +184,10 @@ func TempStream(h host.Host, ad pp.AddrInfo, proto protocol.ID, did string, stre
}
ctxTTL, cancelTTL := context.WithTimeout(context.Background(), expiry)
defer cancelTTL()
if h.Network().Connectedness(ad.ID) != network.Connected {
fmt.Println(ad.ID, len(h.Network().ConnsToPeer(ad.ID)))
if len(h.Network().ConnsToPeer(ad.ID)) == 0 {
if err := h.Connect(ctxTTL, ad); err != nil {
fmt.Println("Connectedness", ad.ID, err)
return streams, err
}
}
@@ -233,7 +232,8 @@ func sendHeartbeat(ctx context.Context, h host.Host, proto protocol.ID, p *pp.Ad
pss, exists := streams[p.ID]
ctxTTL, cancel := context.WithTimeout(ctx, 3*interval)
defer cancel()
if h.Network().Connectedness(p.ID) != network.Connected {
fmt.Println(p.ID, len(h.Network().ConnsToPeer(p.ID)))
if len(h.Network().ConnsToPeer(p.ID)) == 0 {
if err := h.Connect(ctxTTL, *p); err != nil {
logger.Err(err)
return nil, 0, err
+3 -2
View File
@@ -3,12 +3,12 @@ package common
import (
"context"
"encoding/json"
"fmt"
"sort"
"time"
oclib "cloud.o-forge.io/core/oc-lib"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/network"
pp "github.com/libp2p/go-libp2p/core/peer"
)
@@ -153,7 +153,8 @@ func TriggerConsensus(h host.Host, remaining []pp.AddrInfo, need int) {
func probeIndexer(h host.Host, ai pp.AddrInfo) (*HeartbeatResponse, time.Duration, error) {
ctx, cancel := context.WithTimeout(context.Background(), 8*time.Second)
defer cancel()
if h.Network().Connectedness(ai.ID) != network.Connected {
fmt.Println(ai.ID, len(h.Network().ConnsToPeer(ai.ID)))
if len(h.Network().ConnsToPeer(ai.ID)) == 0 {
if err := h.Connect(ctx, ai); err != nil {
return nil, 0, err
}
+40 -2
View File
@@ -39,6 +39,8 @@ type PeerRecordPayload struct {
PubKey []byte `json:"public_key"`
ExpiryDate time.Time `json:"expiry_date"`
IsNano bool `json:"is_nano"`
// MasterID is the libp2p PeerID of this peer's MASTER, self-attested and signed.
MasterID string `json:"master_id,omitempty"`
// TTLSeconds is the publisher's declared lifetime for this record in seconds.
// 0 means "use the default (120 s)". Included in the signed payload so it
// cannot be altered by an intermediary.
@@ -105,6 +107,7 @@ func (pr *PeerRecord) ExtractPeer(ourkey string, key string, pubKey crypto.PubKe
NATSAddress: pr.NATSAddress,
WalletAddress: pr.WalletAddress,
Location: pr.Location,
MasterID: pr.MasterID,
}
if time.Now().UTC().After(pr.ExpiryDate) {
return pp.SELF == p.Relation, nil, errors.New("peer " + key + " is offline")
@@ -285,6 +288,20 @@ func (ix *IndexerService) initNodeHandler() {
}
cancel2()
}
// PendingContact: update inverted index — for each target peer in the list,
// record that hb.PeerID wants to contact it. Entries expire after 3 heartbeat
// intervals so stale callers are cleaned up automatically if they stop advertising.
if len(hb.PendingContact) > 0 {
expiry := time.Now().Add(3 * 20 * time.Second)
ix.pendingContactIndexMu.Lock()
for _, targetID := range hb.PendingContact {
if ix.pendingContactIndex[targetID] == nil {
ix.pendingContactIndex[targetID] = map[string]time.Time{}
}
ix.pendingContactIndex[targetID][hb.PeerID] = expiry
}
ix.pendingContactIndexMu.Unlock()
}
}
ix.Host.SetStreamHandler(common.ProtocolHeartbeat, ix.HandleHeartbeat)
ix.Host.SetStreamHandler(common.ProtocolPublish, ix.handleNodePublish)
@@ -351,7 +368,8 @@ func (ix *IndexerService) handleNodePublish(s network.Stream) {
}
continue
}
if _, err := rec.Verify(); err != nil {
pubKey, err := rec.Verify()
if err != nil {
ix.behavior.RecordBadSignature(remotePeer)
logger.Warn().Err(err).Str("peer", remotePeer.String()).Msg("bad signature on publish")
return
@@ -369,6 +387,26 @@ func (ix *IndexerService) handleNodePublish(s network.Stream) {
if err != nil {
return
}
// Chain of trust: PubKey → PeerID (libp2p invariant), then transport identity.
// This prevents a peer from publishing a record on behalf of someone else.
if derivedID, err := lpp.IDFromPublicKey(pubKey); err != nil || derivedID != pid {
ix.behavior.RecordBadSignature(remotePeer)
logger.Warn().Str("peer", remotePeer.String()).Msg("PubKey/PeerID mismatch on publish")
s.Reset()
return
}
if remotePeer != pid {
ix.behavior.RecordBadSignature(remotePeer)
logger.Warn().Str("remote", remotePeer.String()).Str("claimed", pid.String()).Msg("transport identity mismatch on publish")
s.Reset()
return
}
if rec.StreamAddress != "" && !strings.HasSuffix(rec.StreamAddress, "/p2p/"+rec.PeerID) {
ix.behavior.RecordBadSignature(remotePeer)
logger.Warn().Str("peer", remotePeer.String()).Msg("StreamAddress/PeerID mismatch on publish")
s.Reset()
return
}
ix.StreamMU.Lock()
defer ix.StreamMU.Unlock()
@@ -566,7 +604,7 @@ func (ix *IndexerService) handleIndirectProbe(s network.Stream) {
// Connect to target if not already connected.
ctx, cancel := context.WithTimeout(context.Background(), 6*time.Second)
defer cancel()
if ix.Host.Network().Connectedness(req.Target.ID) != network.Connected {
if len(ix.Host.Network().ConnsToPeer(req.Target.ID)) == 0 {
if err := ix.Host.Connect(ctx, req.Target); err != nil {
respond(false, 0)
return
+24
View File
@@ -79,6 +79,11 @@ type IndexerService struct {
// eventQueue holds SWIM membership events to be piggybacked on responses
// (infection-style dissemination toward connected nodes).
eventQueue *common.MembershipEventQueue
// pendingContactIndex is an inverted index built from Heartbeat.PendingContact.
// Maps target peer ID → { caller peer ID → expiry time }.
// Returned in HeartbeatResponse.PendingCallers when the target reconnects.
pendingContactIndex map[string]map[string]time.Time
pendingContactIndexMu sync.Mutex
}
// NewIndexerService creates an IndexerService.
@@ -95,6 +100,7 @@ func NewIndexerService(h host.Host, ps *pubsub.PubSub, maxNode int) *IndexerServ
behavior: newNodeBehaviorTracker(),
deletedDIDs: make(map[string]time.Time),
eventQueue: &common.MembershipEventQueue{},
pendingContactIndex: map[string]map[string]time.Time{},
}
if ps == nil {
ps, err = pubsub.NewGossipSub(context.Background(), ix.Host)
@@ -408,6 +414,24 @@ func NewIndexerService(h host.Host, ps *pubsub.PubSub, maxNode int) *IndexerServ
resp.Incarnation = ix.incarnation.Load()
resp.MembershipEvents = ix.eventQueue.Drain(5)
// PendingCallers: look up who has undelivered messages for this node.
// Clean up expired entries at the same time.
ix.pendingContactIndexMu.Lock()
if callers, ok := ix.pendingContactIndex[remotePeer.String()]; ok {
now := time.Now()
for callerID, exp := range callers {
if now.Before(exp) {
resp.PendingCallers = append(resp.PendingCallers, callerID)
} else {
delete(callers, callerID)
}
}
if len(callers) == 0 {
delete(ix.pendingContactIndex, remotePeer.String())
}
}
ix.pendingContactIndexMu.Unlock()
return resp
}
+32 -3
View File
@@ -10,6 +10,7 @@ import (
oclib "cloud.o-forge.io/core/oc-lib"
"cloud.o-forge.io/core/oc-lib/config"
"cloud.o-forge.io/core/oc-lib/dbs"
pp_model "cloud.o-forge.io/core/oc-lib/models/peer"
"cloud.o-forge.io/core/oc-lib/tools"
pp "github.com/libp2p/go-libp2p/core/peer"
@@ -51,11 +52,13 @@ func ListenNATS(n *Node) {
}
if err == nil {
switch propalgation.Action {
case tools.PB_ADMIRALTY_CONFIG, tools.PB_MINIO_CONFIG:
case tools.PB_ADMIRALTY_CONFIG, tools.PB_MINIO_CONFIG, tools.PB_SOURCE_PRESIGN:
var m configPayload
var proto protocol.ID = stream.ProtocolAdmiraltyConfigResource
if propalgation.Action == tools.PB_MINIO_CONFIG {
proto = stream.ProtocolMinioConfigResource
} else if propalgation.Action == tools.PB_SOURCE_PRESIGN {
proto = stream.ProtocolSourcePresignResource
}
if err := json.Unmarshal(propalgation.Payload, &m); err == nil {
peers, _ := n.GetPeerRecord(context.Background(), m.PeerID)
@@ -68,9 +71,33 @@ func ListenNATS(n *Node) {
if slices.Contains([]tools.DataType{tools.BOOKING, tools.PURCHASE_RESOURCE}, resp.Datatype) {
m := map[string]interface{}{}
if err := json.Unmarshal(propalgation.Payload, &m); err == nil {
delivered := false
if m["peer_id"] != nil {
n.StreamService.PublishCommon(&resp.Datatype, resp.User, resp.Groups,
_, err := n.StreamService.PublishCommon(&resp.Datatype, resp.User, resp.Groups,
fmt.Sprintf("%v", m["peer_id"]), stream.ProtocolCreateResource, propalgation.Payload)
delivered = err == nil
}
if !delivered {
// NANO unreachable — look up its MasterID from the DB record.
// The NANO self-attests its MASTER in its signed PeerRecord;
// if MasterID is set we forward there, otherwise we drop silently.
var destStruct struct {
DestPeerID string `json:"dest_peer_id"`
}
if json.Unmarshal(propalgation.Payload, &destStruct) == nil && destStruct.DestPeerID != "" {
d := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil).Search(&dbs.Filters{
And: map[string][]dbs.Filter{
"id": {{Operator: dbs.EQUAL.String(), Value: destStruct.DestPeerID}},
},
}, "", false, 0, 1)
if len(d.Data) > 0 {
nano := d.Data[0].(*pp_model.Peer)
if nano.MasterID != "" {
n.StreamService.PublishCommon(&resp.Datatype, resp.User, resp.Groups,
nano.MasterID, stream.ProtocolCreateResource, propalgation.Payload)
}
}
}
}
}
} else {
@@ -150,6 +177,7 @@ func ListenNATS(n *Node) {
// Re-emit on PEER_OBSERVE_RESPONSE_EVENT so the local oc-peer sees it.
tools.NewNATSCaller().SetNATSPub(tools.PEER_OBSERVE_RESPONSE_EVENT, tools.NATSResponse{
FromApp: resp.FromApp,
User: resp.User,
Datatype: tools.PEER,
Method: int(tools.PEER_OBSERVE_RESPONSE_EVENT),
Payload: propalgation.Payload,
@@ -183,7 +211,7 @@ func ListenNATS(n *Node) {
} else {
m := map[string]interface{}{}
if err := json.Unmarshal(propalgation.Payload, &m); err == nil {
fmt.Println("PB_SEARCH CATA", m)
fmt.Println("PB_SEARCH CATA", m, resp.User)
n.PubSubService.SearchPublishEvent(
context.Background(),
@@ -256,6 +284,7 @@ func handlePeerBehaviorEvent(n *Node, resp tools.NATSResponse) {
if b, err := json.Marshal(p.Serialize(p)); err == nil {
tools.NewNATSCaller().SetNATSPub(tools.CREATE_RESOURCE, tools.NATSResponse{
FromApp: "oc-discovery",
User: resp.User,
Datatype: tools.PEER,
Method: int(tools.CREATE_RESOURCE),
Payload: b,
+23 -2
View File
@@ -123,8 +123,25 @@ func InitNode(isNode bool, isIndexer bool) (*Node, error) {
b, _ := json.Marshal(fresh)
return json.RawMessage(b)
}
// streamSvcRef is set after InitStream below; the heartbeat goroutine
// first fires after 20 s so it is always non-nil by then.
var streamSvcRef *stream.StreamService
logger.Info().Msg("connect to indexers...")
common.ConnectToIndexers(node.Host, conf.GetConfig().MinIndexer, conf.GetConfig().MaxIndexer, buildRecord)
common.ConnectToIndexers(node.Host, conf.GetConfig().MinIndexer, conf.GetConfig().MaxIndexer,
common.HeartbeatHooks{
RecordFn: buildRecord,
PendingContactFn: func() []string {
if streamSvcRef != nil {
return streamSvcRef.PendingContacts()
}
return nil
},
OnPendingCallers: func(callers []string) {
if streamSvcRef != nil {
streamSvcRef.NudgeContacts(callers)
}
},
})
logger.Info().Msg("claims my node...")
if _, err := node.claimInfo(conf.GetConfig().Name, conf.GetConfig().Hostname); err != nil {
panic(err)
@@ -135,6 +152,7 @@ func InitNode(isNode bool, isIndexer bool) (*Node, error) {
if node.StreamService, err = stream.InitStream(context.Background(), node.Host, node.PeerID, 1000, node); err != nil {
panic(err)
}
streamSvcRef = node.StreamService
node.StreamService.IsPeerKnown = func(pid pp.ID) bool {
// 1. Local DB: known peer (handles blacklist).
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
@@ -178,7 +196,7 @@ func InitNode(isNode bool, isIndexer bool) (*Node, error) {
}
fmt.Println("PUBSUB SendResponse bef peerrece")
if p, err := node.GetPeerRecord(ctx, evt.From); err == nil && len(p) > 0 && m["search"] != nil {
fmt.Println("PUBSUB SendResponse af peerrece", m)
fmt.Println("PUBSUB SendResponse af peerrece", m, evt.User)
node.StreamService.SendResponse(p[0], &evt, fmt.Sprintf("%v", m["search"]))
}
}
@@ -411,8 +429,10 @@ func (d *Node) claimInfo(
"peer_id": {{Operator: dbs.EQUAL.String(), Value: d.Host.ID().String()}},
},
}, "", false, 0, 1)
var masterID string
if len(peers.Data) > 0 {
did = peers.Data[0].GetID() // if already existing set up did as made
masterID = peers.Data[0].(*peer.Peer).MasterID
}
priv, err := tools.LoadKeyFromFilePrivate()
if err != nil {
@@ -434,6 +454,7 @@ func (d *Node) claimInfo(
PubKey: pubBytes,
IsNano: oclib.GetConfig().IsNano,
MasterID: masterID,
TTLSeconds: indexer.DefaultTTLSeconds,
ExpiryDate: now.Add(indexer.DefaultTTLSeconds * time.Second),
}
+1 -1
View File
@@ -49,7 +49,7 @@ func (ps *PubSubService) SearchPublishEvent(
// remote peers echo it back unchanged, allowing IsActive to validate results.
searchKey := ps.StreamService.ResourceSearches.Register(user, cancel, idleTimeout)
fmt.Println("PUBLISH ON PUBSUB", common.TopicPubSubSearch, searchKey)
return ps.publishEvent(searchCtx, dt, tools.PB_SEARCH, common.TopicPubSubSearch, searchKey, b)
return ps.publishEvent(searchCtx, dt, tools.PB_SEARCH, common.TopicPubSubSearch, user, b)
default:
return errors.New("no type of research found")
}
-362
View File
@@ -1,362 +0,0 @@
package stream
// dnt_cache.go — Disconnection Network Tolerance cache for outbound stream requests.
//
// When a stream write fails because the remote peer is unreachable, the request
// is saved here and retried on the next tick. Two levels are defined:
//
// - dntCritical : retry indefinitely (create / update / delete resource).
// - dntModerate : up to dntMaxModerateRetries retries, then abandon.
//
// Pubsub messages and search streams are explicitly excluded.
// Streams initiated from the indexer side are never enqueued here.
//
// # Crash-resilient persistence
//
// Critical entries are written to an encrypted file (AES-256-GCM) so they
// survive a node crash/restart. The AES key is derived deterministically from
// the node's Ed25519 private key via HKDF-SHA256 — no extra secret to manage.
// Moderate entries are intentionally not persisted: their retry budget is small
// enough that re-loading them after a restart would be misleading.
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha256"
"encoding/json"
"io"
"os"
"path/filepath"
"sync"
"time"
oclib "cloud.o-forge.io/core/oc-lib"
"cloud.o-forge.io/core/oc-lib/tools"
"golang.org/x/crypto/hkdf"
"oc-discovery/conf"
pp "github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/protocol"
)
type dntLevel int
const (
dntCritical dntLevel = iota // retry until the message is delivered
dntModerate // retry up to dntMaxModerateRetries times
)
const dntMaxModerateRetries = 3
const dntRetryInterval = 15 * time.Second
// dntProtocols maps each stream protocol to its DNT level.
// Protocols absent from this map receive no caching (e.g. ProtocolSearchResource).
var dntProtocols = map[protocol.ID]dntLevel{
// Critical — data mutations that must eventually be delivered.
ProtocolCreateResource: dntCritical,
ProtocolUpdateResource: dntCritical,
ProtocolDeleteResource: dntCritical,
// Moderate — confirmations / config / planner: 3 retries before abandon.
ProtocolVerifyResource: dntModerate,
ProtocolSendPlanner: dntModerate,
ProtocolConsidersResource: dntModerate,
ProtocolMinioConfigResource: dntModerate,
ProtocolAdmiraltyConfigResource: dntModerate,
}
// dntEntryJSON is the on-disk representation of a dntEntry.
// pp.AddrInfo and protocol.ID don't have built-in JSON tags so we flatten them.
type dntEntryJSON struct {
DID string `json:"did"`
Addr pp.AddrInfo `json:"addr"`
DT *tools.DataType `json:"dt,omitempty"`
User string `json:"user"`
Payload []byte `json:"payload"`
Proto protocol.ID `json:"proto"`
Retries int `json:"retries"`
AddedAt time.Time `json:"added_at"`
}
type dntEntry struct {
did string
addr pp.AddrInfo
dt *tools.DataType
user string
payload []byte
proto protocol.ID
retries int
addedAt time.Time
}
func (e *dntEntry) toJSON() dntEntryJSON {
return dntEntryJSON{
DID: e.did,
Addr: e.addr,
DT: e.dt,
User: e.user,
Payload: e.payload,
Proto: e.proto,
Retries: e.retries,
AddedAt: e.addedAt,
}
}
func entryFromJSON(j dntEntryJSON) *dntEntry {
return &dntEntry{
did: j.DID,
addr: j.Addr,
dt: j.DT,
user: j.User,
payload: j.Payload,
proto: j.Proto,
retries: j.Retries,
addedAt: j.AddedAt,
}
}
type dntCache struct {
mu sync.Mutex
entries []*dntEntry
// aesKey is the derived AES-256 key used for on-disk encryption.
// Nil when key derivation failed: persistence is disabled but the in-memory
// cache continues to function normally.
aesKey []byte
}
// newDNTCache initialises the cache, derives the encryption key, and restores
// any critical entries that were persisted before the last crash.
func newDNTCache() *dntCache {
log := oclib.GetLogger()
c := &dntCache{}
key, err := deriveDNTKey()
if err != nil {
log.Warn().Err(err).Msg("[dnt] key derivation failed — persistence disabled")
} else {
c.aesKey = key
c.loadFromDisk()
}
return c
}
// enqueue adds an entry to the cache and persists critical entries to disk.
func (c *dntCache) enqueue(e *dntEntry) {
c.mu.Lock()
c.entries = append(c.entries, e)
c.mu.Unlock()
if dntProtocols[e.proto] == dntCritical {
go c.persistToDisk()
}
}
// drain atomically removes and returns all current entries.
func (c *dntCache) drain() []*dntEntry {
c.mu.Lock()
defer c.mu.Unlock()
out := c.entries
c.entries = nil
return out
}
// requeue puts entries back at the head of the list, preserving any new
// entries added while the retry loop was running.
func (c *dntCache) requeue(entries []*dntEntry) {
if len(entries) == 0 {
return
}
c.mu.Lock()
defer c.mu.Unlock()
c.entries = append(entries, c.entries...)
}
// ── Persistence ──────────────────────────────────────────────────────────────
// dntCachePath returns the path of the on-disk cache file, placed next to the
// node's private key so it lives on the same persistent volume.
func dntCachePath() string {
return filepath.Join(filepath.Dir(conf.GetConfig().PrivateKeyPath), "dnt_cache.bin")
}
// deriveDNTKey derives a 32-byte AES key from the node's Ed25519 private key
// using HKDF-SHA256. The derivation is deterministic: the same key is always
// produced from the same private key, so no symmetric secret needs storing.
func deriveDNTKey() ([]byte, error) {
priv, err := tools.LoadKeyFromFilePrivate()
if err != nil {
return nil, err
}
// Raw() on a libp2p Ed25519 private key returns the 64-byte representation
// (32-byte seed || 32-byte public key). We use the full 64 bytes as IKM.
raw, err := priv.Raw()
if err != nil {
return nil, err
}
reader := hkdf.New(sha256.New, raw, nil, []byte("oc-discovery/dnt-cache/v1"))
key := make([]byte, 32)
if _, err := io.ReadFull(reader, key); err != nil {
return nil, err
}
return key, nil
}
// persistToDisk encrypts all current critical entries and writes them to disk.
// Non-critical entries are deliberately excluded — they are not worth restoring
// after a restart given their limited retry budget.
func (c *dntCache) persistToDisk() {
if c.aesKey == nil {
return
}
log := oclib.GetLogger()
c.mu.Lock()
var toSave []dntEntryJSON
for _, e := range c.entries {
if dntProtocols[e.proto] == dntCritical {
toSave = append(toSave, e.toJSON())
}
}
c.mu.Unlock()
plaintext, err := json.Marshal(toSave)
if err != nil {
return
}
block, err := aes.NewCipher(c.aesKey)
if err != nil {
return
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return
}
nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return
}
ciphertext := gcm.Seal(nonce, nonce, plaintext, nil)
path := dntCachePath()
tmp := path + ".tmp"
if err := os.WriteFile(tmp, ciphertext, 0600); err != nil {
log.Warn().Err(err).Msg("[dnt] failed to write cache file")
return
}
if err := os.Rename(tmp, path); err != nil {
log.Warn().Err(err).Msg("[dnt] failed to rename cache file")
_ = os.Remove(tmp)
}
}
// loadFromDisk decrypts the on-disk cache and re-enqueues only critical entries.
// Errors (missing file, decryption failure) are non-fatal: the cache simply
// starts empty, which is safe.
func (c *dntCache) loadFromDisk() {
if c.aesKey == nil {
return
}
log := oclib.GetLogger()
path := dntCachePath()
data, err := os.ReadFile(path)
if err != nil {
if !os.IsNotExist(err) {
log.Warn().Err(err).Msg("[dnt] failed to read cache file")
}
return
}
block, err := aes.NewCipher(c.aesKey)
if err != nil {
return
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return
}
if len(data) < gcm.NonceSize() {
log.Warn().Msg("[dnt] cache file too short, ignoring")
return
}
nonce, ciphertext := data[:gcm.NonceSize()], data[gcm.NonceSize():]
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
log.Warn().Err(err).Msg("[dnt] cache file decryption failed (key mismatch?), ignoring")
return
}
var saved []dntEntryJSON
if err := json.Unmarshal(plaintext, &saved); err != nil {
log.Warn().Err(err).Msg("[dnt] cache file unmarshal failed, ignoring")
return
}
count := 0
for _, j := range saved {
// Only restore critical entries — moderate entries are intentionally
// not persisted, but this guard defends against format changes.
if dntProtocols[j.Proto] != dntCritical {
continue
}
c.entries = append(c.entries, entryFromJSON(j))
count++
}
if count > 0 {
log.Info().Int("count", count).Msg("[dnt] restored critical entries from disk")
}
}
// ── Retry loop ────────────────────────────────────────────────────────────────
// startDNTLoop runs the background retry goroutine. Call once after init.
func (s *StreamService) startDNTLoop() {
logger := oclib.GetLogger()
ticker := time.NewTicker(dntRetryInterval)
defer ticker.Stop()
for range ticker.C {
entries := s.dnt.drain()
if len(entries) == 0 {
continue
}
var keep []*dntEntry
for _, e := range entries {
_, err := s.write(e.did, &e.addr, e.dt, e.user, e.payload, e.proto)
if err == nil {
level := dntProtocols[e.proto]
if level == dntCritical {
logger.Info().
Str("proto", string(e.proto)).
Str("peer", e.did).
Msg("[dnt] critical message delivered after retry")
} else {
logger.Info().
Str("proto", string(e.proto)).
Str("peer", e.did).
Int("retries", e.retries).
Msg("[dnt] moderate message delivered after retry")
}
continue
}
level := dntProtocols[e.proto]
switch level {
case dntCritical:
keep = append(keep, e)
case dntModerate:
e.retries++
if e.retries < dntMaxModerateRetries {
keep = append(keep, e)
} else {
logger.Warn().
Str("proto", string(e.proto)).
Str("peer", e.did).
Int("retries", e.retries).
Msg("[dnt] moderate message abandoned after max retries")
}
}
}
s.dnt.requeue(keep)
// Persist after each tick so the on-disk file reflects the current
// state (entries delivered are removed, new ones from concurrent
// enqueues are included).
go s.dnt.persistToDisk()
}
}
+446
View File
@@ -0,0 +1,446 @@
package stream
// DTN_cache.go — Disconnection Network Tolerance cache for outbound stream requests.
//
// When a stream write fails because the remote peer is unreachable, the request
// is saved here and retried on the next tick. Two levels are defined:
//
// - DTNCritical : retry indefinitely (create / update / delete resource).
// - DTNModerate : up to DTNMaxModerateRetries retries, then abandon.
//
// Pubsub messages and search streams are explicitly excluded.
// Streams initiated from the indexer side are never enqueued here.
//
// # Crash-resilient persistence
//
// Critical entries are written to an encrypted file (AES-256-GCM) so they
// survive a node crash/restart. The AES key is derived deterministically from
// the node's Ed25519 private key via HKDF-SHA256 — no extra secret to manage.
// Moderate entries are intentionally not persisted: their retry budget is small
// enough that re-loading them after a restart would be misleading.
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha256"
"encoding/json"
"io"
"os"
"path/filepath"
"sync"
"time"
oclib "cloud.o-forge.io/core/oc-lib"
"cloud.o-forge.io/core/oc-lib/tools"
"golang.org/x/crypto/hkdf"
"oc-discovery/conf"
pp "github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/protocol"
)
type DTNLevel int
const (
DTNCritical DTNLevel = iota // retry until the message is delivered
DTNModerate // retry up to DTNMaxModerateRetries times
)
const DTNMaxModerateRetries = 3
const DTNRetryInterval = 15 * time.Second
// DTNProtocols maps each stream protocol to its DTN level.
// Protocols absent from this map receive no caching (e.g. ProtocolSearchResource).
var DTNProtocols = map[protocol.ID]DTNLevel{
// Critical — data mutations that must eventually be delivered.
ProtocolCreateResource: DTNCritical,
ProtocolUpdateResource: DTNCritical,
ProtocolDeleteResource: DTNCritical,
// Moderate — confirmations / config / planner: 3 retries before abandon.
ProtocolVerifyResource: DTNModerate,
ProtocolSendPlanner: DTNModerate,
ProtocolConsidersResource: DTNModerate,
ProtocolMinioConfigResource: DTNModerate,
ProtocolAdmiraltyConfigResource: DTNModerate,
ProtocolSourcePresignResource: DTNModerate,
}
// DTNEntryJSON is the on-disk representation of a DTNEntry.
// pp.AddrInfo and protocol.ID don't have built-in JSON tags so we flatten them.
type DTNEntryJSON struct {
DID string `json:"did"`
ResourceID string `json:"resource_id,omitempty"`
ForceCritical bool `json:"force_critical,omitempty"`
Addr pp.AddrInfo `json:"addr"`
DT *tools.DataType `json:"dt,omitempty"`
User string `json:"user"`
Payload []byte `json:"payload"`
Proto protocol.ID `json:"proto"`
Retries int `json:"retries"`
AddedAt time.Time `json:"added_at"`
}
type DTNEntry struct {
did string
resourceID string // UUID of the resource; empty for non-resource payloads (planner, config)
forceCritical bool // true when destination is NANO: all protocols become critical
addr pp.AddrInfo
dt *tools.DataType
user string
payload []byte
proto protocol.ID
retries int
addedAt time.Time
}
// isEffectivelyCritical returns true when the entry must be retried indefinitely,
// either because its protocol is inherently critical or because the destination
// is a NANO peer (forceCritical).
func (e *DTNEntry) isEffectivelyCritical() bool {
return DTNProtocols[e.proto] == DTNCritical || e.forceCritical
}
func (e *DTNEntry) toJSON() DTNEntryJSON {
return DTNEntryJSON{
DID: e.did,
ResourceID: e.resourceID,
ForceCritical: e.forceCritical,
Addr: e.addr,
DT: e.dt,
User: e.user,
Payload: e.payload,
Proto: e.proto,
Retries: e.retries,
AddedAt: e.addedAt,
}
}
func entryFromJSON(j DTNEntryJSON) *DTNEntry {
return &DTNEntry{
did: j.DID,
resourceID: j.ResourceID,
forceCritical: j.ForceCritical,
addr: j.Addr,
dt: j.DT,
user: j.User,
payload: j.Payload,
proto: j.Proto,
retries: j.Retries,
addedAt: j.AddedAt,
}
}
type DTNCache struct {
mu sync.Mutex
entries []*DTNEntry
// aesKey is the derived AES-256 key used for on-disk encryption.
// Nil when key derivation failed: persistence is disabled but the in-memory
// cache continues to function normally.
aesKey []byte
}
// newDNTCache initialises the cache, derives the encryption key, and restores
// any critical entries that were persisted before the last crash.
func newDNTCache() *DTNCache {
log := oclib.GetLogger()
c := &DTNCache{}
key, err := deriveDNTKey()
if err != nil {
log.Warn().Err(err).Msg("[dnt] key derivation failed — persistence disabled")
} else {
c.aesKey = key
c.loadFromDisk()
}
return c
}
// extractResourceID returns the "id" field from a JSON resource payload.
// Returns "" when the payload is not a resource object (planner, config, etc.).
func extractResourceID(payload []byte) string {
var obj struct {
ID string `json:"id"`
}
if err := json.Unmarshal(payload, &obj); err != nil {
return ""
}
return obj.ID
}
// enqueue adds an entry to the cache, respecting the resource lifecycle.
// Deduplication key is (did, resourceID): same resource to the same peer keeps
// only the latest mutation. resourceID is empty for non-resource payloads
// (planner, config), in which case deduplication falls back to did alone.
//
// - DELETE is terminal: any subsequent mutation on the same key is discarded.
// - UPDATE cannot be followed by CREATE: the resource already exists remotely.
// - All other cases replace the existing entry (newer mutation supersedes).
func (c *DTNCache) enqueue(e *DTNEntry) {
c.mu.Lock()
found, mutated := false, false
for i, existing := range c.entries {
if existing.did != e.did || existing.resourceID != e.resourceID {
continue
}
found = true
if existing.proto == ProtocolDeleteResource ||
(existing.proto == ProtocolUpdateResource && e.proto == ProtocolCreateResource) {
break // discard new entry silently — existing state is authoritative
}
c.entries[i] = e
mutated = true
break
}
if !found {
c.entries = append(c.entries, e)
mutated = true
}
c.mu.Unlock()
if mutated && e.isEffectivelyCritical() {
go c.persistToDisk()
}
}
// peersWithPending returns the distinct peer IDs (did) that have at least one
// critical entry in the cache. Used to populate Heartbeat.PendingContact.
func (c *DTNCache) peersWithPending() []string {
c.mu.Lock()
defer c.mu.Unlock()
seen := map[string]struct{}{}
var out []string
for _, e := range c.entries {
if e.isEffectivelyCritical() {
if _, ok := seen[e.did]; !ok {
seen[e.did] = struct{}{}
out = append(out, e.did)
}
}
}
return out
}
// drain atomically removes and returns all current entries.
func (c *DTNCache) drain() []*DTNEntry {
c.mu.Lock()
defer c.mu.Unlock()
out := c.entries
c.entries = nil
return out
}
// requeue puts entries back at the head of the list, preserving any new
// entries added while the retry loop was running.
func (c *DTNCache) requeue(entries []*DTNEntry) {
if len(entries) == 0 {
return
}
c.mu.Lock()
defer c.mu.Unlock()
c.entries = append(entries, c.entries...)
}
// ── Persistence ──────────────────────────────────────────────────────────────
// DTNCachePath returns the path of the on-disk cache file, placed next to the
// node's private key so it lives on the same persistent volume.
func DTNCachePath() string {
return filepath.Join(filepath.Dir(conf.GetConfig().PrivateKeyPath), "dnt_cache.bin")
}
// deriveDNTKey derives a 32-byte AES key from the node's Ed25519 private key
// using HKDF-SHA256. The derivation is deterministic: the same key is always
// produced from the same private key, so no symmetric secret needs storing.
func deriveDNTKey() ([]byte, error) {
priv, err := tools.LoadKeyFromFilePrivate()
if err != nil {
return nil, err
}
// Raw() on a libp2p Ed25519 private key returns the 64-byte representation
// (32-byte seed || 32-byte public key). We use the full 64 bytes as IKM.
raw, err := priv.Raw()
if err != nil {
return nil, err
}
reader := hkdf.New(sha256.New, raw, nil, []byte("oc-discovery/dnt-cache/v1"))
key := make([]byte, 32)
if _, err := io.ReadFull(reader, key); err != nil {
return nil, err
}
return key, nil
}
// persistToDisk encrypts all current critical entries and writes them to disk.
// Non-critical entries are deliberately excluded — they are not worth restoring
// after a restart given their limited retry budget.
func (c *DTNCache) persistToDisk() {
if c.aesKey == nil {
return
}
log := oclib.GetLogger()
c.mu.Lock()
var toSave []DTNEntryJSON
for _, e := range c.entries {
if e.isEffectivelyCritical() {
toSave = append(toSave, e.toJSON())
}
}
c.mu.Unlock()
plaintext, err := json.Marshal(toSave)
if err != nil {
return
}
block, err := aes.NewCipher(c.aesKey)
if err != nil {
return
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return
}
nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return
}
ciphertext := gcm.Seal(nonce, nonce, plaintext, nil)
path := DTNCachePath()
tmp := path + ".tmp"
if err := os.WriteFile(tmp, ciphertext, 0600); err != nil {
log.Warn().Err(err).Msg("[dnt] failed to write cache file")
return
}
if err := os.Rename(tmp, path); err != nil {
log.Warn().Err(err).Msg("[dnt] failed to rename cache file")
_ = os.Remove(tmp)
}
}
// loadFromDisk decrypts the on-disk cache and re-enqueues only critical entries.
// Errors (missing file, decryption failure) are non-fatal: the cache simply
// starts empty, which is safe.
func (c *DTNCache) loadFromDisk() {
if c.aesKey == nil {
return
}
log := oclib.GetLogger()
path := DTNCachePath()
data, err := os.ReadFile(path)
if err != nil {
if !os.IsNotExist(err) {
log.Warn().Err(err).Msg("[dnt] failed to read cache file")
}
return
}
block, err := aes.NewCipher(c.aesKey)
if err != nil {
return
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return
}
if len(data) < gcm.NonceSize() {
log.Warn().Msg("[dnt] cache file too short, ignoring")
return
}
nonce, ciphertext := data[:gcm.NonceSize()], data[gcm.NonceSize():]
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
log.Warn().Err(err).Msg("[dnt] cache file decryption failed (key mismatch?), ignoring")
return
}
var saved []DTNEntryJSON
if err := json.Unmarshal(plaintext, &saved); err != nil {
log.Warn().Err(err).Msg("[dnt] cache file unmarshal failed, ignoring")
return
}
count := 0
for _, j := range saved {
// Only restore critical entries — moderate entries are intentionally
// not persisted, but this guard defends against format changes.
e := entryFromJSON(j)
if !e.isEffectivelyCritical() {
continue
}
c.entries = append(c.entries, e)
count++
}
if count > 0 {
log.Info().Int("count", count).Msg("[dnt] restored critical entries from disk")
}
}
// ── Retry loop ────────────────────────────────────────────────────────────────
// startDNTLoop runs the background retry goroutine. Call once after init.
func (s *StreamService) startDNTLoop() {
logger := oclib.GetLogger()
ticker := time.NewTicker(DTNRetryInterval)
defer ticker.Stop()
// retryEntries attempts delivery for the given entries and returns those
// that must be kept for the next round.
retryEntries := func(entries []*DTNEntry) []*DTNEntry {
var keep []*DTNEntry
for _, e := range entries {
_, err := s.write(e.did, &e.addr, e.dt, e.user, e.payload, e.proto)
if err == nil {
if e.isEffectivelyCritical() {
logger.Info().Str("proto", string(e.proto)).Str("peer", e.did).
Msg("[dnt] critical message delivered after retry")
} else {
logger.Info().Str("proto", string(e.proto)).Str("peer", e.did).
Int("retries", e.retries).Msg("[dnt] moderate message delivered after retry")
}
continue
}
if e.isEffectivelyCritical() {
keep = append(keep, e)
} else {
e.retries++
if e.retries < DTNMaxModerateRetries {
keep = append(keep, e)
} else {
logger.Warn().Str("proto", string(e.proto)).Str("peer", e.did).
Int("retries", e.retries).Msg("[dnt] moderate message abandoned after max retries")
}
}
}
return keep
}
for {
select {
case <-ticker.C:
entries := s.dnt.drain()
if len(entries) == 0 {
continue
}
s.dnt.requeue(retryEntries(entries))
go s.dnt.persistToDisk()
case peerID := <-s.dntNudge:
// A peer just signalled it is reachable — retry its entries immediately.
entries := s.dnt.drain()
var forPeer, other []*DTNEntry
for _, e := range entries {
if e.did == peerID {
forPeer = append(forPeer, e)
} else {
other = append(other, e)
}
}
kept := retryEntries(forPeer)
s.dnt.requeue(append(kept, other...))
if len(kept) < len(forPeer) {
go s.dnt.persistToDisk()
}
}
}
}
+92 -7
View File
@@ -15,6 +15,7 @@ import (
"cloud.o-forge.io/core/oc-lib/models/resources"
"cloud.o-forge.io/core/oc-lib/tools"
"github.com/libp2p/go-libp2p/core/network"
pp "github.com/libp2p/go-libp2p/core/peer"
)
type Verify struct {
@@ -23,8 +24,18 @@ type Verify struct {
func (ps *StreamService) handleEvent(protocol string, evt *common.Event, s network.Stream) error {
fmt.Println("handleEvent", protocol)
// Heartbeat received on an outgoing ProtocolObserve stream.
if protocol == ProtocolObserve {
// Distinguish between an open request and a close request by inspecting
// the ObserveRequest payload. The remote wraps both in a common.Event
// with Type=ProtocolObserve so the persistent readLoop can decode them.
var req ObserveRequest
if evt.Payload != nil {
json.Unmarshal(evt.Payload, &req) //nolint:errcheck — zero value means open
}
if req.Close {
ps.observeCache.cancel(s.Conn().RemotePeer().String())
return nil
}
return ps.handleIncomingObserve(s)
}
if protocol == observeHBEventType {
@@ -59,6 +70,11 @@ func (ps *StreamService) handleEvent(protocol string, evt *common.Event, s netwo
return err
}
}
if protocol == ProtocolSourcePresignResource {
if err := ps.pass(evt, tools.SOURCE_PRESIGN_EVENT); err != nil {
return err
}
}
if protocol == ProtocolAdmiraltyConfigResource {
if err := ps.pass(evt, tools.ADMIRALTY_CONFIG_EVENT); err != nil {
return err
@@ -125,9 +141,9 @@ func (abs *StreamService) sendPlanner(event *common.Event) error { //
}
func (abs *StreamService) retrieveResponse(event *common.Event) error { //
if !abs.ResourceSearches.IsActive(event.User) {
/*if !abs.ResourceSearches.IsActive(event.User) {
return nil // search already closed or timed out
}
}*/
res, err := resources.ToResource(int(event.DataType), event.Payload)
if err != nil || res == nil {
return nil
@@ -137,6 +153,7 @@ func (abs *StreamService) retrieveResponse(event *common.Event) error { //
b, err := json.Marshal(res.Serialize(res))
go tools.NewNATSCaller().SetNATSPub(tools.SEARCH_EVENT, tools.NATSResponse{
FromApp: "oc-discovery",
User: event.User,
Datatype: tools.DataType(event.DataType),
Method: int(tools.SEARCH_EVENT),
Payload: b,
@@ -147,6 +164,7 @@ func (abs *StreamService) retrieveResponse(event *common.Event) error { //
func (abs *StreamService) pass(event *common.Event, method tools.NATSMethod) error { //
go tools.NewNATSCaller().SetNATSPub(method, tools.NATSResponse{
FromApp: "oc-discovery",
User: event.User,
Datatype: tools.DataType(event.DataType),
Method: int(method),
Payload: event.Payload,
@@ -154,6 +172,36 @@ func (abs *StreamService) pass(event *common.Event, method tools.NATSMethod) err
return nil
}
// resolveBookingNano does a single DB lookup and returns:
//
// (nil, true) — not a booking, dest_peer_id absent, or dest == self → process normally, no forward
// (nano, true) — dest is one of our NANO peers → process + forward to nano
// (nil, false) — dest is unknown → ignore
func (ps *StreamService) resolveBookingNano(evt *common.Event) (*peer.Peer, bool) {
if tools.DataType(evt.DataType) != tools.BOOKING {
return nil, true
}
var b struct {
DestPeerID string `json:"dest_peer_id"`
}
if err := json.Unmarshal(evt.Payload, &b); err != nil || b.DestPeerID == "" {
return nil, true
}
if self, err := oclib.GetMySelf(); err == nil && self != nil && b.DestPeerID == self.GetID() {
return nil, true
}
d := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil).Search(&dbs.Filters{
And: map[string][]dbs.Filter{
"id": {{Operator: dbs.EQUAL.String(), Value: b.DestPeerID}},
"relation": {{Operator: dbs.EQUAL.String(), Value: peer.NANO}},
},
}, "", false, 0, 1)
if len(d.Data) == 0 {
return nil, false
}
return d.Data[0].(*peer.Peer), true
}
func (ps *StreamService) handleEventFromPartner(evt *common.Event, protocol string) error {
switch protocol {
case ProtocolSearchResource:
@@ -176,9 +224,10 @@ func (ps *StreamService) handleEventFromPartner(evt *common.Event, protocol stri
ps.SendResponse(p[0], evt, fmt.Sprintf("%v", search))
}
} else {
fmt.Println("SEND SEARCH_EVENT SetNATSPub", m)
go tools.NewNATSCaller().SetNATSPub(tools.SEARCH_EVENT, tools.NATSResponse{
fmt.Println("SEND SEARCH_EVENT SetNATSPub", m, evt.DataType, evt.User)
tools.NewNATSCaller().SetNATSPub(tools.SEARCH_EVENT, tools.NATSResponse{
FromApp: "oc-discovery",
User: evt.User,
Datatype: tools.DataType(evt.DataType),
Method: int(tools.SEARCH_EVENT),
Payload: evt.Payload,
@@ -186,19 +235,35 @@ func (ps *StreamService) handleEventFromPartner(evt *common.Event, protocol stri
}
case ProtocolCreateResource, ProtocolUpdateResource:
fmt.Println("RECEIVED Protocol.Update", string(evt.Payload))
go tools.NewNATSCaller().SetNATSPub(tools.CREATE_RESOURCE, tools.NATSResponse{
nano, ok := ps.resolveBookingNano(evt)
if !ok {
return nil
}
tools.NewNATSCaller().SetNATSPub(tools.CREATE_RESOURCE, tools.NATSResponse{
FromApp: "oc-discovery",
User: evt.User,
Datatype: tools.DataType(evt.DataType),
Method: int(tools.CREATE_RESOURCE),
Payload: evt.Payload,
})
if nano != nil {
ps.forwardToNano(nano, evt, protocol)
}
case ProtocolDeleteResource:
go tools.NewNATSCaller().SetNATSPub(tools.REMOVE_RESOURCE, tools.NATSResponse{
nano, ok := ps.resolveBookingNano(evt)
if !ok {
return nil
}
tools.NewNATSCaller().SetNATSPub(tools.REMOVE_RESOURCE, tools.NATSResponse{
FromApp: "oc-discovery",
User: evt.User,
Datatype: tools.DataType(evt.DataType),
Method: int(tools.REMOVE_RESOURCE),
Payload: evt.Payload,
})
if nano != nil {
ps.forwardToNano(nano, evt, protocol)
}
default:
return errors.New("no action authorized available : " + protocol)
}
@@ -223,11 +288,31 @@ func (abs *StreamService) SendResponse(p *peer.Peer, event *common.Event, search
access := oclib.NewRequestAdmin(oclib.LibDataEnum(dt), nil)
searched := access.Search(abs.FilterPeer(self.GetID(), event.Groups, search), "", false, 0, 0)
for _, ss := range searched.Data {
// SendResponse uses an admin request so SetAllowedInstances
// never calls FilterExploitationAuthorizations. Apply it
// explicitly here so we never leak private AEs to a remote peer.
if r, ok := ss.(resources.ResourceInterface); ok {
r.SetAllowedInstances(&tools.APIRequest{PeerID: p.UUID, Groups: event.Groups, Username: event.User})
}
if j, err := json.Marshal(ss); err == nil {
abs.PublishCommon(&dt, event.User, event.Groups, p.PeerID, ProtocolSearchResource, j)
}
}
}
}
// Close the ProtocolSearchResource stream to the requester immediately after
// sending all results. This prevents TempStream from reusing a stale (already
// closed by the remote) stream entry for a subsequent search from the same peer,
// which would cause write failure and no results for the second search.
if decodedID, err := pp.Decode(p.PeerID); err == nil {
abs.Mu.Lock()
if abs.Streams[ProtocolSearchResource] != nil {
if s, ok := abs.Streams[ProtocolSearchResource][decodedID]; ok {
s.Stream.Reset()
delete(abs.Streams[ProtocolSearchResource], decodedID)
}
}
abs.Mu.Unlock()
}
return nil
}
+176 -56
View File
@@ -27,7 +27,7 @@ const ProtocolObserve = "/opencloud/peer/observe/1.0"
// observeHBEventType is used as the common.Event.Type for heartbeat responses.
const observeHBEventType = "/opencloud/peer/observe/heartbeat"
const observeHBInterval = 30 * time.Second
const observeHBInterval = 10 * time.Second
const observeDrainDuration = 30 * time.Second
// observeBatchWindow is the accumulation window before a heartbeat batch is
@@ -46,6 +46,94 @@ type ObserveRequest struct {
// ObserveHeartbeat is sent by the observed side every observeHBInterval.
type ObserveHeartbeat struct {
State string `json:"state"` // always "online" when actively emitted
SentAt time.Time `json:"sent_at,omitempty"` // timestamp set by sender; lets receiver compute one-way latency
}
const (
maxLatencyMs = 2000.0 // ms above which latency score → 0
latencySamples = 5 // sliding window size for latency averaging
fastThresholdMs = 200.0 // below = "fast", above = "slow"
reliableThreshold = 0.95 // miss_rate below 5% = "reliable"
)
// PeerObserveMetrics accumulates connection-quality data for one observed peer.
// Updated on every incoming heartbeat (observing side).
type PeerObserveMetrics struct {
mu sync.Mutex
firstObservedAt time.Time
lastHeartbeatAt time.Time
received uint64
latencies [latencySamples]time.Duration
latIdx int
latCount int
}
func (m *PeerObserveMetrics) record(latency time.Duration) {
m.mu.Lock()
defer m.mu.Unlock()
m.received++
m.lastHeartbeatAt = time.Now().UTC()
m.latencies[m.latIdx%latencySamples] = latency
m.latIdx++
if m.latCount < latencySamples {
m.latCount++
}
}
func (m *PeerObserveMetrics) snapshot() PeerObserveSnapshot {
m.mu.Lock()
defer m.mu.Unlock()
var total time.Duration
for i := 0; i < m.latCount; i++ {
total += m.latencies[i]
}
var avgMs float64
if m.latCount > 0 {
avgMs = float64(total.Milliseconds()) / float64(m.latCount)
}
expected := int64(time.Duration(m.lastHeartbeatAt.Second()-m.firstObservedAt.Second()) / observeHBInterval)
fmt.Println("EXPECTED", expected, m.received)
var missRate float64
if expected > 0 {
recv := int64(m.received)
if recv > expected {
recv = expected
}
missRate = 1.0 - float64(recv)/float64(expected)
}
latScore := 1.0 - avgMs/maxLatencyMs
if latScore < 0 {
latScore = 0
}
relScore := 1.0 - missRate
trust := (0.35*latScore + 0.65*relScore) * 100
speed := "fast"
if avgMs >= fastThresholdMs {
speed = "slow"
}
reliability := "reliable"
if relScore < reliableThreshold {
reliability = "watch"
}
return PeerObserveSnapshot{
LatencyMs: avgMs,
Speed: speed,
Reliability: reliability,
TrustScore: trust,
LastSeenAt: m.lastHeartbeatAt,
MissRate: missRate,
}
}
// PeerObserveSnapshot is the point-in-time quality summary sent to oc-peer via NATS.
type PeerObserveSnapshot struct {
LatencyMs float64 `json:"latency_ms"`
Speed string `json:"speed"` // "fast" | "slow"
Reliability string `json:"reliability"` // "reliable" | "watch"
TrustScore float64 `json:"trust_score"`
LastSeenAt time.Time `json:"last_seen_at"`
MissRate float64 `json:"miss_rate"`
}
// ShallowPeer is the minimal peer representation sent by oc-peer in a
@@ -204,18 +292,13 @@ func flushObserveBatch(peerIDs []string) {
// ── incoming observe handler (observed side) ──────────────────────────────────
// handleIncomingObserve is registered as the ProtocolObserve stream handler.
// It is called when a remote peer opens an observe stream to us.
// The function reads the request, validates it, then starts (or stops) the
// heartbeat goroutine and returns immediately — the goroutine owns the stream.
// handleIncomingObserve is called when a remote peer opens an observe stream
// to us (observed side). It starts a heartbeat goroutine that writes back on
// the same bidirectional rawStream — no separate reverse stream is opened.
// The goroutine stops via context cancellation (triggered by a close event
// read from rawStream) or when rawStream becomes unwritable.
func (s *StreamService) handleIncomingObserve(rawStream network.Stream) error {
remotePeerID := rawStream.Conn().RemotePeer().String()
addr := rawStream.Conn().RemoteMultiaddr().String()
ad, err := pp.AddrInfoFromString(addr + "/p2p/" + remotePeerID)
if err != nil {
fmt.Println("qndlqnl EERR", addr, err)
return err
}
log := oclib.GetLogger()
// Drain mode: reject any new observations for 30 s after a close-all.
@@ -223,13 +306,11 @@ func (s *StreamService) handleIncomingObserve(rawStream network.Stream) error {
draining := !s.drainUntil.IsZero() && time.Now().Before(s.drainUntil)
s.drainMu.RUnlock()
if draining {
rawStream.Close()
fmt.Println("Draining")
return errors.New("Draining")
return errors.New("draining")
}
// Read the observe request (with a generous deadline to avoid hangs).
// Guard: the requesting peer must not be blacklisted or be ourself.
did := ""
// Guard: the requesting peer must not be blacklisted.
access := oclib.NewRequestAdmin(oclib.LibDataEnum(oclib.PEER), nil)
res := access.Search(&dbs.Filters{
And: map[string][]dbs.Filter{
@@ -238,11 +319,9 @@ func (s *StreamService) handleIncomingObserve(rawStream network.Stream) error {
}, "", false, 0, 1)
if len(res.Data) > 0 {
p := res.Data[0].(*peer.Peer)
did = p.GetID()
if p.Relation == peer.BLACKLIST { // || p.Relation == peer.SELF
rawStream.Close()
if p.Relation == peer.BLACKLIST {
fmt.Println("CLOSE blacklist or self")
return errors.New("can't exploit blacklist or self")
return errors.New("can't observe blacklisted peer")
}
}
@@ -251,53 +330,33 @@ func (s *StreamService) handleIncomingObserve(rawStream network.Stream) error {
s.observeCache.set(remotePeerID, cancel)
fmt.Println("LOOP OBSERVE")
go func() {
defer rawStream.Close()
// Do NOT close rawStream here: the persistent readLoop (HandleResponse)
// owns rawStream's lifecycle. We only stop writing.
defer cancel()
defer s.observeCache.delete(remotePeerID)
ticker := time.NewTicker(observeHBInterval)
defer ticker.Stop()
hbPayload, _ := json.Marshal(ObserveHeartbeat{State: "online"})
evt := common.NewEvent(observeHBEventType, s.Host.ID().String(), nil, "", hbPayload)
if evt == nil {
return
}
if s.Streams, err = common.TempStream(s.Host, *ad, ProtocolObserve, did, s.Streams, protocols, &s.Mu); err == nil {
stream := s.Streams[ProtocolObserve][ad.ID]
if err := json.NewEncoder(stream.Stream).Encode(evt); err != nil {
// Moderate connectivity event: the observer is unreachable.
// The deferred calls above purge this observer from the cache.
fmt.Println("LOOP EVT ERR", err)
log.Info().
Str("observer", remotePeerID).
Err(err).
Msg("[observe] heartbeat write failed — moderate connectivity event, purging observer from cache")
return
}
buildHBEvent := func() *common.Event {
p, _ := json.Marshal(ObserveHeartbeat{State: "online", SentAt: time.Now().UTC()})
return common.NewEvent(observeHBEventType, s.Host.ID().String(), nil, "", p)
}
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
rawStream.SetWriteDeadline(time.Now().Add(5 * time.Second))
fmt.Println("LOOP EVT", evt)
var err error
if s.Streams, err = common.TempStream(s.Host, *ad, ProtocolObserve, did, s.Streams, protocols, &s.Mu); err == nil {
stream := s.Streams[ProtocolObserve][ad.ID]
if err := json.NewEncoder(stream.Stream).Encode(evt); err != nil {
// Moderate connectivity event: the observer is unreachable.
// The deferred calls above purge this observer from the cache.
fmt.Println("LOOP EVT ERR", err)
evt := buildHBEvent()
if err := json.NewEncoder(rawStream).Encode(evt); err != nil {
log.Info().
Str("observer", remotePeerID).
Err(err).
Msg("[observe] heartbeat write failed — moderate connectivity event, purging observer from cache")
Msg("[observe] heartbeat write failed — stream closed, stopping goroutine")
return
}
}
rawStream.SetWriteDeadline(time.Time{})
}
}
@@ -308,14 +367,65 @@ func (s *StreamService) handleIncomingObserve(rawStream network.Stream) error {
// ── heartbeat receiver (observing side) ───────────────────────────────────────
// handleObserveHeartbeat is called by readLoop when a heartbeat event arrives
// on an outgoing ProtocolObserve stream. It queues the peer_id in the batch
// accumulator; the batcher flushes to NATS after observeBatchWindow.
// on an outgoing ProtocolObserve stream. It updates per-peer metrics and flushes
// a quality snapshot to NATS.
func (ps *StreamService) handleObserveHeartbeat(evt *common.Event) error {
// ps.hbBatcher.add(evt.From)
flushObserveBatch([]string{evt.From})
var hb ObserveHeartbeat
if err := json.Unmarshal(evt.Payload, &hb); err == nil && !hb.SentAt.IsZero() {
latency := time.Since(hb.SentAt)
raw, _ := ps.observeMetrics.LoadOrStore(evt.From, &PeerObserveMetrics{
firstObservedAt: time.Now().UTC(),
})
raw.(*PeerObserveMetrics).record(latency)
fmt.Println("METRICS", raw)
ps.observeMetrics.Store(evt.From, raw)
}
ps.flushObserveForPeer(evt.From, evt.User)
return nil
}
// flushObserveForPeer sends a PEER_OBSERVE_RESPONSE_EVENT to NATS with a quality
// snapshot for peerID. Replaces the old flushObserveBatch (single-peer variant).
func (ps *StreamService) flushObserveForPeer(peerID string, user string) {
var snap *PeerObserveSnapshot
if raw, ok := ps.observeMetrics.Load(peerID); ok {
fmt.Println("RETRIEVED METRICS", raw)
s := raw.(*PeerObserveMetrics).snapshot()
snap = &s
}
fmt.Println("RETRIEVED METRICS 2", snap)
payload, err := json.Marshal(map[string]interface{}{
"peer_ids": []string{peerID},
"state": "online",
"metrics": map[string]*PeerObserveSnapshot{peerID: snap},
})
if err != nil {
return
}
tools.NewNATSCaller().SetNATSPub(tools.PEER_OBSERVE_RESPONSE_EVENT, tools.NATSResponse{
FromApp: "oc-discovery",
Datatype: tools.PEER,
User: user,
Method: int(tools.PEER_OBSERVE_RESPONSE_EVENT),
Payload: payload,
})
propPayload, err := json.Marshal(tools.PropalgationMessage{
DataType: int(tools.PEER),
Action: tools.PB_PROPAGATE,
Payload: payload,
})
if err != nil {
return
}
tools.NewNATSCaller().SetNATSPub(tools.PROPALGATION_EVENT, tools.NATSResponse{
FromApp: "oc-discovery",
Datatype: tools.PEER,
User: user,
Method: int(tools.PROPALGATION_EVENT),
Payload: propPayload,
})
}
// ── user→peer index (ref-counted observe management) ─────────────────────────
// userPeerIndex tracks which users are observing which peers.
@@ -514,7 +624,8 @@ func (ps *StreamService) openObserveStream(p ShallowPeer) error {
}
// closeObserveStream closes the ProtocolObserve stream to toPeerID and notifies
// the remote side.
// the remote side. The close event is wrapped in a common.Event so the remote's
// persistent readLoop can decode and handle it (cancel the heartbeat goroutine).
func (ps *StreamService) closeObserveStream(toPeerID string) error {
decodedID, err := pp.Decode(toPeerID)
if err != nil {
@@ -523,12 +634,15 @@ func (ps *StreamService) closeObserveStream(toPeerID string) error {
ps.Mu.Lock()
if ps.Streams[ProtocolObserve] != nil {
if s, ok := ps.Streams[ProtocolObserve][decodedID]; ok {
_ = json.NewEncoder(s.Stream).Encode(ObserveRequest{Close: true})
closePayload, _ := json.Marshal(ObserveRequest{Close: true})
closeEvt := common.NewEvent(ProtocolObserve, ps.Host.ID().String(), nil, "", closePayload)
_ = json.NewEncoder(s.Stream).Encode(closeEvt)
s.Stream.Close()
delete(ps.Streams[ProtocolObserve], decodedID)
}
}
ps.Mu.Unlock()
ps.observeMetrics.Delete(toPeerID)
return nil
}
@@ -537,7 +651,9 @@ func (ps *StreamService) closeObserveStream(toPeerID string) error {
func (ps *StreamService) CloseAllObserves() {
ps.Mu.Lock()
for _, s := range ps.Streams[ProtocolObserve] {
_ = json.NewEncoder(s.Stream).Encode(ObserveRequest{Close: true})
closePayload, _ := json.Marshal(ObserveRequest{Close: true})
closeEvt := common.NewEvent(ProtocolObserve, ps.Host.ID().String(), nil, "", closePayload)
_ = json.NewEncoder(s.Stream).Encode(closeEvt)
s.Stream.Close()
}
delete(ps.Streams, ProtocolObserve)
@@ -545,6 +661,10 @@ func (ps *StreamService) CloseAllObserves() {
// Reset user index so stale ref-counts don't block future opens.
ps.observeUsers = newUserPeerIndex()
ps.observeMetrics.Range(func(k, _ any) bool {
ps.observeMetrics.Delete(k)
return true
})
ps.drainMu.Lock()
ps.drainUntil = time.Now().Add(observeDrainDuration)
+33 -6
View File
@@ -61,9 +61,11 @@ func (ps *StreamService) PublishCommon(dt *tools.DataType, user string, groups [
}
stream, err := ps.write(toPeerID, ad, dt, user, resource, proto)
if err != nil {
if _, ok := dntProtocols[proto]; ok {
ps.dnt.enqueue(&dntEntry{
if _, ok := DTNProtocols[proto]; ok {
ps.dnt.enqueue(&DTNEntry{
did: toPeerID,
resourceID: extractResourceID(resource),
forceCritical: pe.Relation == peer.NANO,
addr: *ad,
dt: dt,
user: user,
@@ -125,20 +127,45 @@ func (ps *StreamService) ToPartnerPublishEvent(
return nil
}
ks := []protocol.ID{}
for k := range protocolsPartners {
ks = append(ks, k)
// Extract creator_id to route to the correct nano.
// A master must only forward a resource to the nano that owns it.
var creatorID string
var minPayload struct {
CreatorID string `json:"creator_id"`
}
for _, rel := range []peer.PeerRelation{peer.PARTNER, peer.MASTER, peer.NANO} {
if json.Unmarshal(payload, &minPayload) == nil {
creatorID = minPayload.CreatorID
}
// PARTNER and MASTER receive every resource unconditionally.
for _, rel := range []peer.PeerRelation{peer.PARTNER, peer.MASTER} {
ps.PublishesCommon(dt, user, groups, &dbs.Filters{
And: map[string][]dbs.Filter{
"relation": {{Operator: dbs.EQUAL.String(), Value: rel}},
},
}, payload, proto)
}
// NANO: only send to the nano whose UUID matches the resource creator.
if creatorID != "" {
ps.PublishesCommon(dt, user, groups, &dbs.Filters{
And: map[string][]dbs.Filter{
"relation": {{Operator: dbs.EQUAL.String(), Value: peer.NANO}},
"id": {{Operator: dbs.EQUAL.String(), Value: creatorID}},
},
}, payload, proto)
}
return nil
}
// forwardToNano sends a booking mutation directly to a known NANO peer.
// The NANO peer is already resolved by the caller (resolveBookingNano).
// DTN critical is applied automatically by PublishCommon (Relation == NANO).
func (abs *StreamService) forwardToNano(nano *peer.Peer, evt *common.Event, proto string) {
dt := tools.DataType(evt.DataType)
abs.PublishCommon(&dt, evt.User, evt.Groups, nano.PeerID, protocol.ID(proto), evt.Payload)
}
func (s *StreamService) write(
did string,
peerID *pp.AddrInfo,
+51 -3
View File
@@ -27,6 +27,10 @@ const ProtocolConsidersResource = "/opencloud/resource/considers/1.0"
const ProtocolMinioConfigResource = "/opencloud/minio/config/1.0"
const ProtocolAdmiraltyConfigResource = "/opencloud/admiralty/config/1.0"
// ProtocolSourcePresignResource routes PB_SOURCE_PRESIGN to the resource-owner peer.
// The owner generates a pre-signed Minio URL and responds via PB_CONSIDERS.
const ProtocolSourcePresignResource = "/opencloud/resource/source-presign/1.0"
const ProtocolSearchResource = "/opencloud/resource/search/1.0"
const ProtocolCreateResource = "/opencloud/resource/create/1.0"
const ProtocolUpdateResource = "/opencloud/resource/update/1.0"
@@ -43,6 +47,7 @@ var protocols = map[protocol.ID]*common.ProtocolInfo{
ProtocolVerifyResource: {WaitResponse: true, TTL: 1 * time.Minute},
ProtocolMinioConfigResource: {WaitResponse: true, TTL: 1 * time.Minute},
ProtocolAdmiraltyConfigResource: {WaitResponse: true, TTL: 1 * time.Minute},
ProtocolSourcePresignResource: {WaitResponse: true, TTL: 1 * time.Minute},
ProtocolObserve: {WaitResponse: true, TTL: 1 * time.Minute},
}
@@ -63,8 +68,8 @@ type StreamService struct {
// IsPeerKnown, when set, is called at stream open for every inbound protocol.
// Return false to reset the stream immediately. Left nil until wired by the node.
IsPeerKnown func(pid pp.ID) bool
// dnt is the Disconnection Network Tolerance cache for outbound streams.
dnt *dntCache
// DTN is the Disconnection Network Tolerance cache for outbound streams.
dnt *DTNCache
// observeCache tracks running heartbeat goroutines on the OBSERVED side.
observeCache *observeCache
// hbBatcher accumulates incoming heartbeats (observing side) and flushes
@@ -78,6 +83,12 @@ type StreamService struct {
// observeUsers tracks which users are observing which peers so streams are
// closed only when the last observer for a peer disconnects.
observeUsers *userPeerIndex
// observeMetrics accumulates connection-quality data per observed peer (observing side).
// Keys are peer_id strings; values are *PeerObserveMetrics.
observeMetrics sync.Map
// DTNNudge receives peer IDs for which an immediate DTN retry should be
// attempted (e.g. when the peer just reconnected via PendingCallers).
dntNudge chan string
}
func InitStream(ctx context.Context, h host.Host, key pp.ID, maxNode int, node common.DiscoveryPeer) (*StreamService, error) {
@@ -92,6 +103,7 @@ func InitStream(ctx context.Context, h host.Host, key pp.ID, maxNode int, node c
dnt: newDNTCache(),
observeCache: newObserveCache(),
observeUsers: newUserPeerIndex(),
dntNudge: make(chan string, 32),
}
service.hbBatcher = newHeartbeatBatcher(flushObserveBatch)
for proto := range protocols {
@@ -105,6 +117,23 @@ func InitStream(ctx context.Context, h host.Host, key pp.ID, maxNode int, node c
return service, nil
}
// PendingContacts returns the peer IDs that have at least one critical DTN
// entry pending. Called on each heartbeat tick to populate PendingContact.
func (s *StreamService) PendingContacts() []string {
return s.dnt.peersWithPending()
}
// NudgeContacts signals the DTN loop to retry immediately for the given peer
// IDs (typically received via HeartbeatResponse.PendingCallers).
func (s *StreamService) NudgeContacts(peerIDs []string) {
for _, id := range peerIDs {
select {
case s.dntNudge <- id:
default:
}
}
}
// gate wraps a stream handler with IsPeerKnown validation.
// If the peer is unknown the entire connection is closed and the handler is not called.
// IsPeerKnown is read at stream-open time so it works even when set after InitStream.
@@ -117,6 +146,17 @@ func (s *StreamService) gatePrivilege(h func(network.Stream)) func(network.Strea
},
}, "", false, 0, 1)
if len(d.Data) == 0 {
stream.Reset()
return
}
master := d.Data[0].(*peer.Peer)
if stream.Conn().RemotePeer().String() != master.PeerID {
logger := oclib.GetLogger()
logger.Warn().
Str("remote", stream.Conn().RemotePeer().String()).
Str("master", master.PeerID).
Msg("[gate] nano rejected stream from non-master peer")
stream.Reset()
return
}
}
@@ -162,9 +202,17 @@ func (s *StreamService) HandleResponse(stream network.Stream) {
Stream: stream,
Expiry: time.Now().UTC().Add(expiry + 1*time.Minute),
}
// ProtocolObserve uses a bidirectional long-lived stream: the remote writes
// heartbeats back on the same stream, and may later send a close event.
// Use a persistent readLoop so we can receive both heartbeats and close events.
protoInfo := protocols[stream.Protocol()]
if stream.Protocol() == ProtocolObserve {
protoInfo = &common.ProtocolInfo{PersistantStream: true}
}
go s.readLoop(s.Streams[stream.Protocol()][stream.Conn().RemotePeer()],
stream.Conn().RemotePeer(),
stream.Protocol(), protocols[stream.Protocol()])
stream.Protocol(), protoInfo)
}
func (s *StreamService) connectToPartners() error {
+143 -291
View File
@@ -1,39 +1,37 @@
# Comparaison entre les Systèmes Existants et la Proposition d'Architecture Décentralisée Souveraine
**Catégorie** : Systèmes distribués Revue comparative et positionnement architectural
**Catégorie** : Systèmes distribués, Revue comparative et positionnement architectural
**Domaine d'application** : Systèmes embarqués, contexte spatial, réseaux hostiles, marchés de ressources décentralisés
**Version** : 1.1 — Mars 2026
**Version** : 1.2, Mai 2026
---
## Résumé
Ce document présente une analyse comparative systématique entre les principaux systèmes décentralisés existants — de la découverte P2P aux blockchains — et la proposition d'architecture pour un réseau décentralisé souverain opérant dans un contexte embarqué et hostile (désignée ci-après "la proposition"). Le contexte de référence est celui du projet GARDEN (Generic Architecture for Resilient Decentralized Execution Networks), qui requiert une combinaison de propriétés rarement satisfaites simultanément par un système unique : découverte décentralisée de pairs, souveraineté des données, confidentialité transactionnelle, tolérance aux disruptions réseau (DTN), et gestion de consortiums à niveaux de confiance hétérogènes.
Ce document présente une analyse comparative entre les principaux systèmes décentralisés existants et la proposition d'architecture pour un réseau décentralisé souverain opérant dans un contexte embarqué et hostile (désignée ci-après "la proposition"). Le contexte de référence est celui du projet GARDEN (Generic Architecture for Resilient Decentralized Execution Networks), qui requiert une combinaison de propriétés rarement satisfaites simultanément : découverte décentralisée de pairs, souveraineté des données, confidentialité transactionnelle, tolérance aux disruptions réseau (DTN), et gestion de consortiums à niveaux de confiance hétérogènes.
L'analyse montre qu'aucun système existant ne répond simultanément à l'ensemble de ces exigences. IPFS/libp2p offre une découverte décentralisée mature mais sans confidentialité native. Hyperledger Fabric offre une blockchain de consortium avec canaux privés mais suppose une connectivité continue. Secret Network offre des smart contracts confidentiels mais repose sur une dépendance matérielle (Intel SGX). Les systèmes de marketplace décentralisée (Golem, Akash) fournissent des mécanismes de marché mais n'abordent pas la tolérance DTN ni la gestion de la confiance relative.
L'analyse montre qu'aucun système existant ne répond simultanément à l'ensemble de ces exigences. IPFS/libp2p offre une découverte décentralisée mature mais sans confidentialité native. Hyperledger Fabric offre une blockchain de consortium avec canaux privés mais suppose une connectivité continue. Secret Network offre des smart contracts confidentiels mais repose sur une dépendance matérielle (Intel SGX). Les systèmes de marketplace décentralisée (Golem, Akash) fournissent des mécanismes de marché mais n'adressent ni la tolérance DTN ni la confiance relative.
La proposition se distingue en intégrant des mécanismes issus de plusieurs domaines de la littérature : scoring comportemental multidimensionnel inspiré des protocoles SWIM [Das et al., 2002], architecture blockchain hybride combinant blockchain permissionnée intra-consortium et règlement confidentiel inter-consortium, et adaptations DTN dérivées de la RFC 4838 [Cerf et al., 2007]. Cette synthèse architecturale constitue une contribution originale par rapport à l'existant.
Un point structurant de la proposition est la **séparation explicite entre le système de découverte P2P** (profil AP, haute disponibilité, cohérence éventuelle) et le **système de règlement monétaire** (profil CP, cohérence forte, finalité déterministe). Ces deux sous-systèmes ont des prérequis mutuellement incompatibles : leur fusion dans un protocole unique dégraderait les garanties des deux.
Un point structurant de la proposition, absent de la majorité des systèmes existants, est la **séparation explicite entre le système de découverte et d'échange pair-à-pair** (profil AP, haute disponibilité, cohérence éventuelle) et le **système de règlement monétaire** (profil CP, cohérence forte, finalité déterministe). Ces deux sous-systèmes ont des prérequis mutuellement incompatibles : leur fusion dans un protocole unique dégraderait les garanties des deux. Le tableau comparatif intègre ce critère de séparation.
Pour la couche de règlement monétaire spécifiquement, l'analyse converge vers l'écosystème Cosmos, par sa capacité à déployer des blockchains souveraines interconnectées, couplé à Secret Network pour la confidentialité transactionnelle. Cette piste est développée en section 6.4.
Les divergences détaillées entre la proposition et un système de référence en cours de développement — avec criticité, options de développement, et feuille de route — sont documentées dans le fichier `NOTE_DIVERGENCE_SYSTEME_REFERENCE.md`.
Les divergences détaillées entre la proposition et un système de référence en cours de développement sont documentées dans `NOTE_DIVERGENCE_SYSTEME_REFERENCE.md`.
---
## 1. Critères de Comparaison
Les critères suivants sont retenus pour l'analyse comparative. Chaque critère est justifié par rapport aux exigences du contexte GARDEN.
| Critère | Définition | Justification GARDEN |
|---|---|---|
| **Décentralisation** | Absence de point unique de contrôle ou de défaillance | Contexte hostile : tout point centralisé est une cible prioritaire |
| **Confidentialité** | Opacité du contenu ET des métadonnées pour les observateurs non autorisés | Watchers passifs, acteurs adversariaux dans le réseau |
| **Résistance Sybil** | Capacité à résister à la création massive d'identités fictives [Douceur, 2002] | Réseau potentiellement infiltré par des adversaires |
| **Tolérance DTN** | Opérabilité sous connectivité intermittente, haute latence, partitions prolongées [Fall, 2003] | Contrainte structurelle spatiale et embarquée |
| **Résistance Sybil** | Capacité à résister à la création massive d'identités fictives | Réseau potentiellement infiltré par des adversaires |
| **Tolérance DTN** | Opérabilité sous connectivité intermittente, haute latence, partitions prolongées | Contrainte structurelle spatiale et embarquée |
| **Scalabilité** | Passage à l'échelle sans dégradation prohibitive des performances | Multi-cluster, multi-organisation |
| **Finalité des transactions** | Délai et certitude de l'irréversibilité des transactions monétaires | Prévention du double-spend dans les contextes DTN |
| **Smart contracts** | Capacité d'automatiser le règlement conditionnel à des événements vérifiables | Marché de ressources : paiement automatique à la livraison attestée |
| **Séparation découverte / règlement** | Architecture explicitement distincte entre la couche de découverte P2P (AP) et la couche de règlement monétaire (CP) | Prérequis mutuellement incompatibles toute fusion dégrade les garanties des deux |
| **Séparation découverte / règlement** | Architecture explicitement distincte entre couche P2P (AP) et couche monétaire (CP) | Prérequis mutuellement incompatibles, toute fusion dégrade les deux |
| **Gestion de consortiums** | Mécanismes d'admission, révocation, et niveaux de confiance différenciés | Coalitions multi-organisations à confiance hétérogène |
| **Souveraineté** | Contrôle par le créateur du cycle de vie de ses données et identités | Exigence fondamentale du contexte spatial/militaire |
| **Maturité** | Disponibilité en production, documentation, écosystème | Faisabilité d'implémentation dans un délai raisonnable |
@@ -43,299 +41,127 @@ Les critères suivants sont retenus pour l'analyse comparative. Chaque critère
## 2. Systèmes de Découverte et Stockage P2P
### 2.1 IPFS / Libp2p (Benet, 2014)
### 2.1 IPFS / Libp2p
**Principe** : IPFS (InterPlanetary File System) est un système de fichiers distribué adressé par contenu. Chaque bloc de données est identifié par son hash cryptographique (Content Identifier, CID), permettant une vérification d'intégrité intrinsèque et une déduplication automatique. La couche de découverte repose sur une DHT Kademlia publique [Maymounkov & Mazières, 2002] implémentée dans libp2p.
IPFS (InterPlanetary File System) [3] est un système de fichiers distribué adressé par contenu : chaque bloc est identifié par son hash cryptographique (CID), ce qui garantit l'intégrité intrinsèque et la déduplication. La couche de découverte repose sur une DHT Kademlia [25] publique, implémentée dans libp2p, qui constitue probablement l'écosystème P2P le plus modulaire et le plus mature disponible aujourd'hui, transports multiples (TCP, QUIC, WebTransport), NAT traversal, multiplexage de protocoles.
**Forces** :
- Architecture décentralisée mature, déployée à très large échelle
- Vérification d'intégrité native par adressage de contenu
- Écosystème libp2p modulaire (transports multiples : TCP, QUIC, WebTransport, Bluetooth)
- Comunauté active, documentation extensive
- Support natif pour les connexions multi-transport et le NAT traversal
Dans IPFS, la DHT est publique par construction. Tout observateur participant à la DHT peut voir quels CIDs sont recherchés et par qui, ce qui dans un contexte hostile revient à diffuser en clair quelles ressources un nœud cherche. Des couches additionnelles (DHT privée avec espace de noms isolé, chiffrement du contenu) peuvent rendre libp2p utilisable comme couche de transport, mais IPFS dans sa forme standard est inadapté. Il n'existe pas non plus de mécanisme de confiance ou de scoring des pairs : n'importe quel nœud peut rejoindre la DHT publique.
**Faiblesses** :
- Aucune confidentialité native : les CIDs dans la DHT publique révèlent quels contenus sont recherchés et partagés
- Aucun contrôle d'accès à la couche de découverte : tout nœud peut rejoindre la DHT publique
- Résistance Sybil non résolue dans la DHT publique
- Pas de mécanisme de confiance ou de scoring des pairs
- Latences de découverte incompatibles avec les contraintes DTN sévères
libp2p reste malgré tout une référence incontournable pour la couche de transport, c'est le socle sur lequel la proposition elle-même s'appuie.
**Compatibilité GARDEN** : Inadapté en l'état. La DHT publique IPFS est une source de fuite d'information massive dans un contexte hostile. Le fait qu'un ensemble de nœuds recherche des ressources de type spécifique révèle des informations stratégiques à tout observateur participant à la DHT. Des couches additionnelles de confidentialité (chiffrement du contenu, utilisation d'une DHT privée avec espace de noms isolé) peuvent rendre libp2p utilisable comme couche de transport, mais IPFS dans sa forme standard est inadapté.
### 2.2 Filecoin
### 2.2 Filecoin (Protocol Labs, 2017)
Filecoin [32] est un marché de stockage décentralisé construit sur IPFS, où les fournisseurs s'engagent à stocker des données via des preuves cryptographiques vérifiables (Proof of Replication, Proof of Spacetime). L'idée de rémunérer le stockage par des preuves plutôt que par de la confiance est conceptuellement solide et constitue une inspiration pour la couche d'attestation de la proposition.
**Principe** : Filecoin est un marché de stockage décentralisé construit sur IPFS. Les fournisseurs de stockage s'engagent à stocker des données en soumettant des preuves cryptographiques : Proof of Replication (PoRep) prouve qu'une copie unique d'un fichier est bien stockée, Proof of Spacetime (PoSt) prouve que le stockage est maintenu dans le temps. Le marché de stockage est réglé via des smart contracts sur la chaîne Filecoin.
En revanche, les transactions on-chain Filecoin sont entièrement publiques, qui stocke quoi pour qui, à quel coût, ce qui est incompatible avec le contexte hostile. La complexité des preuves cryptographiques introduit également une charge de calcul significative, difficilement absorbable par des nœuds embarqués à ressources contraintes.
**Forces** :
- Incentives cryptoéconomiques alignant les comportements des fournisseurs avec les intérêts des utilisateurs
- Preuves cryptographiques vérifiables de l'exécution du stockage
- Décentralisé avec un marché libre de capacité
### 2.3 BitTorrent DHT
**Faiblesses** :
- Transactions on-chain sur Filecoin entièrement publiques : les accords de stockage révèlent qui stocke quoi pour qui
- Latences élevées incompatibles avec les workloads temps-réel
- Complexité des preuves cryptographiques : charge de calcul significative pour les nœuds
- Pas de gestion de confiance relative entre pairs ; pas de consortium
BitTorrent DHT (BEP 5) [23] est la DHT Kademlia la plus déployée au monde, avec des centaines de millions de nœuds. Sa résilience à grande échelle est exceptionnelle et bien documentée. Pour GARDEN, c'est essentiellement une référence théorique : aucune authentification des nœuds, aucune confidentialité des requêtes, résistance Sybil nulle. Tout nœud peut annoncer n'importe quelle clé, et les requêtes révèlent immédiatement ce que le demandeur cherche.
**Compatibilité GARDEN** : Le modèle de preuves cryptographiques de consommation de ressources est conceptuellement pertinent et constitue une inspiration pour la couche d'attestation de la proposition. Cependant, la transparence des transactions Filecoin on-chain et l'absence de confidentialité native rendent ce système inadapté au contexte hostile.
### 2.4 Tor et I2P
### 2.3 BitTorrent DHT (Loewenstern & Norberg, 2008)
Tor (The Onion Router) [10] anonymise les communications en routant chaque message à travers trois relais avec chiffrement en oignon, de sorte qu'aucun relais ne connaît à la fois la source et la destination. Les services cachés (.onion) permettent d'opérer des serveurs sans révéler leur adresse IP. C'est la solution de référence pour protéger les métadonnées de communication contre des observateurs passifs non globaux.
**Principe** : Le protocole BitTorrent DHT (BEP 5) implémente une DHT Kademlia pour la découverte de pairs partageant des torrents. Chaque nœud maintient une table de routage de pairs proches dans l'espace XOR de Kademlia, permettant de localiser des pairs ayant annoncé un torrent spécifique.
I2P propose une approche similaire avec un routage en ail (garlic routing) qui agrège plusieurs messages pour réduire la corrélation temporelle, et une architecture plus décentralisée que Tor (pas de directory authorities).
**Forces** :
- Système très mature, déployé à des centaines de millions de nœuds
- Résilience exceptionnelle démontrée à grande échelle
- Protocole simple et bien documenté
**Faiblesses** :
- Aucune authentification des nœuds : toute clé publique peut être annoncée par n'importe qui
- Aucune confidentialité : les requêtes DHT révèlent quels contenus sont recherchés
- Aucun mécanisme de confiance ou de réputation
- Résistance Sybil nulle
**Compatibilité GARDEN** : Inadapté. BitTorrent DHT constitue une référence historique utile pour comprendre les propriétés de scalabilité et de résilience des DHT Kademlia, mais ses propriétés de sécurité sont incompatibles avec tout contexte hostile.
### 2.4 Tor (Dingledine, Mathewson & Syverson, 2004)
**Principe** : Tor (The Onion Router) est un réseau d'anonymisation par routage en oignon : chaque message est chiffré en plusieurs couches et routé à travers trois nœuds relais (entry guard, middle relay, exit node), de sorte qu'aucun relais unique ne connaît à la fois la source et la destination d'un message. Les services cachés (hidden services, .onion) permettent d'opérer des serveurs sans révéler leur adresse IP.
**Forces** :
- Confidentialité de transport forte, résistance démontrée contre les observateurs passifs non globaux
- Résistance à la surveillance ciblée sur les liaisons intermédiaires
- Écosystème bien documenté, client libre largement déployé
**Faiblesses** :
- Latences élevées (100500ms en moyenne) introduites par le routage multi-sauts
- Vulnérable aux attaques par analyse de trafic global (corrélation temporelle) [Murdoch & Danezis, 2005]
- Pas de découverte décentralisée de pairs : les directory authorities constituent un point centralisé
- Pas de transactions monétaires ni de smart contracts
- Connectivité TCP continue requise : incompatible avec les contraintes DTN
**Compatibilité GARDEN** : Pertinent comme couche de transport pour masquer les métadonnées de communication entre nœuds, en particulier sur les liens exposés à des observateurs passifs. Cependant, Tor ne constitue pas une infrastructure complète pour un système de découverte et de marché de ressources.
### 2.5 I2P (Invisible Internet Project)
**Principe** : I2P est un réseau mixnet utilisant le routage en ail (garlic routing), une variante du routage en oignon où plusieurs messages sont agrégés dans une même "gousse d'ail" pour réduire la corrélation temporelle. I2P est plus décentralisé que Tor (pas de directory authorities) et optimisé pour la communication bidirectionnelle (trafic interne au réseau).
**Forces** :
- Plus décentralisé que Tor (distributed network database)
- Meilleure résistance à l'analyse de trafic pour le trafic bidirectionnel
- Réseau auto-suffisant sans dépendance aux directory authorities
**Faiblesses** :
- Écosystème et communauté plus petits que Tor
- Performances de latence comparables à Tor
- Documentation moins développée
- Pas adapté aux contraintes DTN
**Compatibilité GARDEN** : Alternative crédible à Tor pour la couche de transport anonymisant, avec l'avantage d'une moindre dépendance à des points centralisés. Comme Tor, ne constitue pas une infrastructure complète.
Les deux réseaux partagent les mêmes limitations pour GARDEN : latences élevées (100500ms), connectivité TCP continue requise (incompatible DTN), et absence de toute couche de transactions monétaires ou de découverte décentralisée de pairs. Pertinents comme couche de transport anonymisant sur les liens exposés, pas comme infrastructure complète.
---
## 3. Systèmes de Computation et Marketplace Décentralisée
### 3.1 Golem (Golem Network, 2016)
### 3.1 Golem
**Principe** : Golem est une marketplace de compute décentralisée basée sur Ethereum. Les fournisseurs de ressources (requestors) soumettent des tâches de calcul définies dans un format standardisé ; les prestataires (providers) les exécutent et reçoivent un paiement en tokens GLM. La vérification du bon accomplissement repose sur des challenges cryptographiques sur les résultats.
**Forces** :
- Marché libre de ressources de calcul
- Preuve de travail challengeable pour vérification des résultats
- Décentralisé, pas d'opérateur central
**Faiblesses** :
- Transactions Ethereum entièrement publiques : qui paie qui, pour quel type de tâche, avec quel montant
- Latences du réseau Ethereum (finalité probabiliste) incompatibles avec les workloads temps-réel
- Pas de support DTN
- Pas de gestion de confiance relative ni de consortiums
- Pas de confidentialité des tâches exécutées
**Compatibilité GARDEN** : Insuffisant pour un contexte hostile. Le modèle de marketplace de compute est conceptuellement pertinent, mais l'absence de confidentialité et la dépendance à Ethereum public rendent ce système inadapté.
Golem [16] est une marketplace de compute décentralisée sur Ethereum : les demandeurs soumettent des tâches, les fournisseurs les exécutent et reçoivent des tokens GLM. Le modèle est conceptuellement proche de ce que GARDEN requiert. Le problème est que toutes les transactions sont publiques sur Ethereum, qui paie qui, combien, pour quel type de tâche, ce qui est incompatible avec la souveraineté des données dans un contexte hostile. Pas de support DTN, pas de gestion de confiance relative.
### 3.2 Akash Network
**Principe** : Akash Network est un marché de déploiement Kubernetes décentralisé basé sur le SDK Cosmos. Les fournisseurs de compute publient leurs offres de ressources Kubernetes ; les utilisateurs soumettent des manifestes de déploiement standardisés (SDL : Stack Definition Language) ; un mécanisme d'enchère inverse attribue les déploiements aux fournisseurs les moins coûteux.
Akash est sans doute le système de compute décentralisé le plus architecturalement proche de GARDEN. C'est un marché de déploiement Kubernetes basé sur le SDK Cosmos, avec enchères inverses et finalité Tendermint (~6 secondes). L'interopérabilité Cosmos via IBC est un point de compatibilité potentiel réel.
**Forces** :
- Architecturalement compatible avec Kubernetes (outil standard d'orchestration de conteneurs)
- Finalité rapide via Tendermint BFT (~6 secondes)
- Marché de déploiement décentralisé avec enchères transparentes
- Écosystème Cosmos avec interopérabilité IBC
Akash reste cependant insuffisant : les déploiements sont publics sur la chaîne, le modèle de confiance est binaire (certifié / non certifié), et il n'existe pas de gestion de consortiums à niveaux de confiance différenciés. C'est un exemple utile de ce que le SDK Cosmos permet de construire, mais pas une solution directement adaptable.
**Faiblesses** :
- Transactions publiques sur la chaîne Akash : les déploiements sont entièrement visibles
- Modèle de confiance binaire (fournisseur certifié / non certifié)
- Pas de confidentialité native des workloads déployés
- Pas de support DTN
- Gouvernance de confiance limitée : pas de gestion de consortiums à niveaux de confiance
### 3.3 iExec
**Compatibilité GARDEN** : Architecturalement proche de ce que GARDEN requiert (Kubernetes décentralisé), mais manque les couches de confidentialité et de gestion de confiance relative indispensables. L'interopérabilité Cosmos constitue un point de compatibilité potentiel.
iExec intègre des Trusted Execution Environments (TEE) Intel SGX [7] dans une marketplace de compute sur Ethereum : le fournisseur de compute ne peut pas accéder aux données qu'il traite, ce qui est une propriété utile pour l'attestation de consommation de ressources. La dépendance à Intel SGX et la transparence des transactions de marketplace sur Ethereum L1 sont les deux limitations principales pour GARDEN.
### 3.3 iExec (2017)
### 3.4 Ocean Protocol
**Principe** : iExec est une marketplace de compute décentralisée intégrant des Trusted Execution Environments (TEE) Intel SGX pour l'exécution confidentielle des tâches. Les smart contracts Ethereum gèrent le cycle de vie des tâches et les paiements en tokens RLC. Le TEE garantit que ni le fournisseur de compute ni aucun observateur ne peut accéder au contenu des données traitées.
**Forces** :
- Exécution confidentielle native via Intel SGX : le fournisseur de compute ne voit pas les données traitées
- Marketplace décentralisée avec attestations TEE
- Smart contracts Ethereum pour l'automatisation du paiement
**Faiblesses** :
- Dépendance critique à Intel SGX : vulnérabilités de canal latéral documentées (Spectre-NG, SGAxe, LVI) [Costan & Devadas, 2016]
- Transactions de marketplace publiques sur Ethereum L1
- Pas de support DTN
- Gouvernance centralisée du réseau TEE
**Compatibilité GARDEN** : Le modèle TEE pour l'exécution confidentielle est pertinent pour le contexte GARDEN, particulièrement pour l'attestation de consommation de ressources (verrou oracle). Cependant, la dépendance à Intel SGX constitue une dépendance matérielle problématique pour des nœuds embarqués spatiaux dont la chaîne d'approvisionnement peut être compromise.
### 3.4 Ocean Protocol (2019)
**Principe** : Ocean Protocol est un marché décentralisé de données basé sur Ethereum. Le mécanisme "Compute-to-Data" permet à un fournisseur de données de proposer l'accès à ses données pour du calcul sans jamais les transférer : le calcul s'exécute au plus près des données, et seul le résultat est retourné au demandeur.
**Forces** :
- Modèle Compute-to-Data respectant la souveraineté du fournisseur de données
- Tokenisation des actifs de données (datatokens ERC-20)
- Décentralisé, écosystème actif
**Faiblesses** :
- Transactions de marketplace publiques sur Ethereum
- Confiance basée sur des smart contracts audités, pas sur des preuves cryptographiques d'exécution
- Pas de support DTN
- Pas de gestion de consortiums à confiance différenciée
**Compatibilité GARDEN** : Le modèle Compute-to-Data constitue une approche intéressante pour préserver la souveraineté des données dans un marché décentralisé. Cependant, la transparence Ethereum et l'absence de gestion de la confiance relative limitent son applicabilité directe.
Le mécanisme "Compute-to-Data" d'Ocean Protocol est intéressant : un fournisseur de données peut mettre ses données à disposition pour du calcul sans jamais les transférer, le calcul s'exécute localement, seul le résultat part. C'est une approche qui respecte la souveraineté du fournisseur. La transparence Ethereum et l'absence de gestion de confiance relative limitent son applicabilité directe, mais le modèle Compute-to-Data est une inspiration pertinente pour la couche de données de la proposition.
---
## 4. Systèmes Blockchain
### 4.1 Bitcoin (Nakamoto, 2008)
### 4.1 Bitcoin
**Principe** : Bitcoin est le premier système de règlement monétaire pair-à-pair sans tiers de confiance. La sécurité repose sur une preuve de travail (Proof of Work) permettant d'atteindre un consensus sur l'ordre des transactions sans autorité centrale. La finalité est probabiliste : une transaction est considérée irréversible après ~6 confirmations (~1 heure).
Bitcoin [28] démontre qu'un consensus sur un ledger partagé est possible sans autorité centrale. Sa sécurité éprouvée sur 15+ ans sans compromission protocolaire est remarquable. Mais l'absence de smart contracts expressifs, la finalité à une heure, et la consommation énergétique du Proof of Work le rendent inutilisable pour le règlement d'un marché de ressources embarqué. Sa valeur pour GARDEN est essentiellement théorique, c'est la preuve que le problème est soluble.
**Forces** :
- Sécurité éprouvée sur 15+ ans d'opération continue sans compromission protocolaire
- Décentralisation maximale (aucun opérateur central)
- Résistance à la censure démontrée
### 4.2 Ethereum
**Faiblesses** :
- Pas de smart contracts expressifs (Script très limité)
- Latence finale (~1 heure) incompatible avec les contraintes opérationnelles
- Transactions pseudonymes traçables par analyse de graphe [Meiklejohn et al., 2013]
- Proof of Work : consommation énergétique prohibitive pour contexte embarqué
- Pas de gestion de consortiums
Ethereum a apporté les smart contracts à vocation généraliste. La machine virtuelle EVM exécute des programmes Turing-complets, et l'écosystème d'outils, d'audits, et de développeurs est le plus large qui existe. Depuis la migration vers Proof of Stake (The Merge, 2022), la consommation énergétique est devenue raisonnable.
**Compatibilité GARDEN** : Inadapté pour le règlement programmatique et la confidentialité. Valeur de référence théorique uniquement.
Le problème fondamental reste la transparence totale : toutes les transactions et tous les états de smart contracts sont publics, ce qui rend Ethereum L1 incompatible avec un contexte opérationnel hostile. Les L2 ZK confidentiels (Aztec notamment) représentent une direction prometteuse, mais leur maturité en 2026 reste insuffisante pour un déploiement opérationnel. À noter également le phénomène MEV (Miner Extractable Value) [8] : les validateurs peuvent réordonner les transactions pour extraire de la valeur au détriment des utilisateurs, un risque structurel dans tout marché décentralisé basé sur Ethereum.
### 4.2 Ethereum (Buterin, 2014 ; Wood, 2014)
### 4.3 Hyperledger Fabric
**Principe** : Ethereum est la première plateforme de smart contracts à vocation généraliste. La machine virtuelle EVM (Ethereum Virtual Machine) exécute des programmes Turing-complets encodés dans des transactions on-chain. La migration vers Proof of Stake (The Merge, 2022) a réduit la consommation énergétique de ~99.95%.
Hyperledger Fabric [1] est la blockchain de consortium la plus mature disponible. Son architecture distingue les orderers (ordre des transactions), les peers (exécution des chaincode), et les MSP (gestion des identités membres). Les canaux privés permettent à des sous-groupes de membres d'effectuer des transactions confidentielles vis-à-vis du reste du réseau. La finalité est déterministe, pas de forks possibles avec Raft ou PBFT.
**Forces** :
- EVM : plateforme de smart contracts la plus mature, écosystème DeFi massif
- Large écosystème de développeurs et d'outils
- L2 émergents (ZK-rollups, Optimistic rollups) améliorant scalabilité et potentiellement confidentialité
C'est le candidat le plus adapté parmi les systèmes existants pour un consortium fermé intra-organisation. Sa faiblesse pour GARDEN est double : d'une part la gouvernance repose nécessairement sur la confiance aux opérateurs MSP (pas de trustless), d'autre part la connectivité TCP continue entre peers et orderers est requise, incompatible avec les contraintes DTN.
**Faiblesses** :
- Transparence totale : toutes les transactions et les états des smart contracts sont publics
- Phénomène MEV (Miner/Maximal Extractable Value) créant des distorsions de marché [Daian et al., 2020]
- Finalité probabiliste sur L1 (~12s pour la finalité slot, ~15 minutes pour finalité économique forte)
- Pas de gestion native des consortiums
- L2 ZK confidentiels encore en développement actif
### 4.4 Cosmos / IBC
**Compatibilité GARDEN** : Inadapté en L1 seul. Les L2 ZK confidentiels (Aztec) constituent un axe de développement prometteur mais dont la maturité est insuffisante pour un déploiement opérationnel en 2026. Pertinent comme substrate de référence pour l'écosystème EVM.
Cosmos [21] part d'une idée fondamentalement différente de tous les systèmes précédents : plutôt que de partager une infrastructure commune, chaque application ou consortium peut opérer sa propre blockchain dédiée, appelée "zone", avec son propre consensus, ses propres règles, et son propre validator set. Les zones communiquent via IBC (Inter-Blockchain Communication), un protocole standardisé qui garantit la livraison exactement une fois avec des propriétés vérifiables par light client.
### 4.3 Hyperledger Fabric (Androulaki et al., 2018)
**Créer sa propre zone : ce que ça implique concrètement**
**Principe** : Hyperledger Fabric est une blockchain permissionnée conçue pour les consortiums d'entreprises. Son architecture distingue les orderers (responsables de l'ordre des transactions), les peers (exécutant les chaincode et maintenant le ledger), et les MSP (Membership Service Providers, responsables de l'identité des membres). Les canaux privés permettent à des sous-groupes de membres d'effectuer des transactions confidentielles vis-à-vis du reste du réseau.
Le Cosmos SDK est un framework modulaire en Go qui fournit les composants fondamentaux, consensus Tendermint BFT, mempool, API REST/gRPC, modules bank/staking/governance, sous forme de briques réutilisables et bien testées. Un consortium n'a à écrire que la logique applicative qui lui est propre. L'outil `ignite CLI` (anciennement Starport) génère le squelette d'une zone compilable et fonctionnelle en quelques commandes. Des zones de production comme Osmosis, Akash, ou Injective ont été construites sur cette base; le délai réaliste de mise en production d'une zone dédiée est de quelques semaines à quelques mois, pas d'années.
**Forces** :
- Canaux privés : confidentialité native pour les sous-consortiums
- Finalité déterministe : pas de forks possibles avec Raft ou PBFT
- Modular consensus : le mécanisme de consensus est paramétrable selon les besoins
- Chaincode (smart contracts) en langages standards (Go, Java, Node.js)
- Gouvernance fine via les MSP
Ce qui rend cette approche particulièrement adaptée à GARDEN, c'est la combinaison de trois propriétés :
**Faiblesses** :
- Permissioned : requiert de faire confiance aux opérateurs des MSP (pas de trustless)
- Gouvernance centralisée par essence : il faut faire confiance à la structure d'administration
- Pas de connectivité intermittente supportée nativement : TCP continu requis entre peers et orderers
- Complexité d'administration élevée
La **souveraineté du validator set** est totale. Les validateurs de la zone sont entièrement contrôlés par le consortium, qui valide, qui ne valide pas, selon quelles règles. La sécurité économique repose sur le token natif de la zone : les validateurs stakent des tokens qui peuvent être slashés en cas de comportement malveillant. Pour une coalition naissante sans validator set robuste, l'Interchain Security (ICS, activée sur le Cosmos Hub en 2023) permet de déléguer cette sécurité au validator set du Hub, l'un des plus larges de l'écosystème.
**Compatibilité GARDEN** : Très adapté pour les consortiums fermés (intra-consortium dans la proposition). La finalité déterministe et les canaux privés en font le candidat le plus mature pour le règlement intra-consortium. La dépendance à une connectivité TCP continue constitue le principal gap avec les contraintes DTN.
La **gouvernance onchain native** couvre toutes les décisions du consortium : admissions et exclusions de validateurs, mises à jour de protocole, modifications des paramètres de la chaîne. Ces décisions ne passent pas par un processus hors-bande, elles sont des transactions blockchain ordinaires, soumises au même consensus BFT que les transactions monétaires. Cette convergence évite la fragmentation entre mécanismes de gouvernance et mécanismes de règlement.
### 4.4 Cosmos / IBC (Kwon & Buchman, 2016)
L'**interopérabilité IBC** permet à une zone de consortium privée de communiquer avec Secret Network pour les transactions confidentielles inter-consortium, ou avec d'autres zones pour les échanges entre coalitions. Un canal IBC entre une zone de consortium et Secret Network permet de déléguer l'exécution confidentielle de contrats de règlement tout en conservant le ledger intra-consortium souverain.
**Principe** : Cosmos est un écosystème de blockchains souveraines et interopérables. Chaque "zone" est une blockchain indépendante avec son propre consensus (généralement Tendermint BFT), sa propre gouvernance et ses propres smart contracts (CosmWasm). Les zones communiquent via le protocole IBC (Inter-Blockchain Communication), permettant des transferts de tokens et de messages entre blockchains hétérogènes.
CosmWasm, le framework de smart contracts standard de l'écosystème, présente deux avantages structurels sur l'EVM : le modèle d'exécution "actor" élimine les réentrances [24], la principale classe de bugs catastrophiques, et le langage Rust garantit la sécurité mémoire à la compilation.
**Forces** :
- Zones souveraines : chaque consortium peut opérer sa propre blockchain avec sa propre gouvernance
- Finalité rapide : Tendermint BFT offre une finalité déterministe en ~6 secondes
- IBC : interopérabilité standardisée entre zones
- CosmWasm : smart contracts en Rust avec sécurité mémoire accrue
- Écosystème large et actif
**Faiblesses** :
- Pas de confidentialité native : les transactions IBC sont visibles dans les logs des deux zones impliquées
- Modèle de confiance limité entre zones : pas de mécanisme standardisé pour la confiance relative
- Complexité d'administration d'une zone Cosmos
**Compatibilité GARDEN** : Excellente base pour une architecture multi-consortium. Chaque consortium peut opérer sa propre zone avec sa gouvernance, et les échanges inter-consortium transitent via IBC. L'absence de confidentialité native est compensable par des solutions applicatives (chiffrement des données avant soumission on-chain) ou par l'utilisation de zones confidentielles (Secret Network, zone Cosmos).
Les limitations à ne pas occulter : une zone Cosmos standard n'offre pas de confidentialité native (les transactions sont visibles sur l'explorateur), IBC n'est pas DTN-natif (les relayers supposent une connectivité suffisante), et opérer un validator set est une charge opérationnelle réelle.
### 4.5 Secret Network
**Principe** : Secret Network est une blockchain basée sur Cosmos utilisant des enclaves TEE Intel SGX pour l'exécution confidentielle des smart contracts. Les inputs des transactions, les états des smart contracts, et les outputs sont chiffrés pour les validateurs eux-mêmes : seule la logique du contrat est publique. Les développeurs écrivent des "secret contracts" en CosmWasm avec des annotations de confidentialité.
Secret Network est une zone Cosmos qui ajoute une couche de confidentialité native à l'exécution des smart contracts via des enclaves Intel SGX [7]. Les inputs des transactions, les états des contrats, et les outputs sont chiffrés non seulement en transit mais aussi vis-à-vis des validateurs eux-mêmes, seule la logique du contrat est publique. Ce qui distingue cette approche d'un simple chiffrement applicatif, c'est que la confidentialité est garantie par l'architecture d'exécution, non par la discipline des développeurs. Un validateur malveillant qui contrôlerait l'infrastructure ne peut pas accéder aux états des contrats confidentiels.
**Forces** :
- Smart contracts confidentiels natifs : aucun validateur ne peut accéder aux données en clair
- Compatibilité Cosmos : interopérabilité via IBC avec l'écosystème Cosmos
- Cas d'usage variés : DeFi privé, DAO confidentielles, bridges confidentiels
- Finalité Tendermint (~6 secondes)
Une propriété particulièrement utile pour les marchés de ressources : cette architecture supprime structurellement le MEV basé sur l'information. Un validateur qui ne peut pas lire le contenu des transactions ne peut pas les réordonner à son avantage.
**Faiblesses** :
- Dépendance critique à Intel SGX : vulnérabilités de canal latéral potentielles [Costan & Devadas, 2016]
- Pas de garantie de confidentialité si SGX est compromis
- Complexité de développement supérieure aux smart contracts standard
- Écosystème plus petit que Ethereum ou Cosmos
La limitation principale est réelle et doit être assumée : la dépendance à Intel SGX. Des vulnérabilités de canal latéral (Spectre-NG, SGAxe, LVI) ont été documentées sur cette architecture, et les nœuds embarqués spatiaux ne sont pas nécessairement équipés de processeurs Intel certifiés. C'est un compromis pragmatique, accepter une dépendance matérielle en échange d'une confidentialité des smart contracts mature et disponible aujourd'hui. L'alternative à moyen terme est Penumbra [30], une zone Cosmos dont la confidentialité repose sur des zk-SNARKs sans dépendance matérielle, actuellement en développement actif.
**Compatibilité GARDEN** : Bon candidat pour le règlement inter-consortium confidentiel dans la proposition. La dépendance à Intel SGX constitue une limitation pour les nœuds embarqués spatiaux dont la chaîne d'approvisionnement matérielle peut être compromise ou dont la disponibilité de matériel certifié SGX est incertaine.
### 4.6 Zcash
### 4.6 Zcash (Ben-Sasson et al., 2014 ; Hopwood et al., 2016)
Zcash [19] utilise les zk-SNARKs pour masquer cryptographiquement les montants et les adresses dans les transactions "shielded". L'avantage clé par rapport aux solutions TEE : la confidentialité repose uniquement sur des primitives cryptographiques, sans dépendance matérielle, plus robuste à long terme contre les attaques physiques sur les nœuds.
**Principe** : Zcash est une blockchain de paiements confidentiels utilisant les zk-SNARKs (Zero-Knowledge Succinct Non-interactive ARguments of Knowledge) pour masquer cryptographiquement les montants transférés et les adresses des parties dans les transactions "shielded". Contrairement aux solutions TEE, la confidentialité repose uniquement sur des primitives cryptographiques, sans dépendance matérielle.
La limitation est l'absence de smart contracts complexes. Le langage Script de Zcash est très limité, ce qui empêche d'automatiser le règlement conditionnel d'un marché de ressources. Par ailleurs, en pratique la majorité des transactions Zcash ne sont pas shielded, la protection par effet d'ensemble est réduite. Pertinent comme inspiration pour la couche de paiement pure, pas comme infrastructure complète.
**Forces** :
- Confidentialité cryptographique pure, sans dépendance matérielle
- zk-SNARKs vérifiables par n'importe quel nœud en O(1) de calcul
- Technologie ZK mature, référence académique et industrielle
- Pas de PoW sur la nouvelle architecture (Sapling, Orchard)
### 4.7 Oasis Network
**Faiblesses** :
- Pas de smart contracts complexes : le langage Script de Zcash est très limité
- Les pools shielded sont sous-utilisés (majorité des transactions non-shielded), réduisant l'anonymat par effet d'ensemble
- Gouvernance fortement centralisée par l'Electric Coin Company
- Pas adapté pour automatiser le règlement conditionnel d'un marché de ressources
Oasis [29] propose des "ParaTimes", des environnements d'exécution parallèles avec des niveaux de confidentialité configurables. Le Sapphire ParaTime offre un EVM confidentiel (états des smart contracts chiffrés dans SGX), ce qui permet de bénéficier de la compatibilité avec l'outillage Ethereum tout en ajoutant de la confidentialité. La dépendance SGX est identique à Secret Network. Écosystème plus jeune, mais l'architecture modulaire est intéressante comme référence de conception.
**Compatibilité GARDEN** : Excellent pour les paiements confidentiels simples entre parties connues. L'absence de smart contracts expressifs limite l'automatisation du règlement dans un marché de ressources complexe. Pertinent comme couche de paiement pour des cas d'usage spécifiques ne requérant pas de logique contractuelle.
### 4.8 Penumbra, Confidentialité ZK Cross-Chain dans l'Écosystème Cosmos
### 4.7 Oasis Network (Oasis Labs, 2020)
Penumbra est une zone Cosmos dont la proposition est simple à formuler mais techniquement ambitieuse : apporter à l'écosystème Cosmos une couche de confidentialité cryptographique pure, sans aucune dépendance à du matériel TEE, en s'appuyant exclusivement sur des preuves à divulgation nulle (ZK-proofs). C'est, à ce titre, le successeur naturel de Secret Network dans la trajectoire architecturale de GARDEN.
**Principe** : Oasis Network combine TEE et blockchain en proposant des "ParaTimes" — des environnements d'exécution parallèles avec des niveaux de confidentialité configurables. Le Sapphire ParaTime offre un EVM confidentiel (les états des smart contracts sont chiffrés dans SGX), permettant d'exécuter des smart contracts Solidity avec confidentialité des données internes.
Le modèle de confidentialité de Penumbra est inspiré de Zcash/Sapling mais adapté à un écosystème multi-chaînes. Toutes les transactions sur Penumbra opèrent dans un "shielded pool" : les montants, les adresses des parties, et les assets concernés sont entièrement masqués cryptographiquement. Les validateurs ne voient que des preuves ZK vérifiables, ils confirment que les règles du protocole sont respectées sans accéder aux données sous-jacentes. La confidentialité n'est pas une option ou une couche applicative; c'est le comportement par défaut, ce qui évite le problème d'anonymat par effet d'ensemble qui affecte Zcash (où la majorité des transactions sont non-shielded).
**Forces** :
- EVM confidentiel : compatibilité avec l'écosystème Ethereum + confidentialité
- Architecture modulaire (multiple ParaTimes avec différents niveaux de sécurité)
- Compatibilité Cosmos-adjacent
- Séparation consensus et exécution : scalabilité accrue
**La dimension cross-chain est ce qui rend Penumbra directement pertinent pour GARDEN.** Via IBC, des assets provenant de n'importe quelle zone Cosmos peuvent être déposés dans le shielded pool de Penumbra, y être transactés de manière confidentielle, puis retirés vers leur zone d'origine. Concrètement, une zone de consortium A peut envoyer des tokens de règlement via IBC vers Penumbra, exécuter un swap ou un transfert confidentiel avec la zone B, et retirer le résultat, sans que le contenu de l'opération ne soit jamais visible sur l'une ou l'autre des chaînes sources. Le transit par Penumbra agit comme un shielded relay entre zones.
**Faiblesses** :
- Dépendance à Intel SGX pour les ParaTimes confidentiels
- Écosystème plus jeune que Secret Network ou Ethereum
- Complexité d'architecture (multiple ParaTimes à comprendre et gérer)
Le DEX intégré de Penumbra est aussi un point notable pour le contexte des marchés de ressources : il utilise un mécanisme de batch avec ZK-proofs qui rend structurellement impossible le front-running. Toutes les offres d'une période sont traitées comme un batch sans que l'ordre de soumission soit exploitable, ce qui adresse directement le risque MEV sans dépendre de la confidentialité matérielle.
**Compatibilité GARDEN** : Bon compromis entre smart contracts expressifs (EVM) et confidentialité (TEE). La dépendance SGX est la même limitation que pour Secret Network. La compatibilité EVM facilite le portage de smart contracts existants.
Là où Penumbra diffère de Secret Network de manière structurelle, c'est dans l'expressivité contractuelle. Secret Network permet des smart contracts arbitraires (CosmWasm) avec confidentialité, logique métier complexe, états persistants, conditions multi-parties. Penumbra est avant tout un protocole de paiement et de swap confidentiels; la logique contractuelle y est bien plus limitée. Pour des cas d'usage de règlement simple (transfert de tokens entre consortiums, swap d'actifs), Penumbra est suffisant et préférable. Pour des contrats de règlement conditionnel complexes (oracles, multi-signatures avec conditions temporelles, escrow multi-parties), Secret Network reste plus adapté aujourd'hui.
L'état de maturité est la limitation principale. Penumbra est en développement actif, testnet depuis 2023, mainnet progressivement. L'écosystème d'outils, la documentation, et le retour d'expérience opérationnel sont encore limités comparés à Secret Network qui est en production depuis 2020. Pour GARDEN, Penumbra est la trajectoire cible à moyen terme, pas la fondation immédiate.
En termes de comparaison directe avec Secret Network : Penumbra élimine la dépendance matérielle SGX (avantage fort pour les nœuds embarqués dont la chaîne d'approvisionnement hardware est incertaine), offre une confidentialité cryptographiquement prouvable plutôt que basée sur une hypothèse de sécurité matérielle, et son modèle cross-chain via IBC est plus nativement intégré. En contrepartie, l'expressivité contractuelle est moindre et la maturité opérationnelle inférieure.
---
@@ -360,113 +186,139 @@ Les critères suivants sont retenus pour l'analyse comparative. Chaque critère
| Secret Network | ✓ | ✓✓ | ✓ | ✗ | ✓✓ | ✓✓ | N/A (règlement seul) | ✓ | ✓ | △ |
| Zcash | ✓ | ✓✓ | ✓ | ✗ | △ | ✗ | N/A (règlement seul) | ✗ | ✓✓ | ✗ |
| Oasis Network | ✓ | ✓✓ | ✓ | ✗ | ✓✓ | ✓✓ | N/A (règlement seul) | △ | ✓ | △ |
| Penumbra | ✓✓ | ✓✓ (ZK) | ✓ | ✗ | ✓✓ | △ | N/A (règlement seul) | ✓ | △ | △ |
| **Proposition** | **✓✓** | **✓✓** | **✓** | **✓✓** | **✓✓** | **✓✓** | **✓✓ (3 plans distincts)** | **✓✓** | **△** | **✓✓** |
*Notation : ✓✓ excellent, ✓ bon, △ partiel ou conditionnel, ✗ insuffisant, N/A non applicable*
> **Lecture de la colonne "Séparation découverte/règlement"** : Les systèmes notés N/A n'implémentent qu'une seule des deux fonctions (découverte ou règlement), sans prétendre à l'autre. Les systèmes notés ✗ couplent les deux dans un même protocole ou une même chaîne, créant des compromis défavorables. Seule la proposition formalise explicitement la séparation en trois plans indépendants avec des profils CAP distincts.
> **Lecture de la colonne "Séparation découverte/règlement"** : Les systèmes notés N/A n'implémentent qu'une seule des deux fonctions, sans prétendre à l'autre. Les systèmes notés ✗ couplent les deux dans un même protocole, créant des compromis défavorables. Seule la proposition formalise explicitement la séparation en trois plans indépendants avec des profils CAP distincts.
---
## 6. Positionnement de la Proposition par Rapport à l'Existant
### 6.1 L'Absence d'une Solution Intégrée dans l'État de l'Art
### 6.1 L'Absence d'une Solution Intégrée
L'analyse comparative révèle une lacune structurelle dans l'état de l'art : **aucun système existant ne combine simultanément l'ensemble des propriétés requises par le contexte GARDEN**. Les systèmes actuels se spécialisent sur un sous-ensemble de propriétés, laissant des gaps critiques selon leur domaine de conception.
Aucun système existant ne combine simultanément l'ensemble des propriétés requises par le contexte GARDEN. Ce n'est pas une surprise, les systèmes se spécialisent naturellement sur un sous-ensemble de propriétés qui correspondent à leur contexte de conception originel.
Les systèmes de découverte P2P (IPFS, libp2p, BitTorrent DHT) excellent en décentralisation et en scalabilité mais ignorent la confidentialité et la gestion de confiance. Les réseaux d'anonymisation (Tor, I2P) offrent une excellente confidentialité de transport mais ne fournissent ni découverte décentralisée, ni transactions monétaires, ni tolérance DTN. Les blockchains de consortium (Hyperledger Fabric) offrent confidentialité intra-consortium et finalité déterministe mais supposent une connectivité continue et ne s'intègrent pas avec une couche de découverte P2P. Les blockchains confidentielles (Secret Network, Oasis) offrent des smart contracts confidentiels mais présentent des dépendances matérielles problématiques et ne traitent pas la couche de découverte.
Les systèmes de découverte P2P excellent en décentralisation et en scalabilité mais ignorent la confidentialité et la gestion de confiance. Les réseaux d'anonymisation offrent une excellente confidentialité de transport mais ne fournissent ni découverte décentralisée, ni transactions monétaires, ni tolérance DTN. Les blockchains de consortium offrent confidentialité intra-consortium et finalité déterministe mais supposent une connectivité continue et ne s'intègrent pas avec une couche de découverte P2P. Les blockchains confidentielles offrent des smart contracts confidentiels mais présentent des dépendances matérielles et ne traitent pas la découverte.
### 6.2 La Proposition comme Synthèse Architecturale
La proposition se distingue de tous les systèmes existants par sa nature de **synthèse architecturale multi-couche**, combinant :
La proposition se distingue de tous les systèmes existants par sa nature de synthèse architecturale multi-couche :
1. **Couche de découverte** : DHT Kademlia privée (inspiration libp2p) + scoring comportemental multidimensionnel (absent de tous les systèmes existants) + adaptation DTN (absent de tous les systèmes existants) + gossip épidémique SWIM-adjacent [Das et al., 2002].
1. **Couche de découverte** : DHT Kademlia privée (inspiration libp2p) + scoring comportemental multidimensionnel + protocole SWIM complet avec membership épidémique. Aucun de ces éléments pris séparément n'est nouveau, leur combinaison dans un contexte hostile et embarqué constitue la contribution originale.
2. **Couche de données** : enregistrements signés + chiffrement de contenu bout-en-bout + attestations ZK (inspiration Filecoin PoSt, mais avec confidentialité cryptographique) + Compute-to-Data (inspiration Ocean Protocol, mais avec preuves ZK).
2. **Couche DTN** : cache de messages à deux niveaux (critique / modéré) avec persistance locale chiffrée, mécanisme de réveil intégré aux heartbeats existants sans goroutine additionnelle, et hiérarchie Nano/Maître pour les nœuds à très faible disponibilité avec réconciliation déterministe des conflits à la reconnexion.
3. **Couche de règlement** : architecture hybride intra/inter-consortium (Hyperledger Fabric + Secret Network / Cosmos + Secret Network) + gestion de consortiums à niveaux de confiance différenciés (absent de tous les systèmes existants comme propriété native).
3. **Couche de données** : enregistrements signés + chiffrement bout-en-bout + attestations cryptographiques de consommation + Compute-to-Data avec preuves ZK.
### 6.3 La Tolérance DTN : Le Gap le Plus Universel
4. **Couche de règlement** : architecture hybride intra/inter-consortium avec gestion de consortiums à niveaux de confiance différenciés, propriété absente de tous les systèmes existants comme fonctionnalité native. Piste privilégiée : zones Cosmos souveraines + règlement inter-consortium confidentiel via Secret Network (TEE) ou, à terme, Penumbra (ZK pur).
La tolérance aux réseaux DTN est la propriété la plus universellement absente des systèmes existants. Tous les systèmes analysés supposent implicitement ou explicitement une connectivité TCP continue :
- Les DHT Kademlia supposent une disponibilité suffisante des pairs pour maintenir les tables de routage
- Les blockchains supposent une connectivité entre validateurs pour atteindre le quorum de consensus
- Les systèmes de marketplace supposent la disponibilité en temps quasi-réel des parties contractantes
### 6.3 La Tolérance DTN : Un Gap Structurellement Adressé dans les Couches P2P
La proposition adresse ce gap en adaptant chaque couche aux contraintes DTN : TTL adaptatifs, stockage-et-retransmission, signature différée, heartbeats asynchrones accumulés. Cette adaptation systématique est, à notre connaissance, absente de tout système de marché de ressources décentralisé existant.
La tolérance DTN est la propriété la plus universellement absente des systèmes existants. Tous supposent une connectivité TCP continue, les DHT pour maintenir leurs tables de routage, les blockchains pour atteindre le quorum de consensus, les marketplaces pour la disponibilité des parties contractantes.
La proposition adresse ce gap de manière systématique dans les couches de découverte et de données. L'adaptation, TTL adaptatifs, cache de messages persistant, réveil piggybacked sur les heartbeats, délégation Nano/Maître pour les satellites, est cohérente et absente de tout système de marché de ressources décentralisé existant. Les détails de ces mécanismes sont documentés dans la proposition architecturale.
Le gap résiduel se situe dans la couche de règlement monétaire. Aucun système blockchain analysé ne gère nativement l'intermittence des validateurs sur de longues périodes. Cette limitation est à adresser au niveau du dimensionnement du validator set et d'une conception explicite des périodes d'isolation dans la configuration du consensus.
### 6.4 Piste Privilégiée pour le Règlement Monétaire : Cosmos avec Confidentialité Déléguée
L'analyse comparative fait émerger une piste préférentielle pour la couche de règlement monétaire, la couche pour laquelle les exigences de finalité déterministe, de confidentialité et de gouvernance souveraine sont les plus contraignantes.
L'écosystème Cosmos est le seul parmi tous les systèmes analysés à satisfaire simultanément trois conditions structurelles : souveraineté (chaque consortium opère sa propre blockchain sans tutelle externe), interopérabilité standardisée (IBC avec guaranties formelles), et accessibilité pratique (bootstrap en semaines avec le SDK + ignite CLI). La confidentialité, absente d'une zone standard, est apportée par délégation via IBC à Secret Network pour les contrats de règlement inter-consortium.
L'architecture cible pour GARDEN se décline ainsi :
```
Zone Cosmos Consortium A ─── IBC ───┐
Zone Cosmos Consortium B ─── IBC ───┤──► Secret Network
Zone Cosmos Consortium C ─── IBC ───┘ (règlement inter-consortium confidentiel)
```
Chaque zone de consortium gère son propre ledger intra-consortium. Les transactions inter-consortium, les plus sensibles, transitent par Secret Network, où un smart contract confidentiel exécute le règlement sans exposer montants ni parties.
La dépendance SGX de Secret Network est un compromis pragmatique à assumer lucidement : c'est aujourd'hui la solution de confidentialité des smart contracts la plus mature pour l'écosystème Cosmos. La conception architecturale doit anticiper une migration vers Penumbra, zone Cosmos dont la confidentialité repose sur des zk-SNARKs sans dépendance matérielle, dont le développement avance activement. Les contrats de règlement doivent être conçus comme une implémentation interchangeable d'une interface, non comme une dépendance irréversible.
Il vaut la peine de le rappeler explicitement : cette piste concerne **exclusivement la couche de règlement monétaire**. Les couches de découverte P2P et de gestion des données opèrent selon des mécanismes distincts documentés dans les propositions architecturales associées, la séparation entre ces couches étant elle-même l'une des contributions originales de la proposition.
---
## Références Bibliographiques
**[Androulaki et al., 2018]** Androulaki, E., et al. (2018). Hyperledger Fabric: a distributed operating system for permissioned blockchains. In *Proceedings of the 13th EuroSys Conference*, article 30.
**[1] [Androulaki et al., 2018]** Androulaki, E., et al. (2018). Hyperledger Fabric: a distributed operating system for permissioned blockchains. In *Proceedings of the 13th EuroSys Conference*, article 30.
**[Ben-Sasson et al., 2014]** Ben-Sasson, E., Chiesa, A., Garman, C., Green, M., Miers, I., Tromer, E., & Virza, M. (2014). Zerocash: Decentralized Anonymous Payments from Bitcoin. In *Proceedings of the 2014 IEEE S&P*, pp. 459474.
**[2] [Ben-Sasson et al., 2014]** Ben-Sasson, E., et al. (2014). Zerocash: Decentralized Anonymous Payments from Bitcoin. In *Proceedings of the 2014 IEEE S&P*, pp. 459474.
**[Benet, 2014]** Benet, J. (2014). IPFS - Content Addressed, Versioned, P2P File System. *arXiv preprint* arXiv:1407.3561.
**[3] [Benet, 2014]** Benet, J. (2014). IPFS - Content Addressed, Versioned, P2P File System. *arXiv preprint* arXiv:1407.3561.
**[Brewer, 2000]** Brewer, E. A. (2000). Towards robust distributed systems. In *Proceedings of PODC 2000*, pp. 7.
**[4] [Brewer, 2000]** Brewer, E. A. (2000). Towards robust distributed systems. In *Proceedings of PODC 2000*, pp. 7.
**[Buterin, 2014]** Buterin, V. (2014). *A Next-Generation Smart Contract and Decentralized Application Platform*. Ethereum Whitepaper. https://ethereum.org/whitepaper
**[5] [Buterin, 2014]** Buterin, V. (2014). *A Next-Generation Smart Contract and Decentralized Application Platform*. Ethereum Whitepaper.
**[Cerf et al., 2007]** Cerf, V., et al. (2007). Delay-Tolerant Networking Architecture. *RFC 4838*, IETF.
**[6] [Cerf et al., 2007]** Cerf, V., et al. (2007). Delay-Tolerant Networking Architecture. *RFC 4838*, IETF.
**[Costan & Devadas, 2016]** Costan, V., & Devadas, S. (2016). Intel SGX Explained. *IACR Cryptology ePrint Archive*, Report 2016/086.
**[7] [Costan & Devadas, 2016]** Costan, V., & Devadas, S. (2016). Intel SGX Explained. *IACR Cryptology ePrint Archive*, Report 2016/086.
**[Daian et al., 2020]** Daian, P., et al. (2020). Flash Boys 2.0. In *Proceedings of the 2020 IEEE S&P*, pp. 910927.
**[8] [Daian et al., 2020]** Daian, P., et al. (2020). Flash Boys 2.0. In *Proceedings of the 2020 IEEE S&P*, pp. 910927.
**[Das et al., 2002]** Das, A., Gupta, I., & Motivala, A. (2002). SWIM: Scalable Weakly-consistent Infection-style Process Group Membership Protocol. In *Proceedings of DSN 2002*, pp. 303312.
**[9] [Das et al., 2002]** Das, A., Gupta, I., & Motivala, A. (2002). SWIM: Scalable Weakly-consistent Infection-style Process Group Membership Protocol. In *Proceedings of DSN 2002*, pp. 303312.
**[Dingledine, Mathewson & Syverson, 2004]** Dingledine, R., Mathewson, N., & Syverson, P. (2004). Tor: The Second-Generation Onion Router. In *Proceedings of the 13th USENIX Security Symposium*, pp. 303320.
**[10] [Dingledine, Mathewson & Syverson, 2004]** Dingledine, R., Mathewson, N., & Syverson, P. (2004). Tor: The Second-Generation Onion Router. In *Proceedings of the 13th USENIX Security Symposium*, pp. 303320.
**[Douceur, 2002]** Douceur, J. R. (2002). The Sybil Attack. In *Proceedings of IPTPS 2002*, LNCS 2429, pp. 251260.
**[11] [Douceur, 2002]** Douceur, J. R. (2002). The Sybil Attack. In *Proceedings of IPTPS 2002*, LNCS 2429, pp. 251260.
**[Fall, 2003]** Fall, K. (2003). A delay-tolerant network architecture for challenged internets. In *Proceedings of SIGCOMM 2003*, pp. 2734.
**[12] [Fall, 2003]** Fall, K. (2003). A delay-tolerant network architecture for challenged internets. In *Proceedings of SIGCOMM 2003*, pp. 2734.
**[Fischer, Lynch & Paterson, 1985]** Fischer, M. J., Lynch, N. A., & Paterson, M. S. (1985). Impossibility of distributed consensus with one faulty process. *JACM*, 32(2), 374382.
**[13] [Fischer, Lynch & Paterson, 1985]** Fischer, M. J., Lynch, N. A., & Paterson, M. S. (1985). Impossibility of distributed consensus with one faulty process. *JACM*, 32(2), 374382.
**[Gilbert & Lynch, 2002]** Gilbert, S., & Lynch, N. (2002). Brewer's conjecture and the feasibility of consistent, available, partition-tolerant web services. *ACM SIGACT News*, 33(2), 5159.
**[14] [Gilbert & Lynch, 2002]** Gilbert, S., & Lynch, N. (2002). Brewer's conjecture and the feasibility of consistent, available, partition-tolerant web services. *ACM SIGACT News*, 33(2), 5159.
**[Goldwasser, Micali & Rackoff, 1989]** Goldwasser, S., Micali, S., & Rackoff, C. (1989). The knowledge complexity of interactive proof systems. *SIAM Journal on Computing*, 18(1), 186208.
**[15] [Goldwasser, Micali & Rackoff, 1989]** Goldwasser, S., Micali, S., & Rackoff, C. (1989). The knowledge complexity of interactive proof systems. *SIAM Journal on Computing*, 18(1), 186208.
**[Golem Network, 2016]** Golem Network (2016). *Golem: A decentralized computation network*. Whitepaper. https://golem.network/golem_whitepaper.pdf
**[16] [Golem Network, 2016]** Golem Network (2016). *Golem: A decentralized computation network*. Whitepaper.
**[Groth, 2016]** Groth, J. (2016). On the size of pairing-based non-interactive arguments. In *Proceedings of EUROCRYPT 2016*, LNCS 9666, pp. 305326.
**[17] [Groth, 2016]** Groth, J. (2016). On the size of pairing-based non-interactive arguments. In *Proceedings of EUROCRYPT 2016*, LNCS 9666, pp. 305326.
**[Heilman et al., 2015]** Heilman, E., Kendler, A., Zohar, A., & Goldberg, S. (2015). Eclipse Attacks on Bitcoin's Peer-to-Peer Network. In *Proceedings of the 24th USENIX Security Symposium*, pp. 129144.
**[18] [Heilman et al., 2015]** Heilman, E., et al. (2015). Eclipse Attacks on Bitcoin's Peer-to-Peer Network. In *Proceedings of the 24th USENIX Security Symposium*, pp. 129144.
**[Hopwood et al., 2016]** Hopwood, D., Bowe, S., Hornby, T., & Wilcox, N. (2016). *Zcash Protocol Specification*. Electric Coin Company.
**[19] [Hopwood et al., 2016]** Hopwood, D., et al. (2016). *Zcash Protocol Specification*. Electric Coin Company.
**[Kwon & Buchman, 2016]** Kwon, J., & Buchman, E. (2016). *Cosmos: A Network of Distributed Ledgers*. Whitepaper.
**[20] [Kwon, 2014]** Kwon, J. (2014). *Tendermint: Consensus without Mining*. Draft whitepaper.
**[Lamport, Shostak & Pease, 1982]** Lamport, L., Shostak, R., & Pease, M. (1982). The Byzantine Generals Problem. *ACM TOPLAS*, 4(3), 382401.
**[21] [Kwon & Buchman, 2016]** Kwon, J., & Buchman, E. (2016). *Cosmos: A Network of Distributed Ledgers*. Whitepaper.
**[Loewenstern & Norberg, 2008]** Loewenstern, A., & Norberg, A. (2008). *DHT Protocol (BEP 5)*. BitTorrent Enhancement Proposal.
**[22] [Lamport, Shostak & Pease, 1982]** Lamport, L., Shostak, R., & Pease, M. (1982). The Byzantine Generals Problem. *ACM TOPLAS*, 4(3), 382401.
**[Luu et al., 2016]** Luu, L., Chu, D.-H., Olickel, H., Saxena, P., & Hobor, A. (2016). Making Smart Contracts Smarter. In *Proceedings of CCS 2016*, pp. 254269.
**[23] [Loewenstern & Norberg, 2008]** Loewenstern, A., & Norberg, A. (2008). *DHT Protocol (BEP 5)*. BitTorrent Enhancement Proposal.
**[Maymounkov & Mazières, 2002]** Maymounkov, P., & Mazières, D. (2002). Kademlia: A Peer-to-Peer Information System Based on the XOR Metric. In *Proceedings of IPTPS 2002*, LNCS 2429, pp. 5365.
**[24] [Luu et al., 2016]** Luu, L., et al. (2016). Making Smart Contracts Smarter. In *Proceedings of CCS 2016*, pp. 254269.
**[Meiklejohn et al., 2013]** Meiklejohn, S., et al. (2013). A Fistful of Bitcoins. In *Proceedings of IMC 2013*, pp. 127140.
**[25] [Maymounkov & Mazières, 2002]** Maymounkov, P., & Mazières, D. (2002). Kademlia: A Peer-to-Peer Information System Based on the XOR Metric. In *Proceedings of IPTPS 2002*, LNCS 2429, pp. 5365.
**[Murdoch & Danezis, 2005]** Murdoch, S. J., & Danezis, G. (2005). Low-Cost Traffic Analysis of Tor. In *Proceedings of the 2005 IEEE S&P*, pp. 183195.
**[26] [Meiklejohn et al., 2013]** Meiklejohn, S., et al. (2013). A Fistful of Bitcoins. In *Proceedings of IMC 2013*, pp. 127140.
**[Nakamoto, 2008]** Nakamoto, S. (2008). Bitcoin: A Peer-to-Peer Electronic Cash System. https://bitcoin.org/bitcoin.pdf
**[27] [Murdoch & Danezis, 2005]** Murdoch, S. J., & Danezis, G. (2005). Low-Cost Traffic Analysis of Tor. In *Proceedings of the 2005 IEEE S&P*, pp. 183195.
**[Oasis Labs, 2020]** Oasis Network (2020). *Oasis Network Primer*. https://oasisprotocol.org/primer
**[28] [Nakamoto, 2008]** Nakamoto, S. (2008). Bitcoin: A Peer-to-Peer Electronic Cash System. https://bitcoin.org/bitcoin.pdf
**[Perrin, 2018]** Perrin, T. (2018). *The Noise Protocol Framework*. https://noiseprotocol.org/noise.pdf
**[29] [Oasis Labs, 2020]** Oasis Network (2020). *Oasis Network Primer*. https://oasisprotocol.org/primer
**[Protocol Labs, 2017]** Protocol Labs (2017). *Filecoin: A Decentralized Storage Network*. Whitepaper.
**[30] [Penumbra Labs, 2022]** Penumbra Labs (2022). *Penumbra: A Fully Private Proof-of-Stake Network for the Cosmos Ecosystem*. Technical specification. https://penumbra.zone
**[Stoica et al., 2003]** Stoica, I., et al. (2003). Chord: A scalable peer-to-peer lookup protocol for internet applications. *IEEE/ACM Transactions on Networking*, 11(1), 1732.
**[31] [Perrin, 2018]** Perrin, T. (2018). *The Noise Protocol Framework*. https://noiseprotocol.org/noise.pdf
**[Sun et al., 2017]** Sun, S.-F., Au, M. H., Liu, J. K., & Yuen, T. H. (2017). RingCT 2.0. In *Proceedings of ESORICS 2017*, LNCS 10493, pp. 456474.
**[32] [Protocol Labs, 2017]** Protocol Labs (2017). *Filecoin: A Decentralized Storage Network*. Whitepaper.
**[Szabo, 1997]** Szabo, N. (1997). Formalizing and securing relationships on public networks. *First Monday*, 2(9).
**[33] [Stoica et al., 2003]** Stoica, I., et al. (2003). Chord: A scalable peer-to-peer lookup protocol for internet applications. *IEEE/ACM Transactions on Networking*, 11(1), 1732.
**[W3C, 2022]** W3C (2022). *Decentralized Identifiers (DIDs) v1.0*. https://www.w3.org/TR/did-core/
**[34] [Sun et al., 2017]** Sun, S.-F., et al. (2017). RingCT 2.0. In *Proceedings of ESORICS 2017*, LNCS 10493, pp. 456474.
**[Wood, 2014]** Wood, G. (2014). *Ethereum: A Secure Decentralised Generalised Transaction Ledger*. Ethereum Yellow Paper.
**[35] [Szabo, 1997]** Szabo, N. (1997). Formalizing and securing relationships on public networks. *First Monday*, 2(9).
**[Wood, 2016]** Wood, G. (2016). *Polkadot: Vision for a Heterogeneous Multi-Chain Framework*. Whitepaper.
**[36] [W3C, 2022]** W3C (2022). *Decentralized Identifiers (DIDs) v1.0*. https://www.w3.org/TR/did-core/
**[37] [Wood, 2014]** Wood, G. (2014). *Ethereum: A Secure Decentralised Generalised Transaction Ledger*. Ethereum Yellow Paper.
**[38] [Wood, 2016]** Wood, G. (2016). *Polkadot: Vision for a Heterogeneous Multi-Chain Framework*. Whitepaper.
+135 -144
View File
@@ -1,18 +1,18 @@
# Proposition d'Architecture Minimale pour un Réseau Décentralisé Souverain dans un Contexte Embarqué et Hostile
**Catégorie** : Architecture des systèmes distribués Proposition de conception
**Catégorie** : Architecture des systèmes distribués, Proposition de conception
**Domaine d'application** : Systèmes embarqués, contexte spatial, réseaux DTN, environnements hostiles
**Version** : 1.0 Mars 2026
**Version** : 1.0, Mars 2026
---
## Résumé
Ce document présente une proposition d'architecture minimale pour un réseau distribué décentralisé répondant aux exigences de souveraineté, de confidentialité, et de tolérance aux disruptions réseau dans des environnements hostiles tels que les systèmes spatiaux embarqués ou les réseaux opérant en présence d'adversaires actifs. Le contexte cible désigné GARDEN (Generic Architecture for Resilient Decentralized Execution Networks) impose des contraintes qui rendent inadaptée toute solution standard : connectivité intermittente (paradigme DTN [Fall, 2003 ; Cerf et al., 2007]), présence d'acteurs à niveaux de confiance hétérogènes incluant des adversaires d'État, contraintes énergétiques et de bande passante sévères, et exigence de souveraineté absolue des données sur les acteurs externes.
Ce document présente une proposition d'architecture minimale pour un réseau distribué décentralisé répondant aux exigences de souveraineté, de confidentialité, et de tolérance aux disruptions réseau dans des environnements hostiles tels que les systèmes spatiaux embarqués ou les réseaux opérant en présence d'adversaires actifs. Le contexte cible, désigné GARDEN (Generic Architecture for Resilient Decentralized Execution Networks), impose des contraintes qui rendent inadaptée toute solution standard : connectivité intermittente (paradigme DTN), présence d'acteurs à niveaux de confiance hétérogènes incluant des adversaires d'État, contraintes énergétiques et de bande passante sévères, et exigence de souveraineté absolue des données sur les acteurs externes.
L'architecture proposée repose sur une séparation stricte en trois plans indépendants : le plan de découverte de pairs, le plan de transactions de ressources, et le plan de règlement monétaire. Cette séparation n'est pas un choix stylistique mais une nécessité de sécurité : chaque plan présente des exigences de disponibilité, de cohérence et de confidentialité fondamentalement différentes, et leur fusion dans un protocole unique crée des couplages qui dégradent les garanties de sécurité de chacun.
La proposition couvre en détail les sept couches fonctionnelles de cette architecture : le transport chiffré (Noise Protocol Framework [Perrin, 2018]), la découverte DHT avec scoring comportemental multidimensionnel, la gestion des enregistrements de ressources avec chiffrement bout-en-bout, l'attestation de consommation par preuves à divulgation nulle (ZK-proofs [Groth, 2016]), le règlement monétaire par blockchain confidentielle (analyse comparative de dix solutions), et la gouvernance des consortiums à confiance relative.
La proposition couvre en détail les sept couches fonctionnelles de cette architecture : le transport chiffré (Noise Protocol Framework), la découverte DHT avec scoring comportemental multidimensionnel, la gestion des enregistrements de ressources avec chiffrement bout-en-bout, l'attestation de consommation par preuves à divulgation nulle (ZK-proofs), le règlement monétaire par blockchain confidentielle (analyse comparative de dix solutions), et la gouvernance des consortiums à confiance relative.
Huit verrous conceptuels et technologiques sont identifiés et analysés : identité sans autorité centrale (TOFU), bootstrap trustless, résistance Sybil sans coût cryptoéconomique, cohérence CAP dans un réseau AP, détection de panne sans oracle (FLP), confidentialité des transactions on-chain, transactions intermittentes en contexte DTN, et oracle problem pour les preuves de consommation réelle. Pour chaque verrou, l'état de l'art des solutions disponibles est présenté avec leurs limites résiduelles.
@@ -22,29 +22,29 @@ Huit verrous conceptuels et technologiques sont identifiés et analysés : ident
Les principes suivants constituent les invariants de l'architecture proposée. Tout compromis sur ces principes dégrade structurellement la sécurité du système dans le contexte hostile cible.
### Principe 1 Souveraineté par Défaut
### Principe 1, Souveraineté par Défaut
Aucune donnée ne doit quitter le périmètre de confiance d'un acteur sans son consentement explicite. Ce principe s'applique à toutes les couches : les enregistrements de présence dans la DHT, les transactions de ressources, et le règlement monétaire. La souveraineté s'entend au sens technique (contrôle cryptographique du cycle de vie des données) et opérationnel (possibilité de révocation et d'expiration contrôlée).
### Principe 2 Confiance Relative et Continue (Non-Binaire)
### Principe 2, Confiance Relative et Continue (Non-Binaire)
Le modèle de confiance ne peut être binaire dans un réseau hostile. Chaque pair se voit associer un score de confiance multidimensionnel calculé sur la base de comportements observés (disponibilité historique, précision des challenges, cohérence des données annoncées, diversité réseau). Ce score évolue dans le temps et détermine dynamiquement les interactions autorisées. L'impossibilité de distinguer panne et lenteur (FLP [Fischer, Lynch & Paterson, 1985]) implique que ce score est probabiliste par nature.
Le modèle de confiance ne peut être binaire dans un réseau hostile. Chaque pair se voit associer un score de confiance multidimensionnel calculé sur la base de comportements observés (disponibilité historique, précision des challenges, cohérence des données annoncées, diversité réseau). Ce score évolue dans le temps et détermine dynamiquement les interactions autorisées. L'impossibilité de distinguer panne et lenteur (résultat FLP) implique que ce score est probabiliste par nature.
### Principe 3 Disponibilité Prioritaire pour la Découverte, Cohérence Prioritaire pour le Règlement
### Principe 3, Disponibilité Prioritaire pour la Découverte, Cohérence Prioritaire pour le Règlement
La couche de découverte adopte délibérément le profil AP du théorème CAP [Brewer, 2000 ; Gilbert & Lynch, 2002] : elle doit rester opérationnelle même en cas de partitionnement, au prix d'une cohérence éventuellement relâchée. La couche de règlement monétaire adopte le profil CP : la cohérence forte est requise pour la prévention du double-spend, au prix d'une indisponibilité temporaire lors des partitions.
La couche de découverte adopte délibérément le profil AP du théorème CAP : elle doit rester opérationnelle même en cas de partitionnement, au prix d'une cohérence éventuellement relâchée. La couche de règlement monétaire adopte le profil CP : la cohérence forte est requise pour la prévention du double-spend, au prix d'une indisponibilité temporaire lors des partitions.
### Principe 4 Opérabilité en Mode Complètement Autonome
### Principe 4, Opérabilité en Mode Complètement Autonome
Un nœud doit pouvoir opérer prendre des décisions, gérer ses ressources locales, maintenir un état cohérent sans aucune connexion réseau pendant des durées pouvant atteindre plusieurs jours. Les protocoles de resynchronisation après reconnexion doivent être déterministes, convergents, et capables de gérer les conflits d'état accumulés pendant la période d'isolation.
Un nœud doit pouvoir opérer, prendre des décisions, gérer ses ressources locales, maintenir un état cohérent, sans aucune connexion réseau pendant des durées pouvant atteindre plusieurs jours. Les protocoles de resynchronisation après reconnexion doivent être déterministes, convergents, et capables de gérer les conflits d'état accumulés pendant la période d'isolation.
### Principe 5 Opacité des Flux (Confidentialité des Métadonnées)
### Principe 5, Opacité des Flux (Confidentialité des Métadonnées)
Le chiffrement de contenu est nécessaire mais insuffisant. L'architecture doit minimiser les informations révélées par les métadonnées de trafic : fréquence des échanges, volume, topologie des connexions. Des techniques de padding temporel, de trafic fictif calibré, et de routage multi-sauts doivent être employées sur les liens exposés à des observateurs potentiellement adversariaux.
### Principe 6 Minimisation de la Surface d'Attaque
### Principe 6, Minimisation de la Surface d'Attaque
Chaque couche de l'architecture ne doit exposer que les fonctionnalités strictement nécessaires à son rôle. La couche de découverte ne doit pas avoir accès aux clés de chiffrement des transactions ; la couche de règlement ne doit pas avoir connaissance de la topologie du réseau de découverte. Cette isolation minimise l'impact d'une compromission partielle.
Chaque couche de l'architecture ne doit exposer que les fonctionnalités strictement nécessaires à son rôle. La couche de découverte ne doit pas avoir accès aux clés de chiffrement des transactions; la couche de règlement ne doit pas avoir connaissance de la topologie du réseau de découverte. Cette isolation minimise l'impact d'une compromission partielle.
---
@@ -54,31 +54,15 @@ L'architecture proposée repose sur une séparation stricte en trois plans fonct
### Plan de Découverte
**Objectif** : permettre à un nœud de localiser d'autres nœuds offrant des ressources compatibles, d'évaluer leur qualité, et de maintenir un réseau de voisinage robuste.
**Exigences** : haute disponibilité (AP), tolérance aux partitions, faible latence de découverte, résistance aux manipulations de routage. La cohérence n'est pas critique : une vue légèrement obsolète du réseau est acceptable.
**Ce qui ne doit PAS figurer dans ce plan** : le contenu des transactions, les identités réelles des acteurs, les montants échangés, ou tout élément permettant d'inférer des stratégies opérationnelles.
La couche de découverte permet à un nœud de localiser des pairs offrant des ressources compatibles, d'évaluer leur qualité, et de maintenir un réseau de voisinage robuste. Elle adopte délibérément le profil AP du théorème CAP, disponibilité prioritaire sur cohérence, car une vue légèrement obsolète du réseau est acceptable là où une indisponibilité totale lors d'une partition ne l'est pas. Cette couche ne doit porter aucune information transactionnelle : ni contenu des échanges, ni identités réelles, ni montants. Toute information permettant d'inférer des stratégies opérationnelles depuis la DHT constitue une fuite de confidentialité, pas un problème de découverte.
### Plan de Données et Ressources
**Objectif** : permettre à des acteurs de décrire, offrir, découvrir et transacter des ressources (compute, stockage, données, workflows) de manière sécurisée et souveraine.
**Exigences** : intégrité forte (enregistrements signés), confidentialité du contenu (chiffrement bout-en-bout), souveraineté du cycle de vie (TTL contrôlé par le créateur), attestation de consommation vérifiable sans révélation du contenu.
**Ce qui ne doit PAS figurer dans ce plan** : le règlement monétaire (séparation de la couche applicative et de la couche financière), ni les détails de routage de la couche de découverte.
Ce plan prend en charge la description, l'offre et la transaction de ressources, compute, stockage, données, workflows, avec des garanties de sécurité et de souveraineté fortes. Les enregistrements sont signés par leur créateur, leur contenu est chiffré bout-en-bout, leur cycle de vie est sous contrôle du créateur via un TTL explicite, et leur consommation peut être attestée sans révéler le contenu. Le règlement monétaire n'a pas sa place ici : séparer la couche applicative de la couche financière est une nécessité architecturale, non un choix stylistique.
### Plan de Règlement Monétaire
**Objectif** : régler les transactions monétaires résultant de la consommation de ressources, de manière automatisée, confidentielle, et résistante à la censure.
**Exigences** : finalité déterministe ou quasi-déterministe, confidentialité des montants et des parties, smart contracts pour l'automatisation du règlement, gouvernance de consortium, résistance à la censure par des validateurs adversariaux.
**Pourquoi ces trois plans doivent rester indépendants** :
La couche de découverte optimise pour la disponibilité et la performance de routage — des propriétés antagonistes avec la confidentialité forte. Fusionner les couches de découverte et de données exposerait les patterns d'accès aux ressources à tout observateur participant à la DHT. La couche de règlement monétaire requiert une cohérence forte et une finalité déterministe — des propriétés incompatibles avec le profil AP de la découverte. Un seul protocole ne peut satisfaire simultanément ces exigences contradictoires.
Analogie : le réseau téléphonique (couche de transport) ne gère pas le réseau bancaire (couche de règlement), même si les deux transportent des informations liées à des transactions économiques.
Ce plan règle les compensations monétaires résultant de la consommation attestée de ressources. Ses exigences sont l'inverse du plan de découverte : finalité déterministe, cohérence forte, résistance à la censure par des validateurs adversariaux, smart contracts pour l'automatisation du paiement conditionnel. Un seul protocole ne peut satisfaire simultanément ces exigences et celles de la découverte, la fusion dégradrait inévitablement les garanties sur au moins une dimension. C'est la même raison pour laquelle le réseau téléphonique et le réseau bancaire sont des infrastructures distinctes, quand bien même les deux transportent des informations liées à des transactions économiques.
---
@@ -86,19 +70,19 @@ Analogie : le réseau téléphonique (couche de transport) ne gère pas le rése
### 3.1 DHT Kademlia avec Espace de Noms Privé
La DHT Kademlia [Maymounkov & Mazières, 2002] constitue la base la plus adaptée pour la couche de découverte décentralisée. Son routage XOR en O(log n) sauts, sa robustesse au churn, et son implémentation dans de nombreux frameworks (libp2p, notamment) en font le choix le plus mature pour les réseaux P2P décentralisés à grande échelle.
La DHT Kademlia [18] constitue la base la plus adaptée pour la couche de découverte décentralisée. Son routage XOR en O(log n) sauts, sa robustesse au churn, et son implémentation dans de nombreux frameworks (libp2p, notamment) en font le choix le plus mature pour les réseaux P2P décentralisés à grande échelle.
Pour un réseau privé ou semi-privé, l'espace de noms DHT doit être isolé de la DHT globale publique. Cette isolation est réalisée par une clé de réseau (network key) distincte, empêchant la découverte croisée avec des nœuds appartenant à d'autres réseaux. S/Kademlia [Baumgart & Meinert, 2007] étend Kademlia avec des contraintes cryptographiques sur la génération des identifiants de nœuds (preuve de travail légère sur le NodeID) et des signatures sur les messages de routage, réduisant significativement les vecteurs d'empoisonnement.
Pour un réseau privé ou semi-privé, l'espace de noms DHT doit être isolé de la DHT globale publique. Cette isolation est réalisée par une clé de réseau (network key) distincte, empêchant la découverte croisée avec des nœuds appartenant à d'autres réseaux. S/Kademlia [2] étend Kademlia avec des contraintes cryptographiques sur la génération des identifiants de nœuds (preuve de travail légère sur le NodeID) et des signatures sur les messages de routage, réduisant significativement les vecteurs d'empoisonnement.
Il n'existe pas d'alternative réaliste à Kademlia pour un réseau P2P décentralisé à cette échelle : Chord [Stoica et al., 2003] est plus simple mais moins robuste au churn ; Pastry et Tapestry présentent des propriétés similaires mais un écosystème d'implémentation plus réduit.
Il n'existe pas d'alternative réaliste à Kademlia pour un réseau P2P décentralisé à cette échelle : Chord [23] est plus simple mais moins robuste au churn; Pastry et Tapestry présentent des propriétés similaires mais un écosystème d'implémentation plus réduit.
### 3.2 Transport Chiffré Multi-Protocole
Le Noise Protocol Framework [Perrin, 2018] fournit la primitive de transport sécurisé. Le pattern Noise_XX permet une authentification mutuelle des parties par échange de clés publiques, sans infrastructure PKI centralisée. La légèreté du framework (implémentation en quelques centaines de lignes, sans dépendance à une bibliothèque X.509) le rend particulièrement adapté aux contraintes embarquées.
Le Noise Protocol Framework [22] fournit la primitive de transport sécurisé. Le pattern Noise_XX permet une authentification mutuelle des parties par échange de clés publiques, sans infrastructure PKI centralisée. La légèreté du framework (implémentation en quelques centaines de lignes, sans dépendance à une bibliothèque X.509) le rend particulièrement adapté aux contraintes embarquées.
Pour les réseaux de niveau de confiance élevée (consortium fermé), une clé pré-partagée (PSK) peut être incorporée dans le handshake Noise (pattern Noise_XXpsk), offrant une couche d'authentification supplémentaire qui garantit qu'un nœud non-membre du consortium ne peut même pas établir une connexion, réduisant drastiquement la surface d'attaque Sybil.
Le support multi-protocole (TCP, QUIC, WebTransport selon la disponibilité du lien) permet d'adapter le transport aux contraintes du lien physique, en particulier dans les environnements DTN où TCP peut être remplacé par des protocoles de couche bundle [Cerf et al., 2007].
Le support multi-protocole (TCP, QUIC, WebTransport selon la disponibilité du lien) permet d'adapter le transport aux contraintes du lien physique, en particulier dans les environnements DTN où TCP peut être remplacé par des protocoles de couche bundle.
### 3.3 Bootstrap Minimaliste
@@ -112,19 +96,19 @@ Le problème du premier contact est inévitable dans tout réseau décentralisé
Le scoring comportemental constitue le mécanisme primaire d'évaluation de la qualité et de la fiabilité des pairs. La proposition retient une formule à sept dimensions, chacune justifiée par un vecteur de menace distinct :
**Dimension 1 — Ratio d'uptime (poids : 0.20)** : mesure la disponibilité historique du pair, en tenant compte des fenêtres de contact prévues. Un pair disponible 95% du temps dans ses fenêtres de contact prévues mérite une évaluation haute. Cette dimension pénalise les pairs instables ou éphémères (vecteur anti-Sybil par coût temporel).
**Ratio d'uptime (20 %)** : mesure la disponibilité historique du pair en tenant compte des fenêtres de contact prévues. Un pair disponible 95 % du temps dans ses fenêtres prévisibles mérite une évaluation haute. Cette dimension pénalise les pairs instables ou éphémères, un coût temporel qui freine les identités Sybil à durée de vie courte.
**Dimension 2 — Latence normalisée (poids : 0.15)** : mesure le temps de réponse aux requêtes, normalisé par la latence attendue selon le type de lien. Cette dimension pénalise les pairs surchargés ou géographiquement distants sans que cela constitue un signal de compromission.
**Latence normalisée (15 %)** : mesure le temps de réponse aux requêtes, normalisé par la latence attendue selon le type de lien. Elle pénalise les pairs surchargés ou géographiquement trop distants, sans que cela constitue un signal de compromission.
**Dimension 3 — Précision des challenges (poids : 0.25)** : des challenges cryptographiques périodiques (écho de données DHT, challenge de contenu connu) permettent de vérifier que le pair héberge réellement les données qu'il annonce. Un pair falsifiant sa capacité de stockage ou de traitement échouera sur ces challenges. C'est la dimension la plus résistante à la manipulation car elle requiert une réponse correcte à une question que l'adversaire ne peut anticiper.
**Précision des challenges (25 %)** : des challenges cryptographiques périodiques, écho de données DHT, vérification de contenu connu, permettent de vérifier que le pair héberge réellement les données qu'il annonce. C'est la dimension la plus résistante à la manipulation : elle requiert une réponse correcte à une question que l'adversaire ne peut anticiper. Elle constitue le vecteur de détection principal.
**Dimension 4 — Diversité réseau (poids : 0.15)** : mesure la diversité des sous-réseaux IP des pairs que ce nœud connaît, favorisant les pairs bien connectés à des régions réseau variées. Cette dimension pénalise implicitement les clusters de nœuds contrôlés par un même acteur (colluseurs sur le même réseau).
**Diversité réseau (15 %)** : mesure la diversité des sous-réseaux IP des pairs que ce nœud connaît. Elle favorise les pairs bien connectés à des régions réseau variées et pénalise implicitement les clusters de nœuds contrôlés par un même acteur.
**Dimension 5 — Taux de remplissage inverse (poids : 0.10)** : dans un contexte de marché de ressources, un pair offrant des ressources très chargées est moins utile qu'un pair offrant des ressources disponibles. Cette dimension oriente naturellement les nouveaux clients vers les pairs les moins sollicités, équilibrant la charge du réseau.
**Taux de remplissage inverse (10 %)** : dans un marché de ressources, un pair offrant des capacités très chargées est moins utile qu'un pair disponible. Cette dimension oriente naturellement les nouveaux clients vers les pairs les moins sollicités, équilibrant la charge du réseau sans coordination centrale.
**Dimension 6 — Cohérence des témoins (poids : 0.10)** : les observations d'un pair par des témoins tiers (autres pairs qui l'ont récemment contacté) sont corrélées avec les observations directes. Une incohérence forte entre les témoignages et les observations directes signale une possible compromission ou une collusion localisée.
**Cohérence des témoins (10 %)** : les observations d'un pair par des témoins tiers (autres pairs qui l'ont récemment contacté) sont comparées aux observations directes. Une incohérence forte signale une possible compromission localisée ou une collusion.
**Dimension 7 — Fiabilité DHT (poids : 0.05)** : mesure la probabilité que les enregistrements stockés par ce pair soient restitués correctement à des requêtes ultérieures. Cette dimension détecte les pairs qui acceptent des enregistrements sans les stocker (comportement parasite) ou qui altèrent les enregistrements confiés.
**Fiabilité DHT (5 %)** : mesure la probabilité que les enregistrements confiés à ce pair soient restitués correctement. Elle détecte les pairs qui acceptent des enregistrements sans les stocker (comportement parasite) ou qui les altèrent.
**Score global** :
```
@@ -143,7 +127,7 @@ Typiquement : `Seuil_min(age) = min(80, 20 + 60 × age/24h)`, démarrant à 20%
### 3.6 Protection Contre l'Isolement Total
Un invariant critique de sécurité : **le dernier pair actif d'un nœud ne peut jamais être évincé pour raison de score insuffisant seul**. Si un nœud ne dispose que d'un unique pair actif, le maintien de cette connexion, même avec un pair de score médiocre, est préférable à l'isolement complet qui rendrait le nœud aveugle et muet. L'éviction du dernier pair ne peut être déclenchée que par une preuve positive de comportement malveillant (challenge échoué, signature invalide) non par un score passant sous un seuil.
Un invariant critique de sécurité : **le dernier pair actif d'un nœud ne peut jamais être évincé pour raison de score insuffisant seul**. Si un nœud ne dispose que d'un unique pair actif, le maintien de cette connexion, même avec un pair de score médiocre, est préférable à l'isolement complet qui rendrait le nœud aveugle et muet. L'éviction du dernier pair ne peut être déclenchée que par une preuve positive de comportement malveillant (challenge échoué, signature invalide), non par un score passant sous un seuil.
### 3.7 Vérification Multi-Canal
@@ -155,20 +139,44 @@ La vérification de l'identité et de la qualité d'un pair par un unique canal
La vérification simultanément cohérente sur ces trois canaux orthogonaux requiert un niveau de sophistication adversariale croissant de manière exponentielle avec le nombre de canaux vérifiés, rendant la tromperie coordonnée prohibitivement coûteuse.
### 3.8 Gossip Sub pour la Propagation d'Événements
### 3.8 SWIM, Membership Épidémique avec Réfutation
Les événements d'appartenance (arrivée, départ, mise à jour de score significative) sont propagés par un mécanisme de gossip sub — diffusion épidémique structurée de type infection-style [Das et al., 2002]. Ce mécanisme garantit une convergence en O(log n) étapes avec haute probabilité, sans coordination centrale. La propagation épidémique est robuste au churn et tolère l'absence temporaire de nœuds.
Les événements d'appartenance (arrivée, départ, changement d'état) sont propagés par le protocole SWIM [9] (Scalable Weakly-consistent Infection-style process group Membership). Chaque événement est typé alive / suspect / dead et porte un numéro d'incarnation : un pair peut réfuter une suspicion en incrémentant son incarnation, ce qui neutralise les faux signaux de mort propagés à son encontre. La propagation est bornée par un compteur de sauts (HopsLeft décrémenté à chaque retransmission) qui empêche une campagne de désinformation de se propager au-delà d'un voisinage local.
Pour les environnements hostiles, le gossip peut être limité aux paires de pairs avec une clé de chiffrement commune (intra-consortium), empêchant la fuite d'informations topologiques vers des observateurs extérieurs.
Ces événements sont piggybacked sur les heartbeats existants, aucun canal dédié, aucun message supplémentaire. La déduplication repose sur la paire (PeerID, incarnation) : une incarnation plus haute ou un état de priorité supérieure (dead > suspect > alive) gagne. Ce mécanisme garantit une convergence en O(log n) étapes avec haute probabilité, sans coordination centrale, tout en résistant aux faux positifs de détection de panne inhérents aux contextes asynchrones (résultat FLP).
### 3.9 Adaptation DTN/Spatial
Pour les environnements hostiles, la diffusion des événements peut être restreinte aux paires de pairs partageant une clé de consortium, empêchant la fuite d'informations topologiques vers des observateurs extérieurs.
Les adaptations suivantes sont indispensables pour le contexte DTN :
### 3.9 Cache DTN, Livraison Garantie en Connectivité Intermittente
- **Stockage-et-retransmission** : les messages de découverte non livrables (pair inaccessible) sont stockés localement et retransmis lors des prochaines fenêtres de contact, selon le modèle de la RFC 4838 [Cerf et al., 2007].
- **TTL adaptatifs** : le TTL des enregistrements DHT est paramétré en fonction du délai de propagation prévisible dans le réseau. Pour un satellite LEO avec une fenêtre de contact de 15 minutes toutes les 90 minutes, les TTL doivent être d'au moins 90 minutes pour survivre à un cycle orbital complet.
- **Heartbeats asynchrones** : en l'absence de connectivité continue, les heartbeats sont accumulés localement et émis en batch lors des fenêtres de contact, avec des timestamps signés permettant la reconstitution de l'historique d'uptime.
- **State snapshots** : l'état complet du réseau de voisinage est sérialisé périodiquement sur le stockage local, permettant une reprise sans perte après une déconnexion prolongée.
L'adaptation DTN de la couche de données repose sur un cache de messages outbound à deux niveaux selon la criticité de la mutation.
**Niveau critique** couvre les mutations de ressources (CREATE / UPDATE / DELETE) : le message est retranté indéfiniment jusqu'à livraison confirmée. La persistance est chiffrée sur disque (AES-256-GCM, clé dérivée de façon déterministe de l'identité Ed25519 du nœud via HKDF) pour survivre aux redémarrages. La déduplication opère sur la clé `(peer_id, resource_id)` avec des règles de cycle de vie : DELETE est terminal (tout nouveau CREATE ou UPDATE pour le même couple est ignoré), UPDATE ne peut pas être suivi d'un CREATE (la ressource existe déjà côté pair). Ces règles garantissent que l'état final livré est cohérent quelle que soit la durée de l'interruption.
**Niveau modéré** couvre les confirmations, planners, et configurations : budget de trois essais puis abandon. Ces messages ne sont pas persistés sur disque, leur budget de retry est trop court pour qu'une restauration après redémarrage soit pertinente.
Lorsque la destination est un nœud Nano, tous les protocoles passent en niveau critique indépendamment de leur classification par défaut, un satellite peut être absent longtemps et aucune mutation ne doit être perdue.
**Mécanisme de réveil (PendingContact)** : plutôt qu'une boucle de retry aveugle, chaque nœud inclut dans son heartbeat la liste des peer IDs pour lesquels il a des entrées critiques en attente (`PendingContact`). Les indexeurs maintiennent un index inversé `peerID → [pairs qui l'attendent]`. Quand un pair reconnecte, il interroge cet index (`PendingCallers`) et initie le contact vers chaque pair en attente, déclenchant un flush immédiat du cache. Le signal s'éteint naturellement à la livraison, aucun timer additionnel, aucun protocole de callback dédié, redondance gratuite via les multiples indexeurs.
### 3.10 Hiérarchie Nano/Maître
Les nœuds à disponibilité très intermittente, typiquement des satellites ou des capteurs embarqués avec de courtes fenêtres de contact, peuvent être associés à un nœud maître présumé plus stable (station sol, concentrateur). Cette relation est un primitif de gouvernance et de délégation formellement encodé dans le peer record de chaque pair.
**Invariants fondamentaux :**
- Un nano n'est jamais un partenaire direct : toute relation de partenariat passe par son maître. Un tiers ne négocie pas avec le nano, il négocie avec son maître.
- Le maître est l'autorité du catalogue de ses nanos : il tient l'état à jour et propage les mutations dans les deux sens. Toute mutation (CREATE/UPDATE/DELETE) émise vers un nano par un émetteur qui n'est pas son maître enregistré est rejetée.
- Un maître envoie à un nano uniquement les ressources dont ce nano est propriétaire, pas l'intégralité du catalogue.
**Gestion des réservations en mode dégradé :**
*Cas nominal* : nano et maître joignables. La réservation est prise directement sur le nano, le maître est notifié ensuite (pas de DTN critique, le nano a déjà confirmé).
*Nano hors-ligne, maître joignable* : le maître prend la réservation en mode proxy avec `DestPeerID = nano.peer_id`, et la transmet au nano via le cache DTN critique à sa reconnexion.
*Split brain* : nano et maître déconnectés au moment où chacun prend une décision. À la reconnexion, **le maître a raison**, ses bookings priment sur ceux pris directement sur le nano pendant la déconnexion. Tout conflit (même resource_id, créneaux qui se chevauchent) est résolu en faveur du maître; le booking nano-only est annulé et le demandeur est notifié.
Cette règle de réconciliation déterministe est la seule qui garantisse la cohérence sans requérir de consensus distribué entre nano et maître au moment de la prise de décision, un consensus impossible précisément parce qu'ils sont déconnectés.
---
@@ -182,7 +190,7 @@ Pour le contexte DTN, les TTL sont adaptés au profil de connectivité prévisib
### 4.2 Tombstones Signés pour la Révocation Propre
La suppression explicite d'un enregistrement avant son expiration naturelle passe par un tombstone signé un enregistrement spécial portant la clé de l'enregistrement révoqué, le timestamp de révocation, et la signature du créateur. Les tombstones sont propagés par gossip et stockés temporairement dans la DHT pour prévenir la réapparition de l'enregistrement révoqué (replay attack).
La suppression explicite d'un enregistrement avant son expiration naturelle passe par un tombstone signé, un enregistrement spécial portant la clé de l'enregistrement révoqué, le timestamp de révocation, et la signature du créateur. Les tombstones sont propagés par gossip et stockés temporairement dans la DHT pour prévenir la réapparition de l'enregistrement révoqué (replay attack).
La durée de vie d'un tombstone doit être supérieure à la durée de vie maximale de l'enregistrement qu'il révoque, pour garantir que les nœuds qui n'ont pas encore vu la révocation ne réacceptent pas un replay de l'enregistrement original.
@@ -198,7 +206,7 @@ Ce principe garantit que même un adversaire contrôlant une région de la DHT n
### 4.5 Attestation de Consommation par Zero-Knowledge Proofs
Le problème de l'oracle (comment prouver qu'une ressource a été réellement consommée sans révéler ni le contenu ni l'identité de l'initiateur) est adressé par les preuves à divulgation nulle de connaissance (ZK-proofs). Goldwasser, Micali et Rackoff [Goldwasser et al., 1989] ont formalisé ce paradigme ; les constructions modernes basées sur des arguments non-interactifs à divulgation nulle (zk-SNARKs [Groth, 2016]) permettent de prouver la bonne exécution d'un calcul en O(1) de vérification, quelle que soit la complexité du calcul.
Le problème de l'oracle (comment prouver qu'une ressource a été réellement consommée sans révéler ni le contenu ni l'identité de l'initiateur) est adressé par les preuves à divulgation nulle de connaissance (ZK-proofs). Goldwasser, Micali et Rackoff [14] ont formalisé ce paradigme; les constructions modernes basées sur des arguments non-interactifs à divulgation nulle (zk-SNARKs) [15] permettent de prouver la bonne exécution d'un calcul en O(1) de vérification, quelle que soit la complexité du calcul.
Pour un marché de ressources, une attestation ZK permet à un consommateur de prouver à un smart contract qu'il a reçu et vérifié un résultat de calcul conforme à sa spécification, sans révéler ni le résultat lui-même ni les paramètres d'entrée.
@@ -214,7 +222,7 @@ Les événements applicatifs (disponibilité d'une ressource, completion d'un wo
La blockchain n'est pas la couche de découverte, ni la couche de données. Elle intervient exclusivement pour le règlement monétaire des transactions de ressources, après que ces ressources ont été consommées et attestées. Ce positionnement est fondamental : confondre la blockchain avec l'infrastructure de découverte ou de données créerait des couplages qui dégradent à la fois les performances (latence blockchain incompatible avec la découverte en temps réel) et la confidentialité (toute donnée sur la blockchain est potentiellement publique).
La blockchain règle les transactions APRÈS leur exécution, sur la base d'attestations cryptographiques de consommation. Elle n't pas besoin de connaître le contenu des ressources échangées, ni les identités des parties au-delà de leurs adresses blockchain (qui peuvent être pseudonymes ou chiffrées selon la solution choisie).
La blockchain règle les transactions APRÈS leur exécution, sur la base d'attestations cryptographiques de consommation. Elle n'a pas besoin de connaître le contenu des ressources échangées, ni les identités des parties au-delà de leurs adresses blockchain (qui peuvent être pseudonymes ou chiffrées selon la solution choisie).
### 5.2 Exigences Non-Négociables pour la Blockchain Éligible
@@ -225,7 +233,7 @@ Les exigences suivantes sont dérivées des contraintes du contexte cible et con
| Confidentialité des transactions (montants et parties) | Tout observateur externe ne doit pouvoir inférer ni le volume des échanges, ni les partenariats entre acteurs |
| Souveraineté (pas de fuite vers observateur externe) | Même les métadonnées de la blockchain ne doivent pas révéler d'informations stratégiques |
| Finalité rapide (< 30s idéalement, < 5 min acceptable) | Compatibilité avec les fenêtres de contact DTN limitées |
| Smart contracts pour automatisation du règlement | Automatisation du paiement conditionnel à l'attestation de consommation [Szabo, 1997 ; Wood, 2014] |
| Smart contracts pour automatisation du règlement | Automatisation du paiement conditionnel à l'attestation de consommation |
| Résistance à la censure | Un validateur adversarial ne doit pas pouvoir bloquer unilatéralement une transaction |
| Gouvernabilité de consortium | Admission, révocation, rotation des validateurs sans redémarrage du réseau |
| Faible empreinte énergétique | Contrainte stricte pour les nœuds embarqués (Proof of Work exclu) |
@@ -245,26 +253,29 @@ Les exigences suivantes sont dérivées des contraintes du contexte cible et con
| Hyperledger Fabric | ✓✓ (canaux privés) | ✓✓ (déterministe, Raft/PBFT) | ✓✓ (chaincode mature) | ✓✓ (MSP, canaux) | ✓✓ | ✓✓ | Idéal consortium fermé |
| Cosmos SDK + IBC | △ (dépend de la zone) | ✓✓ (Tendermint ~6s) | ✓ (CosmWasm) | ✓✓ (zones souveraines) | ✓✓ | ✓✓ | Excellente base multi-consortium |
| Polkadot / Substrate | △ | ✓ (GRANDPA ~12s) | ✓ (ink!, EVM via frontier) | ✓✓ (parachains) | ✓✓ | ✓ | Adapté multi-consortium, complexe |
| Penumbra | ✓✓ (ZK-SNARKs, pool aveugle) | ✓ (Tendermint ~6s) | △ (actions natives, pas CosmWasm) | ✓ (Cosmos zones) | ✓✓ | △ (testnet actif, mainnet récent) | Très prometteur ZK pur, contrats limités |
**Analyse détaillée des blockchains les plus pertinentes** :
**Hyperledger Fabric** [Androulaki et al., 2018] est une blockchain permissionnée conçue pour les consortiums d'entreprises. Son architecture modulaire (orderers, peers, MSP) permet une gouvernance fine des membres du consortium. Les canaux privés permettent à un sous-ensemble de membres d'effectuer des transactions invisibles aux autres membres. La finalité est déterministe (pas de forks possibles avec Raft ou PBFT), propriété critique pour le contexte DTN où la réconciliation de forks est difficile. Son principal défaut est l'absence de résistance trustless : la confiance dans les MSP (Membership Service Providers) est requise, ce qui convient aux consortiums fermés mais rend la solution inadaptée aux échanges inter-consortium entre adversaires potentiels.
**Hyperledger Fabric** [1] est une blockchain permissionnée conçue pour les consortiums d'entreprises. Son architecture modulaire (orderers, peers, MSP) permet une gouvernance fine des membres du consortium. Les canaux privés permettent à un sous-ensemble de membres d'effectuer des transactions invisibles aux autres membres. La finalité est déterministe (pas de forks possibles avec Raft ou PBFT), propriété critique pour le contexte DTN où la réconciliation de forks est difficile. Son principal défaut est l'absence de résistance trustless : la confiance dans les MSP (Membership Service Providers) est requise, ce qui convient aux consortiums fermés mais rend la solution inadaptée aux échanges inter-consortium entre adversaires potentiels.
**Cosmos SDK + IBC** [Kwon & Buchman, 2016] offre une architecture de zones souveraines interconnectées via le protocole IBC (Inter-Blockchain Communication). Chaque zone peut être configurée indépendamment (algorithme de consensus, gouvernance, smart contracts), permettant des niveaux de sécurité différenciés selon le contexte. Le consensus Tendermint BFT [Buchman, 2016] offre une finalité déterministe en environ 6 secondes compatible avec les contraintes DTN raisonnables. L'absence de confidentialité native est le principal défaut : les transactions IBC sont visibles dans les logs des deux zones impliquées.
**Cosmos SDK + IBC** [17] offre une architecture de zones souveraines interconnectées via le protocole IBC (Inter-Blockchain Communication). Chaque zone peut être configurée indépendamment (algorithme de consensus, gouvernance, smart contracts), permettant des niveaux de sécurité différenciés selon le contexte. Le consensus Tendermint BFT offre une finalité déterministe en environ 6 secondes, compatible avec les contraintes DTN raisonnables. L'absence de confidentialité native est le principal défaut : les transactions IBC sont visibles dans les logs des deux zones impliquées.
**Secret Network** utilise des enclaves TEE (Trusted Execution Environment) Intel SGX pour exécuter les smart contracts dans un environnement chiffré. Les entrées, les sorties, et l'état des smart contracts sont chiffrés pour les validateurs eux-mêmes seul le code est public. Cette propriété est exceptionnelle pour un contexte hostile. La principale limitation est la dépendance à Intel SGX, une technologie matérielle présentant des vulnérabilités de canal latéral documentées [Costan & Devadas, 2016]. La compatibilité Cosmos offre une interopérabilité avec un écosystème large.
**Secret Network** utilise des enclaves TEE (Trusted Execution Environment) Intel SGX [7] pour exécuter les smart contracts dans un environnement chiffré. Les entrées, les sorties, et l'état des smart contracts sont chiffrés pour les validateurs eux-mêmes, seul le code est public. Cette propriété est exceptionnelle pour un contexte hostile. La principale limitation est la dépendance à Intel SGX, une technologie matérielle présentant des vulnérabilités de canal latéral documentées. La compatibilité Cosmos offre une interopérabilité avec un écosystème large.
**Zcash** [Ben-Sasson et al., 2014 ; Hopwood et al., 2016] utilise les zk-SNARKs pour permettre des transactions shielded dont les montants et les adresses sont cryptographiquement cachés. C'est la solution la plus mature pour les paiements confidentiels purs, sans dépendance matérielle (contrairement aux TEE). Sa limitation principale est l'absence de smart contracts expressifs : le langage Script de Zcash ne permet pas d'automatiser le règlement conditionnel requis pour un marché de ressources complexe.
**Zcash** [16] utilise les zk-SNARKs pour permettre des transactions shielded dont les montants et les adresses sont cryptographiquement cachés. C'est la solution la plus mature pour les paiements confidentiels purs, sans dépendance matérielle (contrairement aux TEE). Sa limitation principale est l'absence de smart contracts expressifs : le langage Script de Zcash ne permet pas d'automatiser le règlement conditionnel requis pour un marché de ressources complexe.
**Oasis Network** [Oasis Labs, 2020] combine TEE et blockchain pour offrir des "ParaThreads" confidentiels : des environnements d'exécution chiffrés où les calculs se déroulent à l'abri des validateurs. L'EVM confidentiel (Sapphire ParaTime) permet d'exécuter des smart contracts Solidity avec confidentialité des états internes. La compatibilité avec l'écosystème Cosmos et l'EVM en fait un candidat particulièrement polyvalent.
**Oasis Network** [21] combine TEE et blockchain pour offrir des "ParaThreads" confidentiels : des environnements d'exécution chiffrés où les calculs se déroulent à l'abri des validateurs. L'EVM confidentiel (Sapphire ParaTime) permet d'exécuter des smart contracts Solidity avec confidentialité des états internes. La compatibilité avec l'écosystème Cosmos et l'EVM en fait un candidat particulièrement polyvalent.
**Penumbra** est une zone Cosmos dont la confidentialité repose exclusivement sur des zk-SNARKs — aucune dépendance matérielle, contrairement aux solutions TEE. Son architecture centrale est un pool aveugle (shielded pool) : les actifs y sont déposés, les transactions s'y effectuent, et les retraits se font via des preuves cryptographiques qui ne révèlent ni les montants ni les participants. Le DEX intégré (batch swap) traite les échanges par lot à un prix uniforme sur chaque bloc, éliminant structurellement le MEV par front-running — propriété particulièrement pertinente pour un marché de ressources où les validateurs ne doivent pas pouvoir manipuler l'ordre des transactions. La connexion IBC est supportée et les transferts cross-chain transitent par des chemins chiffrés, préservant la confidentialité au-delà des frontières de la zone. La principale limitation de Penumbra est l'expressivité contractuelle : les "actions" natives (swap, delegation, vote) couvrent les cas usuels mais ne disposent pas d'un moteur de smart contracts générique comparable à CosmWasm. Pour des règlements de ressources avec logique conditionnelle complexe, cette limite est contraignante. Penumbra constitue la cible de migration naturelle depuis Secret Network dès que la maturité de son écosystème le permettra : même famille Cosmos, même interopérabilité IBC, confidentialité sans dépendance SGX.
### 5.4 Recommandation Architecturale
La proposition retient une architecture hybride à deux niveaux :
**Niveau 1 Intra-consortium** : Hyperledger Fabric ou une zone Cosmos permissionnée. La gouvernance est assurée par le consortium via les MSP (Fabric) ou la gouvernance on-chain (Cosmos). Les transactions intra-consortium bénéficient de canaux privés (Fabric) ou d'une confidentialité applicative. La finalité déterministe garantit l'absence de forks. Ce niveau traite 95%+ des transactions dans un déploiement opérationnel normal.
**Niveau 1, Intra-consortium** : Hyperledger Fabric ou une zone Cosmos permissionnée. La gouvernance est assurée par le consortium via les MSP (Fabric) ou la gouvernance on-chain (Cosmos). Les transactions intra-consortium bénéficient de canaux privés (Fabric) ou d'une confidentialité applicative. La finalité déterministe garantit l'absence de forks. Ce niveau traite 95%+ des transactions dans un déploiement opérationnel normal.
**Niveau 2 Inter-consortium et règlement public** : Secret Network ou Oasis Network pour les transactions entre acteurs de consortiums distincts, bénéficiant de smart contracts confidentiels. Les attestations de consommation de ressources sont soumises on-chain comme ZK-proofs hors-chaîne, permettant de prouver la bonne exécution sans révéler le contenu des calculs [Groth, 2016].
**Niveau 2, Inter-consortium et règlement confidentiel** : Secret Network pour les transactions entre acteurs de consortiums distincts, via des smart contracts CosmWasm confidentiels exécutés dans des enclaves TEE. Les attestations de consommation de ressources sont soumises on-chain, permettant de prouver la bonne exécution sans révéler le contenu des calculs. La dépendance SGX est assumée comme compromis pragmatique à court terme; Penumbra constitue la migration naturelle à moyen terme, apportant la même confidentialité sans dépendance matérielle via zk-SNARKs, dans le même écosystème Cosmos et avec la même interopérabilité IBC. Les contrats de règlement doivent être conçus comme une implémentation interchangeable d'une interface pour faciliter cette migration.
**Gouvernance** : chaque consortium maintient une structure de gouvernance multi-sig avec seuil de quorum configurable. Les décisions d'admission et d'exclusion de membres requièrent un quorum configurable (typiquement 2/3) pour résister aux attaques de corruption minoritaire.
@@ -272,75 +283,55 @@ La proposition retient une architecture hybride à deux niveaux :
## 6. Verrous Conceptuels et Technologiques
### Verrou 1 Identité sans Autorité Centrale (TOFU)
### Verrou 1, Identité sans Autorité Centrale (TOFU)
**Problème** : Comment établir qu'une clé publique appartient bien à l'acteur qu'elle prétend représenter, sans autorité de certification centrale ? Le paradigme TOFU (Trust On First Use) accepte la clé lors du premier contact et avertit en cas de changement — solution pragmatique mais vulnérable à l'interception du premier contact.
Comment établir qu'une clé publique appartient bien à l'acteur qu'elle prétend représenter, sans autorité de certification centrale ? Le paradigme TOFU (Trust On First Use) est la réponse la plus simple : accepter la clé lors du premier contact, avertir en cas de changement ultérieur. C'est pragmatique, mais la vulnérabilité à l'interception de ce premier échange est réelle. Les identifiants décentralisés (DID, spécification W3C [26]) offrent une alternative plus robuste : des identités auto-certifiées ancrées dans une blockchain ou un réseau de confiance distribué, sans dépendance à une autorité centrale. Les PeerID libp2p (dérivés directement de la clé publique) constituent la forme la plus primitive de cette auto-certification.
**Solutions** : Les identifiants décentralisés (DID) définis par la spécification W3C [W3C, 2022] permettent à des acteurs de créer des identités auto-certifiées ancrées dans une blockchain ou un réseau de confiance distribué, sans dépendance à une autorité centrale. Les identifiants libp2p (PeerID dérivé de la clé publique) offrent une auto-certification primitive.
Le risque résiduel est propre au contexte hostile : ancrer une identité DID dans une blockchain publique révèle son existence à tout observateur. Pour les environnements qui l'exigent, des identités éphémères rotatoires avec mécanismes de reconnaissance hors-bande constituent une alternative, au prix d'une complexité opérationnelle significativement plus élevée.
**Challenge résiduel** : L'ancrage d'une identité DID dans une blockchain publique révèle l'existence de l'identité à tout observateur. Pour un contexte hostile, des identités éphémères rotatoires avec des mécanismes de reconnaissance hors-bande constituent une alternative, au prix d'une complexité opérationnelle plus élevée.
### Verrou 2, Bootstrap Trustless
### Verrou 2 — Bootstrap Trustless
Le premier contact avec le réseau suppose la connaissance d'au moins un pair de confiance. Ces seeds constituent une ancre de confiance qui ne peut être supprimée, seulement diversifiée et distribuée pour réduire le risque de compromission partielle. La proposition retient trois niveaux : seeds codés en dur géographiquement et organisationnellement diversifiés (analogie directe avec les directory authorities de Tor), DHT locale persistante pour les reconnexions ultérieures, et canal hors-bande sécurisé pour les déploiements à haute sécurité.
**Problème** : Le premier contact avec le réseau requiert de connaître au moins un pair de confiance. Ces seeds constituent un ancre de confiance qui ne peut être supprimée — elle peut seulement être diversifiée et distribuée pour réduire le risque de compromission partielle.
La limite est structurelle : aucun système sans seeds hardcodés ou sans canal hors-bande de confiance ne peut bootstrapper de manière véritablement trustless. L'ancre de confiance minimale est irréductible, ce qu'on peut faire est la rendre aussi résistante que possible à une compromission partielle.
**Solutions** : Diversification des seeds (géographique, organisationnelle, technologique). Distribution des seeds par canal hors-bande pour les environnements à haute sécurité. DHT locale persistante pour les reconnexions.
### Verrou 3, Résistance Sybil sans Coût Cryptoéconomique
**Challenge résiduel** : Aucun système sans seed codés en dur ou sans canal hors-bande de confiance ne peut bootstrapper de manière véritablement trustless. Les seeds constituent nécessairement une ancre de confiance minimale.
Douceur [10] a démontré que la résistance Sybil est impossible sans coût d'entrée ou autorité centrale. Pour les réseaux ouverts en environnement hostile, aucune solution unique n'est complète. La clé pré-partagée (PSK) organisationnelle est efficace dans les réseaux fermés mais requiert une coordination hors-bande pour chaque nouvel entrant. Le scoring comportemental multidimensionnel constitue une défense secondaire solide mais peut être contourné par un adversaire patient qui simule durablement un comportement exemplaire. Pour les réseaux ouverts, un dépôt cryptoéconomique (stake on-chain) est la seule barrière structurellement robuste, elle rend prohibitivement coûteuse la multiplication d'identités.
### Verrou 3 — Résistance Sybil sans Coût Cryptoéconomique
En pratique, la combinaison PSK + scoring suffit pour les réseaux de consortium. La barrière cryptoéconomique est réservée aux configurations ouvertes où des adversaires bien financés disposent du temps nécessaire pour bâtir une réputation factice.
**Problème** : Douceur [Douceur, 2002] a démontré que la résistance Sybil est impossible sans coût d'entrée ou autorité centrale. Pour les réseaux ouverts en environnement hostile, ni la PSK organisationnelle ni le scoring comportemental ne constituent des solutions complètes : la PSK est efficace mais requiert une coordination hors-bande pour chaque nouvel entrant ; le scoring peut être manipulé sur le long terme par un adversaire patient.
### Verrou 4, Cohérence sans Consensus Fort (CAP)
**Solutions** : PSK organisationnelle pour les réseaux fermés. Scoring comportemental multidimensionnel comme couche de défense secondaire. Pour les réseaux ouverts, un dépôt cryptoéconomique (stake on-chain) comme coût d'entrée minimum.
Le théorème CAP [4][13] impose un choix entre cohérence et disponibilité lors d'un partitionnement. Choisir le profil CP pour la couche de découverte la rendrait indisponible lors des partitions DTN fréquentes, inacceptable opérationnellement. La proposition assume ce choix explicitement : profil AP pour la découverte (cohérence éventuelle, disponibilité prioritaire), profil CP pour le règlement blockchain (cohérence forte, disponibilité conditionnelle au quorum). Les conflits d'état lors de la réunification sont résolus par Last-Write-Wins ou vecteurs d'horloge selon la criticité des enregistrements.
**Challenge résiduel** : Les réseaux entièrement ouverts et hostiles sans coût d'entrée cryptoéconomique restent vulnérables à des attaques Sybil patient et bien financées.
Ce qui ne disparaît pas pour autant : la cohérence éventuelle autorise des fenêtres temporaires d'état incohérent qui peuvent être exploitées par un adversaire contrôlant l'instant de la réunification. C'est un risque connu et accepté, atténué par la durée typiquement courte de ces fenêtres dans les scénarios orbitaux prévisibles.
### Verrou 4 — Cohérence sans Consensus Fort (CAP)
### Verrou 5, Détection de Panne sans Oracle (FLP)
**Problème** : Le théorème CAP [Brewer, 2000 ; Gilbert & Lynch, 2002] impose un choix entre cohérence et disponibilité lors d'un partitionnement. Pour la couche de découverte, choisir CP rendrait le système indisponible lors des partitions DTN fréquentes.
Fischer, Lynch et Paterson [12] ont démontré qu'en présence d'asynchronisme, aucun algorithme déterministe ne peut distinguer un pair défaillant d'un pair simplement lent. Toute détection de panne est donc probabiliste par nature. Le protocole SWIM adresse ce problème de manière adaptée aux réseaux DTN : plutôt qu'un timeout binaire, il introduit une période de suspicion pendant laquelle un pair suspecté n'est pas immédiatement exclu mais marqué comme tel, la confirmation de la panne requérant la convergence de plusieurs observations indépendantes. Cette approche réduit significativement les faux positifs, particulièrement fréquents dans les environnements à haute latence.
**Solution** : Choix délibéré du profil AP pour la découverte (cohérence éventuelle, disponibilité prioritaire), CP pour le règlement blockchain (cohérence forte, disponibilité conditionnelle au quorum). Les conflits d'état lors de la réunification sont résolus par Last-Write-Wins ou par vecteurs d'horloge selon la criticité des enregistrements.
Dans les réseaux DTN à très haute latence, les délais de confirmation peuvent atteindre plusieurs cycles orbitaux, pendant lesquels un pair défaillant ou malveillant reste présent dans les tables de voisinage. C'est la contrepartie inévitable du choix AP : une table avec quelques entrées stale est préférable à l'absence de table.
**Challenge résiduel** : La cohérence éventuelle autorise des fenêtres temporaires d'état incohérent qui peuvent être exploitées par un adversaire contrôlant l'instant de la réunification.
### Verrou 6, Confidentialité des Transactions sur Chaîne Publique
### Verrou 5 — Détection de Panne sans Oracle (FLP)
La transparence des blockchains publiques est structurellement antagoniste à la confidentialité opérationnelle. Même les blockchains pseudonymes permettent la reconstruction partielle des graphes de transactions par analyse de clustering. Trois approches couvrent ce problème, chacune avec un périmètre différent.
**Problème** : Fischer, Lynch et Paterson [Fischer, Lynch & Paterson, 1985] ont démontré qu'en présence d'asynchronisme, aucun algorithme déterministe ne peut distinguer un pair défaillant d'un pair lent. Toute détection de panne est donc probabiliste et sujette à des faux positifs.
Les ZK-SNARKs masquent cryptographiquement montants et adresses sans dépendance matérielle, la solution la plus pure, mais les constructions pour smart contracts complexes restent en cours de maturation. Les TEE (Intel SGX, ARM TrustZone) permettent une exécution confidentielle des smart contracts là où même les validateurs ne voient pas les données, mature dans l'écosystème Cosmos via Secret Network, mais soumis à des vulnérabilités de canal latéral documentées. Les blockchains permissionnées avec canaux privés offrent une confidentialité intra-consortium robuste, au prix d'une confiance requise dans les opérateurs du réseau. Ces trois approches ne sont pas exclusives et peuvent couvrir des périmètres complémentaires.
**Solution** : Le protocole SWIM [Das et al., 2002] offre une approche infection-style avec gestion des suspicions (un pair suspecté d'être défaillant n'est pas immédiatement exclu mais marqué comme suspect, et la confirmation de sa panne requiert la convergence de plusieurs observations indépendantes). Cette approche est adaptée aux réseaux DTN où les faux positifs de détection de panne sont fréquents.
### Verrou 7, DTN et Transactions Intermittentes
**Challenge résiduel** : Dans les réseaux DTN à très haute latence, les délais de confirmation de panne peuvent atteindre plusieurs cycles orbitaux, pendant lesquels un pair défaillant (ou malveillant) reste actif dans les tables de voisinage.
Les blockchains classiques supposent une connectivité continue entre validateurs. Dans un réseau DTN, un validateur peut être absent plusieurs heures sans être défaillant, bloquant le quorum et donc le traitement des transactions pendant toute la durée de son absence. Les state channels offrent une réponse élégante : deux parties pré-engagent des fonds dans un canal off-chain et échangent des signatures hors-chaîne pendant une période prolongée, ne soumettant le résultat final on-chain qu'à la clôture. Cette approche tolère des périodes de déconnexion arbitrairement longues mais requiert une connexion initiale pour l'engagement. La signature différée est une alternative plus simple : les transactions sont signées localement avec un timestamp, accumulées pendant la période hors-ligne, soumises en batch à la prochaine fenêtre de connexion, le smart contract vérifiant la validité temporelle et l'unicité des nonces.
### Verrou 6 — Confidentialité des Transactions sur Chaîne Publique
Les optimistic rollups introduisent une fenêtre de contestation de plusieurs heures, ce qui est compatible DTN pour la latence mais techniquement moins adapté aux partitions prolongées que les state channels. Les deux approches peuvent coexister selon la criticité de la transaction.
**Problème** : La transparence des blockchains publiques est structurellement antagoniste à la confidentialité opérationnelle. Même les blockchains pseudonymes permettent la reconstruction partielle des graphes de transactions [Meiklejohn et al., 2013].
### Verrou 8, Oracle et Preuve de Consommation Réelle
**Solutions** : ZK-SNARKs [Ben-Sasson et al., 2014] pour masquer cryptographiquement les montants et les adresses. TEE (Trusted Execution Environment) pour l'exécution confidentielle des smart contracts [Oasis Labs, 2020]. Blockchains permissionnées avec canaux privés [Androulaki et al., 2018].
Szabo [25] a posé le problème fondamental : un smart contract de règlement doit vérifier qu'un calcul s'est réellement exécuté, que des données ont réellement été livrées, mais il opère dans un environnement blockchain isolé du monde physique. Trois approches permettent d'y répondre.
**Challenge résiduel** : Les solutions ZK sont encore en cours de maturation pour les smart contracts complexes. Les solutions TEE présentent des dépendances matérielles avec des vulnérabilités de canal latéral documentées. Les blockchains permissionnées requièrent une confiance dans les opérateurs du réseau.
Les attestations TEE génèrent une preuve cryptographique signée par le microprocesseur lui-même, certifiant que le code spécifié s'est exécuté dans un environnement sécurisé (Intel SGX, ARM TrustZone). Les ZK-proofs d'exécution prouvent la bonne exécution d'un programme sur des entrées données sans révéler ni les entrées ni les sorties, des systèmes comme zkEVM et les ZKVM permettent cette approche pour des programmes arbitraires, au prix d'un coût de génération encore élevé pour les programmes complexes. Le challenge-response interactif repose sur un échantillonnage aléatoire de résultats vérifiables que le fournisseur ne peut produire qu'en ayant réellement exécuté le calcul.
### Verrou 7 — DTN et Transactions Intermittentes
**Problème** : Les blockchains classiques supposent une connectivité continue entre validateurs. Dans un réseau DTN, un validateur peut être absent pendant plusieurs heures, bloquant l'atteinte du quorum et donc le traitement des transactions.
**Solutions** :
- **State channels** : deux parties pré-engagent des fonds dans un canal off-chain et échangent des signatures hors-chaîne pendant une période prolongée, ne soumettant le résultat final on-chain qu'à la clôture du canal. Cette approche tolère des périodes de déconnexion arbitrairement longues.
- **Optimistic rollups** : les transactions sont soumises on-chain avec une fenêtre de contestation. En l'absence de contestation, la transaction est finalisée. Adapté aux environnements à faible fraude mais à connectivité intermittente.
- **Signature différée** : les transactions sont signées localement avec un timestamp, accumulées pendant la période hors-ligne, et soumises en batch lors de la prochaine fenêtre de connexion. Le smart contract vérifie la validité temporelle des signatures.
**Challenge résiduel** : Les state channels requièrent une connexion initiale pour l'engagement des fonds. Les optimistic rollups introduisent des fenêtres de contestation de plusieurs heures — compatibles DTN mais augmentant la latence de finalité effective.
### Verrou 8 — Oracle et Preuve de Consommation Réelle
**Problème** : Szabo [Szabo, 1997] a identifié la difficulté fondamentale d'ancrer des contrats sur des événements du monde réel. Un smart contract de règlement de ressources doit vérifier qu'un calcul s'est réellement exécuté, que des données ont été réellement livrées — mais un smart contract est exécuté dans un environnement blockchain isolé du monde extérieur.
**Solutions** :
- **TEE attestations** : un calcul exécuté dans une enclave Intel SGX ou ARM TrustZone génère une attestation cryptographique signée par le microprocesseur lui-même, prouvant que le code spécifié s'est exécuté dans un environnement sécurisé.
- **ZK-proof d'exécution** : un ZKP prouve la bonne exécution d'un programme sur des entrées données sans révéler ni les entrées ni les sorties. Des systèmes comme zkEVM et les ZKVM expérimentaux permettent cette approche pour des programmes arbitraires [Groth, 2016].
- **Challenge-response** : le consommateur soumet une preuve interactive (échantillonnage aléatoire de résultats vérifiables) que le fournisseur ne peut produire qu'en ayant réellement exécuté le calcul.
**Challenge résiduel** : Les TEE présentent des vulnérabilités de canal latéral [Costan & Devadas, 2016]. Les ZK-proofs d'exécution générique restent coûteux à générer pour des programmes complexes.
Dans la pratique, TEE et challenge-response sont les approches les plus immédiatement déployables. Les ZK-proofs d'exécution générique représentent la direction de long terme, leur coût de génération décroît à chaque génération de circuits.
---
@@ -356,21 +347,21 @@ Confiance(pair, t) = f(uptime_ratio(t), challenge_precision(t),
diversity_contribution(t))
```
Ce score est mis à jour à chaque interaction et décroît graduellement en l'absence d'observations récentes (décroissance exponentielle avec demi-vie paramétrable). Un pair absent depuis longtemps n'est pas nécessairement malveillant son score se dégrade pour refléter l'incertitude croissante sur son état.
Ce score est mis à jour à chaque interaction et décroît graduellement en l'absence d'observations récentes (décroissance exponentielle avec demi-vie paramétrable). Un pair absent depuis longtemps n'est pas nécessairement malveillant, son score se dégrade pour refléter l'incertitude croissante sur son état.
Un modèle binaire échoue parce qu'il ignore cette incertitude temporelle : un pair qui obtient le statut "de confiance" le conserve indéfiniment, même si son comportement récent est suspect. Le modèle continu à décroissance temporelle force une réévaluation permanente.
### 7.2 Architecture de Consortium à Trois Niveaux
**Niveau 1 Consortium PSK** : Pairs partageant une clé pré-partagée (Pre-Shared Key) distribuée par voie organisationnelle sécurisée. La PSK est incorporée dans le handshake Noise, garantissant que seuls les membres du consortium peuvent établir des connexions dans cet espace. La confiance a priori est élevée (score initial : 70/100). Ce niveau correspond aux pairs appartenant à la même organisation ou unité opérationnelle.
**Niveau 1, Consortium PSK** : Pairs partageant une clé pré-partagée (Pre-Shared Key) distribuée par voie organisationnelle sécurisée. La PSK est incorporée dans le handshake Noise, garantissant que seuls les membres du consortium peuvent établir des connexions dans cet espace. La confiance a priori est élevée (score initial : 70/100). Ce niveau correspond aux pairs appartenant à la même organisation ou unité opérationnelle.
**Niveau 2 Consortium à Attestation** : Pairs d'organisations alliées disposant d'une attestation signée par un membre de niveau 1. L'attestation contient la clé publique du pair, sa période de validité, et les ressources auxquelles il est autorisé à accéder. La confiance a priori est modérée (score initial : 40/100). Ce niveau correspond aux partenaires de coalition.
**Niveau 2, Consortium à Attestation** : Pairs d'organisations alliées disposant d'une attestation signée par un membre de niveau 1. L'attestation contient la clé publique du pair, sa période de validité, et les ressources auxquelles il est autorisé à accéder. La confiance a priori est modérée (score initial : 40/100). Ce niveau correspond aux partenaires de coalition.
**Niveau 3 Réseau Ouvert** : Pairs sans attestation ni PSK. La confiance initiale est nulle (score : 0/100) et ne peut augmenter que par accumulation d'observations comportementales positives sur une période prolongée. L'accès aux ressources critiques est restreint jusqu'à ce que le score dépasse un seuil configurable.
**Niveau 3, Réseau Ouvert** : Pairs sans attestation ni PSK. La confiance initiale est nulle (score : 0/100) et ne peut augmenter que par accumulation d'observations comportementales positives sur une période prolongée. L'accès aux ressources critiques est restreint jusqu'à ce que le score dépasse un seuil configurable.
### 7.3 Révocation et Propagation de Méfiance
La révocation d'un pair est propagée par un tombstone signé par un membre de niveau 1, diffusé par gossip épidémique [Das et al., 2002]. Tous les pairs recevant ce tombstone mettent immédiatement le score du pair révoqué à zéro et le placent sur une liste noire temporaire. La liste noire est elle-même signée et distribuée avec un TTL configurable, permettant une réhabilitation éventuelle après révocation temporaire.
La révocation d'un pair est propagée par un tombstone signé par un membre de niveau 1, diffusé par gossip épidémique. Tous les pairs recevant ce tombstone mettent immédiatement le score du pair révoqué à zéro et le placent sur une liste noire temporaire. La liste noire est elle-même signée et distribuée avec un TTL configurable, permettant une réhabilitation éventuelle après révocation temporaire.
Pour les situations de compromission active (clé privée extraite), le protocole de révocation d'urgence est initié simultanément par plusieurs membres de niveau 1 pour éviter qu'un adversaire contrôlant un unique membre puisse bloquer la révocation.
@@ -406,58 +397,58 @@ Chaque nœud doit être capable d'opérer en mode complètement autonome (zéro
## Références Bibliographiques
**[Androulaki et al., 2018]** Androulaki, E., Barger, A., Bortnikov, V., Cachin, C., Christidis, K., De Caro, A., Enyeart, D., Ferris, C., Laventman, G., Manevich, Y., Muralidharan, S., Murthy, C., Nguyen, B., Sethi, M., Singh, G., Smith, K., Sorniotti, A., Stathakopoulou, C., Vukolic, M., Cocco, S. W., & Yellick, J. (2018). Hyperledger Fabric: a distributed operating system for permissioned blockchains. In *Proceedings of the 13th EuroSys Conference*, article 30.
**[1] [Androulaki et al., 2018]** Androulaki, E., Barger, A., Bortnikov, V., Cachin, C., Christidis, K., De Caro, A., Enyeart, D., Ferris, C., Laventman, G., Manevich, Y., Muralidharan, S., Murthy, C., Nguyen, B., Sethi, M., Singh, G., Smith, K., Sorniotti, A., Stathakopoulou, C., Vukolic, M., Cocco, S. W., & Yellick, J. (2018). Hyperledger Fabric: a distributed operating system for permissioned blockchains. In *Proceedings of the 13th EuroSys Conference*, article 30.
**[Baumgart & Meinert, 2007]** Baumgart, I., & Meinert, S. (2007). S/Kademlia: A practicable approach towards secure key-based routing. In *Proceedings of the 2007 International Conference on Parallel and Distributed Systems (ICPADS)*, pp. 18.
**[2] [Baumgart & Meinert, 2007]** Baumgart, I., & Meinert, S. (2007). S/Kademlia: A practicable approach towards secure key-based routing. In *Proceedings of the 2007 International Conference on Parallel and Distributed Systems (ICPADS)*, pp. 18.
**[Ben-Sasson et al., 2014]** Ben-Sasson, E., Chiesa, A., Garman, C., Green, M., Miers, I., Tromer, E., & Virza, M. (2014). Zerocash: Decentralized Anonymous Payments from Bitcoin. In *Proceedings of the 2014 IEEE Symposium on Security and Privacy (S&P)*, pp. 459474.
**[3] [Ben-Sasson et al., 2014]** Ben-Sasson, E., Chiesa, A., Garman, C., Green, M., Miers, I., Tromer, E., & Virza, M. (2014). Zerocash: Decentralized Anonymous Payments from Bitcoin. In *Proceedings of the 2014 IEEE Symposium on Security and Privacy (S&P)*, pp. 459474.
**[Brewer, 2000]** Brewer, E. A. (2000). Towards robust distributed systems. In *Proceedings of the 19th Annual ACM Symposium on Principles of Distributed Computing (PODC)*, pp. 7.
**[4] [Brewer, 2000]** Brewer, E. A. (2000). Towards robust distributed systems. In *Proceedings of the 19th Annual ACM Symposium on Principles of Distributed Computing (PODC)*, pp. 7.
**[Buchman, 2016]** Buchman, E. (2016). *Tendermint: Byzantine Fault Tolerance in the Age of Blockchains*. M.Sc. Thesis, University of Guelph.
**[5] [Buchman, 2016]** Buchman, E. (2016). *Tendermint: Byzantine Fault Tolerance in the Age of Blockchains*. M.Sc. Thesis, University of Guelph.
**[Cerf et al., 2007]** Cerf, V., Burleigh, S., Hooke, A., Torgerson, L., Durst, R., Scott, K., Fall, K., & Weiss, H. (2007). Delay-Tolerant Networking Architecture. *RFC 4838*, IETF.
**[6] [Cerf et al., 2007]** Cerf, V., Burleigh, S., Hooke, A., Torgerson, L., Durst, R., Scott, K., Fall, K., & Weiss, H. (2007). Delay-Tolerant Networking Architecture. *RFC 4838*, IETF.
**[Costan & Devadas, 2016]** Costan, V., & Devadas, S. (2016). Intel SGX Explained. *IACR Cryptology ePrint Archive*, Report 2016/086.
**[7] [Costan & Devadas, 2016]** Costan, V., & Devadas, S. (2016). Intel SGX Explained. *IACR Cryptology ePrint Archive*, Report 2016/086.
**[Daian et al., 2020]** Daian, P., Goldfeder, S., Kell, T., Li, Y., Zhao, X., Bentov, I., Breidenbach, L., & Juels, A. (2020). Flash Boys 2.0: Frontrunning in Decentralized Exchanges, Miner Extractable Value, and Consensus Instability. In *Proceedings of the 2020 IEEE Symposium on Security and Privacy (S&P)*, pp. 910927.
**[8] [Daian et al., 2020]** Daian, P., Goldfeder, S., Kell, T., Li, Y., Zhao, X., Bentov, I., Breidenbach, L., & Juels, A. (2020). Flash Boys 2.0: Frontrunning in Decentralized Exchanges, Miner Extractable Value, and Consensus Instability. In *Proceedings of the 2020 IEEE Symposium on Security and Privacy (S&P)*, pp. 910927.
**[Das et al., 2002]** Das, A., Gupta, I., & Motivala, A. (2002). SWIM: Scalable Weakly-consistent Infection-style Process Group Membership Protocol. In *Proceedings of the 2002 International Conference on Dependable Systems and Networks (DSN)*, pp. 303312.
**[9] [Das et al., 2002]** Das, A., Gupta, I., & Motivala, A. (2002). SWIM: Scalable Weakly-consistent Infection-style Process Group Membership Protocol. In *Proceedings of the 2002 International Conference on Dependable Systems and Networks (DSN)*, pp. 303312.
**[Douceur, 2002]** Douceur, J. R. (2002). The Sybil Attack. In *Proceedings of the 1st International Workshop on Peer-to-Peer Systems (IPTPS)*, LNCS 2429, pp. 251260.
**[10] [Douceur, 2002]** Douceur, J. R. (2002). The Sybil Attack. In *Proceedings of the 1st International Workshop on Peer-to-Peer Systems (IPTPS)*, LNCS 2429, pp. 251260.
**[Fall, 2003]** Fall, K. (2003). A delay-tolerant network architecture for challenged internets. In *Proceedings of SIGCOMM 2003*, pp. 2734.
**[11] [Fall, 2003]** Fall, K. (2003). A delay-tolerant network architecture for challenged internets. In *Proceedings of SIGCOMM 2003*, pp. 2734.
**[Fischer, Lynch & Paterson, 1985]** Fischer, M. J., Lynch, N. A., & Paterson, M. S. (1985). Impossibility of distributed consensus with one faulty process. *Journal of the ACM (JACM)*, 32(2), 374382.
**[12] [Fischer, Lynch & Paterson, 1985]** Fischer, M. J., Lynch, N. A., & Paterson, M. S. (1985). Impossibility of distributed consensus with one faulty process. *Journal of the ACM (JACM)*, 32(2), 374382.
**[Gilbert & Lynch, 2002]** Gilbert, S., & Lynch, N. (2002). Brewer's conjecture and the feasibility of consistent, available, partition-tolerant web services. *ACM SIGACT News*, 33(2), 5159.
**[13] [Gilbert & Lynch, 2002]** Gilbert, S., & Lynch, N. (2002). Brewer's conjecture and the feasibility of consistent, available, partition-tolerant web services. *ACM SIGACT News*, 33(2), 5159.
**[Goldwasser, Micali & Rackoff, 1989]** Goldwasser, S., Micali, S., & Rackoff, C. (1989). The knowledge complexity of interactive proof systems. *SIAM Journal on Computing*, 18(1), 186208.
**[14] [Goldwasser, Micali & Rackoff, 1989]** Goldwasser, S., Micali, S., & Rackoff, C. (1989). The knowledge complexity of interactive proof systems. *SIAM Journal on Computing*, 18(1), 186208.
**[Groth, 2016]** Groth, J. (2016). On the size of pairing-based non-interactive arguments. In *Proceedings of the 35th Annual International Conference on the Theory and Applications of Cryptographic Techniques (EUROCRYPT 2016)*, LNCS 9666, pp. 305326.
**[15] [Groth, 2016]** Groth, J. (2016). On the size of pairing-based non-interactive arguments. In *Proceedings of the 35th Annual International Conference on the Theory and Applications of Cryptographic Techniques (EUROCRYPT 2016)*, LNCS 9666, pp. 305326.
**[Hopwood et al., 2016]** Hopwood, D., Bowe, S., Hornby, T., & Wilcox, N. (2016). *Zcash Protocol Specification*. Electric Coin Company. https://zips.z.cash/protocol/protocol.pdf
**[16] [Hopwood et al., 2016]** Hopwood, D., Bowe, S., Hornby, T., & Wilcox, N. (2016). *Zcash Protocol Specification*. Electric Coin Company. https://zips.z.cash/protocol/protocol.pdf
**[Kwon & Buchman, 2016]** Kwon, J., & Buchman, E. (2016). *Cosmos: A Network of Distributed Ledgers*. Whitepaper. https://v1.cosmos.network/resources/whitepaper
**[17] [Kwon & Buchman, 2016]** Kwon, J., & Buchman, E. (2016). *Cosmos: A Network of Distributed Ledgers*. Whitepaper. https://v1.cosmos.network/resources/whitepaper
**[Maymounkov & Mazières, 2002]** Maymounkov, P., & Mazières, D. (2002). Kademlia: A Peer-to-Peer Information System Based on the XOR Metric. In *Proceedings of IPTPS 2002*, LNCS 2429, pp. 5365.
**[18] [Maymounkov & Mazières, 2002]** Maymounkov, P., & Mazières, D. (2002). Kademlia: A Peer-to-Peer Information System Based on the XOR Metric. In *Proceedings of IPTPS 2002*, LNCS 2429, pp. 5365.
**[Meiklejohn et al., 2013]** Meiklejohn, S., Pomarole, M., Jordan, G., Levchenko, K., McCoy, D., Voelker, G. M., & Savage, S. (2013). A Fistful of Bitcoins: Characterizing Payments Among Men with No Names. In *Proceedings of IMC 2013*, pp. 127140.
**[19] [Meiklejohn et al., 2013]** Meiklejohn, S., Pomarole, M., Jordan, G., Levchenko, K., McCoy, D., Voelker, G. M., & Savage, S. (2013). A Fistful of Bitcoins: Characterizing Payments Among Men with No Names. In *Proceedings of IMC 2013*, pp. 127140.
**[Nakamoto, 2008]** Nakamoto, S. (2008). Bitcoin: A Peer-to-Peer Electronic Cash System. https://bitcoin.org/bitcoin.pdf
**[20] [Nakamoto, 2008]** Nakamoto, S. (2008). Bitcoin: A Peer-to-Peer Electronic Cash System. https://bitcoin.org/bitcoin.pdf
**[Oasis Labs, 2020]** Oasis Network (2020). *Oasis Network Primer*. Oasis Labs. https://oasisprotocol.org/primer
**[21] [Oasis Labs, 2020]** Oasis Network (2020). *Oasis Network Primer*. Oasis Labs. https://oasisprotocol.org/primer
**[Perrin, 2018]** Perrin, T. (2018). *The Noise Protocol Framework*. https://noiseprotocol.org/noise.pdf
**[22] [Perrin, 2018]** Perrin, T. (2018). *The Noise Protocol Framework*. https://noiseprotocol.org/noise.pdf
**[Stoica et al., 2003]** Stoica, I., Morris, R., Liben-Nowell, D., Karger, D. R., Kaashoek, M. F., Dabek, F., & Balakrishnan, H. (2003). Chord: A scalable peer-to-peer lookup protocol for internet applications. *IEEE/ACM Transactions on Networking*, 11(1), 1732.
**[23] [Stoica et al., 2003]** Stoica, I., Morris, R., Liben-Nowell, D., Karger, D. R., Kaashoek, M. F., Dabek, F., & Balakrishnan, H. (2003). Chord: A scalable peer-to-peer lookup protocol for internet applications. *IEEE/ACM Transactions on Networking*, 11(1), 1732.
**[Sun et al., 2017]** Sun, S.-F., Au, M. H., Liu, J. K., & Yuen, T. H. (2017). RingCT 2.0: A Compact Accumulator-Based (Linkable Ring Signature) Protocol for Blockchain Cryptocurrency Monero. In *Proceedings of ESORICS 2017*, LNCS 10493, pp. 456474.
**[24] [Sun et al., 2017]** Sun, S.-F., Au, M. H., Liu, J. K., & Yuen, T. H. (2017). RingCT 2.0: A Compact Accumulator-Based (Linkable Ring Signature) Protocol for Blockchain Cryptocurrency Monero. In *Proceedings of ESORICS 2017*, LNCS 10493, pp. 456474.
**[Szabo, 1997]** Szabo, N. (1997). Formalizing and securing relationships on public networks. *First Monday*, 2(9).
**[25] [Szabo, 1997]** Szabo, N. (1997). Formalizing and securing relationships on public networks. *First Monday*, 2(9).
**[W3C, 2022]** W3C (2022). *Decentralized Identifiers (DIDs) v1.0*. W3C Recommendation. https://www.w3.org/TR/did-core/
**[26] [W3C, 2022]** W3C (2022). *Decentralized Identifiers (DIDs) v1.0*. W3C Recommendation. https://www.w3.org/TR/did-core/
**[Wood, 2014]** Wood, G. (2014). *Ethereum: A Secure Decentralised Generalised Transaction Ledger*. Ethereum Yellow Paper. https://ethereum.github.io/yellowpaper/paper.pdf
**[27] [Wood, 2014]** Wood, G. (2014). *Ethereum: A Secure Decentralised Generalised Transaction Ledger*. Ethereum Yellow Paper. https://ethereum.github.io/yellowpaper/paper.pdf
**[Wood, 2016]** Wood, G. (2016). *Polkadot: Vision for a Heterogeneous Multi-Chain Framework*. Whitepaper. https://polkadot.network/PolkaDotPaper.pdf
**[28] [Wood, 2016]** Wood, G. (2016). *Polkadot: Vision for a Heterogeneous Multi-Chain Framework*. Whitepaper. https://polkadot.network/PolkaDotPaper.pdf
@@ -1,83 +1,67 @@
# Analyse des Risques d'une Découverte de Pair Sans Confiance et des Transactions de Données et Monétaires dans un Réseau Décentralisé
**Catégorie** : Sécurité des systèmes distribués Analyse de risques
**Catégorie** : Sécurité des systèmes distribués, Analyse de risques
**Domaine d'application** : Systèmes embarqués, contexte spatial, réseaux tolérants aux disruptions (DTN)
**Version** : 1.0 — Mars 2026
**Version** : 1.1, Mai 2026
---
## Résumé
Les réseaux pair-à-pair décentralisés opérant dans des environnements hostiles posent des défis de sécurité fondamentalement différents de ceux rencontrés dans les infrastructures classiques. Ce document analyse les risques inhérents à deux problématiques interdépendantes : d'une part, la découverte de pairs en l'absence d'autorité centrale de confiance, et d'autre part, la conduite de transactions portant sur des données et des actifs monétaires dans un réseau potentiellement infiltré, surveillé, ou partiellement contrôlé par des adversaires.
Les réseaux pair-à-pair décentralisés opérant dans des environnements hostiles posent des défis de sécurité fondamentalement différents de ceux rencontrés dans les infrastructures classiques. Ce document analyse les risques inhérents à deux problématiques interdépendantes : la découverte de pairs en l'absence d'autorité centrale de confiance, et la conduite de transactions portant sur des données et des actifs monétaires dans un réseau potentiellement infiltré, surveillé, ou partiellement contrôlé par des adversaires.
Le périmètre de cette analyse est délimité par le contexte des systèmes distribués embarqués et spatiaux opérant selon le paradigme DTN (Delay/Disruption Tolerant Networking), caractérisés par des latences élevées, une connectivité intermittente, et la coprésence d'acteurs aux niveaux de confiance hétérogènes.
Le périmètre est délimité par le contexte des systèmes distribués embarqués et spatiaux opérant selon le paradigme DTN (Delay/Disruption Tolerant Networking) : latences élevées, connectivité intermittente, coprésence d'acteurs aux niveaux de confiance hétérogènes.
Le modèle de menace retenu distingue deux classes d'adversaires : l'adversaire rationnel à ressources limitées, dont les actions sont guidées par le rapport coût/bénéfice, et l'adversaire disposant de ressources quasi-illimitées, capable de conduire des attaques passives prolongées (watchers) ou actives (injection, manipulation). Dans ce second cas, les garanties probabilistes offertes par les protocoles cryptographiques standards peuvent être insuffisantes sur des horizons temporels longs.
Le modèle de menace distingue deux classes d'adversaires. L'adversaire rationnel à ressources limitées agit selon un calcul coût/bénéfice, il attaque si ça vaut la peine. L'adversaire à ressources quasi-illimitées peut financer des attaques dont le coût dépasse le bénéfice apparent, dans une perspective stratégique à long terme : maintenir une présence passive dans le réseau pendant des mois (watchers), accumuler des informations permettant de dé-anonymiser des participants, ou reconstruire des stratégies opérationnelles. C'est ce second modèle qui prévaut dans un contexte spatial ou militaire embarqué.
L'analyse couvre trois couches distinctes : la couche réseau et transport, la couche de découverte P2P, et la couche de transactions (données et monétaires). Pour chacune, nous identifions les vecteurs d'attaque connus de la littérature, leur criticité relative selon le contexte d'utilisation (réseau privé vs réseau public hostile), et les mécanismes de mitigation disponibles avec leurs limites résiduelles. Une synthèse tabulaire conclut l'analyse et permet d'orienter les choix architecturaux vers les risques les plus critiques.
L'analyse couvre trois couches : réseau et transport, découverte P2P, transactions (données et monétaires). Pour chacune, on identifie les vecteurs d'attaque connus, leur criticité selon le contexte, et les mécanismes de mitigation avec leurs limites résiduelles.
La conclusion principale de cette étude est que la confiance ne peut, dans ce contexte, être que probabiliste et relative — jamais binaire ni absolue — et que toute architecture ignorant cette réalité est structurellement vulnérable sur le long terme.
Un fil directeur traverse cette analyse : pour la couche de **règlement monétaire** spécifiquement, les risques de double-spend, de transparence transactionnelle et de finalité non déterministe ne trouvent de réponse robuste que dans une blockchain, idéalement confidentielle et souveraine. Les autres couches relèvent de mécanismes distincts documentés dans les propositions architecturales associées.
La conclusion principale est que la confiance ne peut, dans ce contexte, être que probabiliste et relative, jamais binaire ni absolue, et que toute architecture ignorant cette réalité est structurellement vulnérable sur le long terme.
---
## 1. Contexte et Modèle de Menace
### 1.1 Le Problème Fondamental : Confiance sans Autorité Centrale
### 1.1 Le Problème Fondamental
La question de la coordination entre agents sans autorité centrale de confiance est l'un des problèmes fondamentaux de l'informatique distribuée. Lamport, Shostak et Pease [Lamport et al., 1982] ont formalisé ce problème sous la forme du "problème des généraux byzantins" : comment un ensemble de processus peut-il atteindre un consensus lorsque certains d'entre eux peuvent se comporter de manière arbitrairement malveillante ? Leur résultat fondamental établit qu'un consensus fiable est possible si et seulement si la proportion de processus défaillants est strictement inférieure à un tiers de l'ensemble.
La question de la coordination entre agents sans autorité centrale de confiance est l'un des problèmes fondamentaux de l'informatique distribuée. Lamport, Shostak et Pease [14] ont formalisé ce problème sous la forme du "problème des généraux byzantins" : comment atteindre un consensus lorsque certains processus peuvent se comporter de manière arbitrairement malveillante ? Leur résultat établit qu'un consensus fiable est possible si et seulement si la proportion de processus défaillants reste strictement inférieure à un tiers de l'ensemble.
Ce résultat théorique contraint directement toute architecture distribuée opérant dans un environnement hostile : même en supposant que les mécanismes cryptographiques sont parfaits, le nombre de nœuds compromis ou malveillants que le système peut tolérer est borné par la proportion d'un tiers. Au-delà de ce seuil, aucun algorithme de consensus déterministe ne peut garantir la cohérence.
Ce résultat contraint directement toute architecture distribuée en environnement hostile : même avec des mécanismes cryptographiques parfaits, le nombre de nœuds compromis que le système peut tolérer est borné. Au-delà d'un tiers, aucun algorithme de consensus déterministe ne peut garantir la cohérence.
Par ailleurs, le résultat FLP [Fischer, Lynch & Paterson, 1985] démontre l'impossibilité d'un algorithme de consensus déterministe tolérant même une seule panne dans un système purement asynchrone. Ce théorème impose des compromis entre disponibilité, cohérence et tolérance aux pannes que toute architecture doit assumer explicitement, sous peine de créer des zones d'ombre dans les garanties de sécurité.
S'y ajoute le résultat FLP (Fischer, Lynch & Paterson) [9], qui démontre l'impossibilité d'un consensus déterministe tolérant même une seule panne dans un système purement asynchrone. Ce théorème impose des compromis entre disponibilité, cohérence et tolérance aux pannes que toute architecture doit assumer explicitement, sous peine de créer des zones d'ombre dans ses garanties de sécurité.
### 1.2 Contexte Embarqué, Spatial et Hostile : Spécificités DTN
### 1.2 Spécificités DTN
Les réseaux de communication spatiaux et les réseaux embarqués militaires ou industriels partagent des caractéristiques qui les distinguent radicalement des réseaux terrestres filaires sur lesquels la majorité des protocoles P2P ont été conçus.
Les réseaux spatiaux et les réseaux embarqués militaires partagent des caractéristiques qui les distinguent radicalement des réseaux terrestres filaires sur lesquels la majorité des protocoles P2P ont été conçus.
Fall [Fall, 2003] a posé les bases du paradigme DTN (Delay-Tolerant Networking), conçu pour des environnements où les chemins bout-en-bout n'existent pas en permanence, où les latences peuvent s'étendre de secondes à plusieurs heures (communications interplanétaires), et où les protocoles de transport classiques fondés sur TCP/IP s'avèrent inutilisables. La RFC 4838 [Cerf et al., 2007] formalise l'architecture DTN dans le cadre de l'IETF, en introduisant le concept de couche "bundle" qui stocke les messages et les retransmet lors des fenêtres de contact.
Le paradigme DTN (Delay-Tolerant Networking) a été conçu précisément pour ces environnements : chemins bout-en-bout inexistants en permanence, latences de secondes à plusieurs heures, protocoles TCP/IP inutilisables dans leur forme standard. La couche "bundle" (RFC 4838) [4] stocke les messages et les retransmet lors des fenêtres de contact. Dans ce contexte, les hypothèses habituelles des protocoles P2P s'effondrent : connectivité permanente, timeouts courts, heartbeats garantis, détection de panne par timeout.
Dans ce contexte, les hypothèses habituelles des protocoles P2P s'effondrent :
- L'hypothèse de connectivité partielle mais permanente disparaît ;
- Les timeouts TCP standard deviennent inutilisables ;
- Les heartbeats périodiques ne peuvent plus être garantis ;
- La détection de panne par timeout devient ambiguë (panne ou simple absence de connectivité ?).
Ce dernier point mérite attention : dans un réseau DTN, la détection de panne par timeout devient profondément ambiguë. Un nœud absent depuis une heure est-il défaillant, ou simplement hors de couverture radio ? Cette ambiguïté crée des fenêtres d'opportunité pour des adversaires capables d'exploiter les périodes de déconnexion pour injecter de faux états ou corrompre des enregistrements en l'absence de réfutation possible.
Ces contraintes ne sont pas seulement techniques : elles créent des fenêtres d'opportunité pour des adversaires capables d'exploiter les périodes de déconnexion pour injecter de faux états ou corrompre des enregistrements en l'absence de réfutation possible.
### 1.3 Adversaire Rationnel vs Adversaire d'État
### 1.3 Modèle d'Adversaire : Rationnel à Ressources Limitées vs Adversaire d'État
L'adversaire rationnel à ressources limitées optimise un objectif économique. Il attaquera si le bénéfice attendu dépasse le coût. Ce modèle est pertinent pour les attaques opportunistes sur les réseaux P2P publics, la majorité des attaques réelles.
La littérature distingue classiquement deux grandes classes d'adversaires dans les protocoles cryptographiques :
L'adversaire à ressources quasi-illimitées opère dans une logique différente. Il peut maintenir une présence passive sur des années, capturer physiquement des nœuds pour en extraire les secrets cryptographiques, contrôler silencieusement des nœuds compromis pendant des semaines (stealthy Byzantine), et analyser les métadonnées de trafic même en présence de chiffrement de contenu. C'est ce second modèle qui est pertinent pour un contexte spatial ou militaire.
**L'adversaire rationnel à ressources limitées** est un acteur dont le comportement est guidé par l'optimisation d'un objectif économique. Il attaquera si le bénéfice attendu dépasse le coût de l'attaque. Ce modèle est pertinent pour les attaques opportunistes sur les réseaux P2P publics.
### 1.4 Confiance Relative
**L'adversaire à ressources illimitées** peut financer des attaques dont le coût dépasse le bénéfice apparent, dans une perspective stratégique à long terme. Il peut maintenir une présence passive dans le réseau pendant des mois ou des années sans se manifester activement (watchers), accumulant des informations permettant ultérieurement de dé-anonymiser des participants ou de reconstruire des stratégies opérationnelles.
Le modèle de confiance binaire, pair de confiance / pair non-fiable, est inadapté aux environnements complexes. Un pair peut être partiellement compromis, fiable pour certaines opérations mais pas d'autres. La confiance est temporelle : un pair fiable hier peut être compromis aujourd'hui. Et le modèle binaire est vulnérable aux promotions frauduleuses : un adversaire peut se comporter parfaitement pendant longtemps pour atteindre un statut de confiance, puis l'exploiter.
Dans un contexte spatial ou militaire embarqué, c'est ce second modèle qui prévaut. Les hypothèses de sécurité doivent donc être dimensionnées pour un adversaire capable de :
- Capturer physiquement des nœuds et en extraire les secrets ;
- Maintenir une écoute passive à long terme sur tous les canaux visibles ;
- Contrôler silencieusement des nœuds compromis pendant des semaines (Stealthy Byzantine [Amir et al., 2011]) ;
- Analyser les métadonnées de trafic même en présence de chiffrement de contenu.
### 1.4 Confiance Relative : Modèle Continu vs Binaire
Le modèle de confiance binaire (pair de confiance / pair non-fiable) est inadapté aux environnements complexes où les acteurs peuvent être partiellement compromis, temporairement indisponibles, ou simplement peu fiables sans être nécessairement malveillants. La notion de confiance doit être modélisée comme un continuum probabiliste.
Le théorème FLP [Fischer, Lynch & Paterson, 1985] établit qu'en présence d'asynchronisme, un observateur ne peut distinguer de manière déterministe un nœud défaillant d'un nœud simplement lent. Cela implique que tout jugement de confiance sur un pair distant est nécessairement probabiliste : il repose sur une accumulation d'observations cohérentes sur le temps, non sur une preuve déterministe.
Ce constat motive l'adoption de modèles de confiance à scores continus, intégrant des dimensions comportementales (disponibilité historique, précision des réponses, cohérence des données annoncées) plutôt que des jugements binaires susceptibles d'être manipulés par un adversaire capable de jouer sur les délais d'observation.
Le résultat FLP [9] établit en outre qu'en présence d'asynchronisme, un observateur ne peut distinguer de manière déterministe un nœud défaillant d'un nœud simplement lent. Tout jugement de confiance sur un pair distant est donc nécessairement probabiliste, il repose sur une accumulation d'observations cohérentes dans le temps, non sur une preuve déterministe. D'où l'adoption de modèles de confiance à scores continus et multidimensionnels plutôt que de jugements binaires.
### 1.5 Propriétés de Sécurité Visées
Pour ce contexte, les propriétés de sécurité cibles sont les suivantes :
- **Authenticité** : chaque pair peut prouver son identité sans tiers de confiance (identité auto-certifiée).
- **Authenticité** : chaque pair peut prouver son identité sans tiers de confiance.
- **Intégrité** : les données transmises ou stockées ne peuvent être altérées sans détection.
- **Disponibilité** : le système continue de fonctionner en mode dégradé en cas d'indisponibilité partielle.
- **Disponibilité** : le système continue de fonctionner en mode dégradé lors d'indisponibilités partielles.
- **Confidentialité** : le contenu des échanges est opaque pour les observateurs non autorisés.
- **Souveraineté** : les données appartiennent à leur créateur, qui contrôle leur cycle de vie.
- **Non-traçabilité** : l'existence même des échanges doit, dans le cas le plus hostile, être dissimulée.
- **Non-traçabilité** : dans le cas le plus hostile, l'existence même des échanges doit pouvoir être dissimulée.
Ces propriétés sont partiellement antagonistes. La disponibilité et la confidentialité entrent souvent en tension : un système qui chiffre toutes ses communications peut voir sa disponibilité dégradée par l'overhead cryptographique ; un système qui optimise la découverte de pairs maximise la visibilité des participants.
Ces propriétés sont partiellement antagonistes, la disponibilité et la confidentialité entrent régulièrement en tension. Reconnaître ces tensions explicitement est la première étape vers une architecture qui les gère de manière informée plutôt que de les ignorer.
---
@@ -85,326 +69,289 @@ Ces propriétés sont partiellement antagonistes. La disponibilité et la confid
### 2.1 Man-in-the-Middle et Attaques Actives
L'attaque MitM (Man-in-the-Middle) consiste pour un adversaire actif à s'interposer entre deux pairs communicants, en se faisant passer pour chacun d'eux auprès de l'autre. Sans authentification mutuelle des parties, cette attaque est triviale sur tout réseau P2P non protégé.
L'attaque MitM consiste pour un adversaire actif à s'interposer entre deux pairs communicants, se faisant passer pour chacun d'eux. Sans authentification mutuelle, cette attaque est triviale sur tout réseau P2P non protégé.
Le Noise Protocol Framework [Perrin, 2018] offre une réponse adaptée : il fournit des primitives de handshake cryptographique permettant l'authentification mutuelle et l'établissement de canaux chiffrés sans infrastructure PKI centralisée. Le pattern Noise_XX permet une authentification mutuelle des clés publiques sans nécessiter une autorité de certification. Sa légèreté en fait un candidat adapté aux contraintes embarquées.
Le Noise Protocol Framework [21] offre une réponse adaptée : handshake cryptographique avec authentification mutuelle, sans PKI centralisée. Le pattern Noise_XX permet une authentification mutuelle des clés publiques en restant léger pour les contraintes embarquées.
La principale limite résiduelle est celle du premier contact : si un pair ne connaît pas a priori la clé publique de son interlocuteur, le premier échange est vulnérable à un MitM qui substituerait sa propre clé (problème TOFU : Trust On First Use).
La limite résiduelle est le premier contact : si un pair ne connaît pas a priori la clé publique de son interlocuteur, le premier échange est vulnérable à un MitM qui substituerait sa propre clé. C'est le problème TOFU (Trust On First Use), difficile à éliminer sans mécanisme d'enrôlement hors-bande.
### 2.2 Eclipse Attacks — Isolation d'un Pair du Réseau
### 2.2 Eclipse Attacks
Une attaque par éclipse (eclipse attack) vise à monopoliser l'ensemble des connexions entrantes et sortantes d'un pair cible, de sorte que toutes les informations que ce pair reçoit du réseau passent par des nœuds contrôlés par l'adversaire [Heilman et al., 2015]. Une fois isolé, le pair peut être manipulé : l'adversaire lui présente une vue falsifiée du réseau, peut censurer ses messages sortants, ou lui soumettre de fausses transactions.
Une attaque par éclipse vise à monopoliser toutes les connexions entrantes et sortantes d'un pair cible, de sorte que toute l'information qu'il reçoit passe par des nœuds contrôlés par l'adversaire. Une fois isolé, le pair peut être manipulé : vue falsifiée du réseau, censure des messages sortants, soumission de fausses transactions.
Heilman et al. démontrent que cette attaque est réalisable sur Bitcoin avec un nombre limité de connexions adversariales, en exploitant la structure de la table de routage. Pour les réseaux P2P plus généraux, la résistance à cette attaque passe par la diversification des sources de pairs (bootstrap multi-seeds, connexions aléatoires dans des sous-espaces distincts du graphe).
La résistance passe par la diversification des sources de pairs, bootstrap multi-seeds, connexions aléatoires dans des sous-espaces distincts du graphe. Un adversaire contrôlant un ISP ou une infrastructure réseau intermédiaire peut contourner ces mitigations.
### 2.3 Partitionnement Réseau et Problème CAP
### 2.3 Partitionnement Réseau et Théorème CAP
Le théorème CAP, formulé par Brewer [Brewer, 2000] et formalisé par Gilbert et Lynch [Gilbert & Lynch, 2002], établit qu'un système distribué ne peut simultanément garantir la cohérence (Consistency), la disponibilité (Availability) et la tolérance au partitionnement réseau (Partition tolerance). Face à un partitionnement, tout système doit choisir entre cohérence et disponibilité.
Le théorème CAP [3][10] établit qu'un système distribué ne peut simultanément garantir cohérence (Consistency), disponibilité (Availability) et tolérance au partitionnement (Partition tolerance). Face à un partitionnement, le système doit choisir.
Dans un contexte DTN, les partitions réseau ne sont pas des événements exceptionnels : elles sont la norme opérationnelle. Un système de découverte de pairs en contexte spatial doit délibérément favoriser la disponibilité (AP) sur la cohérence forte : un nœud doit pouvoir continuer à opérer même s'il ne peut pas vérifier en temps réel l'état de ses pairs. La cohérence forte est réservée aux opérations critiques (règlement de transactions monétaires), où elle doit être assurée par un mécanisme de consensus distinct.
En contexte DTN, les partitions ne sont pas des événements exceptionnels, elles sont la norme opérationnelle. Un système de découverte de pairs doit délibérément favoriser la disponibilité (AP) : un nœud doit pouvoir continuer à opérer même sans vérifier en temps réel l'état de ses pairs. La cohérence forte est réservée aux opérations critiques, le règlement de transactions monétaires, où elle doit être assurée par une couche séparée avec un consensus distinct.
### 2.4 Traffic Analysis par Acteurs Passifs — Le Watcher Problem
### 2.4 Traffic Analysis, Le Watcher Problem
Le chiffrement de contenu ne suffit pas à protéger contre un adversaire passif capable d'analyser les métadonnées de trafic. Murdoch et Danezis [Murdoch & Danezis, 2005] ont démontré que même sur le réseau Tor, l'analyse des patterns de trafic (timing, volume, fréquence) permet de corréler des flux anonymisés avec leurs sources avec une précision significative.
Le chiffrement de contenu ne suffit pas contre un adversaire passif qui analyse les métadonnées de trafic. Timing, volume, fréquence, patterns de connexion/déconnexion, toutes ces métadonnées révèlent des informations critiques même sans accès au contenu. La fréquence des heartbeats révèle les cycles opérationnels. L'apparition simultanée de plusieurs nœuds révèle une coordination. Des travaux sur les réseaux Bitcoin montrent que l'identification de l'émetteur d'une transaction est possible à partir des seuls patterns de diffusion, sans contenu chiffré [17].
Dans un réseau de découverte P2P, les métadonnées révèlent des informations critiques même en l'absence d'accès au contenu :
- La fréquence des heartbeats révèle les cycles opérationnels d'un nœud ;
- Le volume des échanges avec certains pairs révèle des relations privilégiées ;
- Les patterns de connexion/déconnexion révèlent les horaires d'activité ;
- L'évolution du nombre de pairs connus révèle des phases d'expansion ou de repli.
La mitigation complète (padding temporel, traffic shaping, mixnets) est coûteuse en bande passante, un compromis difficile dans un contexte spatial.
Sun et al. [Sun et al., 2015] ont quantifié l'efficacité de ces attaques sur les réseaux Bitcoin, montrant que l'identification de l'émetteur d'une transaction est possible avec une probabilité élevée à partir de l'analyse des patterns de diffusion, même sans accès au contenu chiffré.
### 2.5 Spécificités DTN : Latences et Discontinuité
### 2.5 Spécificités DTN/Spatial : Latences, Connectivité Intermittente, Impossibilité TCP
Les protocoles P2P conçus pour des réseaux terrestres supposent des connexions TCP stables, des latences de l'ordre de la milliseconde à la centaine de milliseconde, et une disponibilité continue des pairs actifs. Aucune de ces hypothèses ne tient dans un contexte spatial :
- Les communications Terre-orbite basse (LEO) introduisent des latences de 20 à 600 ms selon l'élévation ;
- Les fenêtres de visibilité entre satellites imposent des périodes de contact discontinues ;
- L'énergie disponible contraint le temps de transmission, forçant des modes de veille.
Ces contraintes rendent TCP inutilisable dans sa forme standard : les mécanismes de retransmission, de contrôle de flux et de gestion des timeouts sont dimensionnés pour des latences sub-secondes. Les protocoles de couche bundle définis dans la RFC 4838 [Cerf et al., 2007] offrent une alternative, mais leur adoption dans les systèmes P2P est embryonnaire.
Les communications Terre-orbite basse introduisent des latences de 20 à 600 ms selon l'élévation; les fenêtres de visibilité entre satellites imposent des périodes de contact discontinues; les contraintes énergétiques forcent des modes de veille. TCP est inutilisable dans sa forme standard, les mécanismes de retransmission et de gestion des timeouts sont dimensionnés pour des latences sub-secondes. Les protocoles de couche bundle (RFC 4838) offrent une alternative, mais leur adoption dans les systèmes P2P reste embryonnaire.
---
## 3. Risques de la Couche de Découverte P2P (Sans Confiance)
## 3. Risques de la Couche de Découverte P2P
### 3.1 Sybil Attack : Création Massive d'Identités
### 3.1 Sybil Attack
L'attaque Sybil, formalisée par Douceur [Douceur, 2002], consiste pour un adversaire à créer un grand nombre d'identités pseudonymes dans un réseau P2P, lui permettant d'acquérir une influence disproportionnée sur les mécanismes de consensus, de routage ou de réputation.
La formalisation de Douceur [7] est un résultat fondamental : l'attaque Sybil, création massive d'identités pseudonymes pour acquérir une influence disproportionnée, est **insoluble sans coût d'entrée ou autorité centrale**. En l'absence d'un mécanisme rendant la création d'identités coûteuse ou d'une autorité capable de vérifier les identités, aucun système P2P ne peut garantir une résistance Sybil complète.
Le résultat fondamental de Douceur est que cette attaque est **insoluble sans coût d'entrée ou autorité centrale**. En l'absence d'un mécanisme rendant la création d'identités coûteuse (preuve de travail, preuve d'enjeu, dépôt cryptoéconomique) ou d'une autorité centrale capable de vérifier les identités, aucun système P2P ne peut garantir une résistance Sybil complète.
Dans un contexte embarqué à ressources limitées, les mécanismes de preuve de travail sont énergétiquement prohibitifs. Les clés pré-partagées (PSK) organisationnelles constituent une réponse adaptée pour les réseaux fermés. Pour les réseaux plus ouverts, le scoring comportemental pénalise les pairs nouveaux ou peu fiables, sans résoudre le problème, mais en l'amortissant.
Dans un contexte embarqué à ressources limitées, les mécanismes de preuve de travail sont énergétiquement prohibitifs. Les solutions alternatives incluent les clés pré-partagées (PSK) organisationnelles pour les réseaux fermés, et le scoring comportemental pour pénaliser les pairs nouveaux ou peu fiables — sans résoudre complètement le problème pour les réseaux ouverts.
### 3.2 Empoisonnement des Tables de Routage
### 3.2 Routing Table Poisoning
Le DHT Kademlia [16] organise les pairs dans un espace d'adressage XOR permettant la découverte en O(log n) sauts. Sa table de routage est vulnérable à l'empoisonnement : un adversaire peut insérer de fausses entrées, redirigeant le trafic vers des nœuds malveillants. L'extension S/Kademlia [2] ajoute des contraintes cryptographiques sur la génération des identifiants de nœuds et des signatures sur les messages de routage, ce qui réduit significativement la surface d'attaque sans l'éliminer pour un adversaire disposant de suffisamment de nœuds.
Le DHT Kademlia [Maymounkov & Mazières, 2002] organise les pairs dans un espace d'adressage XOR, permettant la découverte de ressources en O(log n) sauts. Cependant, sa table de routage est vulnérable à l'empoisonnement : un adversaire peut insérer de fausses entrées dans la table d'un pair cible, redirigeant le trafic vers des nœuds malveillants.
### 3.3 Éclipse sur DHT
Baumgart et Meinert [Baumgart & Meinert, 2007] ont proposé S/Kademlia comme extension sécurisée de Kademlia, ajoutant des contraintes cryptographiques sur la génération des identifiants de nœuds et des signatures sur les messages de routage. S/Kademlia réduit significativement la facilité d'empoisonnement des tables de routage, mais n'élimine pas complètement le risque pour un adversaire disposant de suffisamment de nœuds.
En contrôlant un sous-ensemble de nœuds stratégiquement positionnés dans l'espace d'adressage [23], un adversaire peut isoler une région de la DHT et intercepter toutes les requêtes portant sur les identifiants de cette région. Si la DHT est aussi utilisée pour le stockage (pas seulement la découverte), les enregistrements dans la région éclipsée peuvent être supprimés, falsifiés, ou rendus inaccessibles sans détection immédiate.
### 3.3 Attaque d'Éclipse sur DHT
### 3.4 Bootstrap Poisoning
Singh et al. [Singh et al., 2006] ont démontré des attaques d'éclipse spécifiques aux DHT : en contrôlant un sous-ensemble de nœuds strategiquement positionnés dans l'espace d'adressage, un adversaire peut isoler une région de la DHT, interceptant toutes les requêtes de découverte portant sur des identifiants tombant dans cette région.
Tout réseau P2P doit résoudre le premier contact : un nœud rejoignant le réseau doit connaître au moins un pair existant. Les seeds d'amorçage sont donc une cible prioritaire. Bitcoin [19] utilise des DNS seeds distribués opérés par plusieurs entités indépendantes; Tor utilise des directory authorities dont les clés sont codées en dur dans le client. Dans un réseau embarqué hostile, les DNS seeds peuvent être censurés et les clés codées en dur peuvent être extraites par capture physique. Un adversaire contrôlant les seeds peut orienter tous les nouveaux nœuds vers une partition malveillante.
Cette attaque est particulièrement dangereuse pour les systèmes où la DHT est utilisée non seulement pour la découverte mais aussi pour le stockage de données : les enregistrements stockés dans la région éclipsée peuvent être supprimés, falsifiés, ou rendus inaccessibles sans détection immédiate.
### 3.5 Churn Adversarial
### 3.4 Bootstrap Poisoning : Compromission des Seeds d'Amorçage
Un churn élevé dégrade les performances de routage, fragmente les tables, et peut rendre certaines régions de la DHT temporairement inaccessibles. Dans un contexte DTN, le churn n'est pas exceptionnel mais structurel, les nœuds apparaissent et disparaissent selon les fenêtres de contact. Un adversaire peut exploiter cela en injectant massivement des nœuds éphémères qui saturent les tables de routage, déplacent les nœuds légitimes, puis disparaissent avant d'être pénalisés par les mécanismes de scoring.
Tout réseau P2P doit résoudre le problème du premier contact : un nœud rejoignant le réseau doit connaître au moins un pair existant pour s'y connecter. Les seeds d'amorçage (bootstrap nodes) constituent donc un point de défaillance unique ou une cible prioritaire pour un adversaire.
### 3.6 Collusion et Faux Consensus de Scoring
Bitcoin résout partiellement ce problème via des DNS seeds distribués opérés par plusieurs entités indépendantes. Tor utilise des directory authorities dont les clés publiques sont codées en dur dans le client. Dans un réseau embarqué hostile, ces approches présentent des limitations : les DNS seeds peuvent être censurés, et les clés publiques codées en dur peuvent être compromises si un nœud est capturé physiquement.
Un groupe de nœuds malveillants peut s'attribuer mutuellement de bons scores, se recommander mutuellement, et dégrader les scores des nœuds légitimes. Cette attaque est particulièrement insidieuse car difficile à distinguer d'un comportement légitime sans information hors-bande sur la topologie réelle.
Un adversaire capable de contrôler les seeds d'amorçage peut orienter tous les nouveaux nœuds vers une partition malveillante du réseau, les isolant efficacement du réseau légitime.
Les mécanismes de témoin croisé réduisent ce risque, à condition que les témoins interrogés soient suffisamment diversifiés. Un protocole de membership épidémique avec réfutation explicite ajoute une couche de protection : un nœud injustement suspecté peut émettre une réfutation qui neutralise les faux signaux propagés à son encontre. La propagation bornée des événements de membership limite la portée d'une campagne de désinformation à un voisinage local. Ces mécanismes ne résolvent pas la collusion si l'adversaire contrôle une fraction suffisante des nœuds, ils en rendent simplement la conduite plus coûteuse et plus visible.
### 3.5 Churn Excessif et Instabilité du Réseau
### 3.7 Injection de Faux Enregistrements
Rhea et al. [Rhea et al., 2004] ont étudié l'impact du churn (arrivées et départs fréquents de nœuds) sur la stabilité des DHT. Un churn élevé dégrade les performances de routage, fragmente les tables de routage, et peut rendre certaines régions de la DHT inaccessibles temporairement.
Dans un contexte DTN, le churn n'est pas exceptionnel mais structurel. Les nœuds apparaissent et disparaissent selon les fenêtres de contact, créant un churn permanent. Les mécanismes de maintenance des DHT (requêtes périodiques de vérification des voisins, repopulation des k-buckets) doivent être adaptés pour ne pas consommer une bande passante prohibitive dans ce contexte.
Un adversaire peut exploiter le churn en injectant massivement des nœuds éphémères : ces nœuds saturent les tables de routage, déplacent les nœuds légitimes, puis disparaissent avant d'être pénalisés par les mécanismes de scoring.
### 3.6 Collusion entre Pairs et Faux Consensus de Scoring
Les systèmes de réputation décentralisés sont vulnérables aux attaques de collusion : un groupe de nœuds malveillants peut s'attribuer mutuellement de bons scores, se recommander mutuellement, et dégrader les scores des nœuds légitimes par des témoignages falsifiés.
Cette attaque est particulièrement insidieuse car elle est difficile à distinguer d'un comportement légitime sans information hors-bande sur la topologie réelle du réseau. Les mécanismes de témoin croisé (un tiers indépendant observe le comportement du pair) réduisent ce risque mais ne l'éliminent pas si l'adversaire contrôle suffisamment de nœuds pour couvrir tous les angles d'observation.
### 3.7 Injection de Faux Enregistrements de Présence
Dans un contexte hostile, un adversaire peut injecter de faux enregistrements de présence dans la DHT, annonçant l'existence de ressources ou de nœuds fictifs. Cette pollution de la couche de découverte a plusieurs effets négatifs :
- Elle gaspille la bande passante des pairs qui tentent de contacter des nœuds inexistants ;
- Elle peut masquer la découverte de ressources légitimes en saturant les réponses de fausses entrées ;
- Elle peut servir de leurre pour identifier quels nœuds recherchent quels types de ressources (surveillance active via pot de miel).
Un adversaire peut injecter de faux enregistrements de présence dans la DHT, annoncer des ressources ou des nœuds fictifs. Au-delà du gaspillage de bande passante, cette pollution peut servir de leurre pour identifier quels nœuds recherchent quels types de ressources : une surveillance active via pot de miel.
---
## 4. Risques des Transactions de Données
### 4.1 Data Poisoning : Altération Silencieuse des Enregistrements
### 4.1 Data Poisoning
La DHT Kademlia stocke les enregistrements à proximité des nœuds dont l'identifiant est proche de la clé de l'enregistrement. Un adversaire contrôlant des nœuds dans une région de l'espace d'adressage peut altérer silencieusement les enregistrements qui lui sont confiés, substituant des données falsifiées aux données légitimes.
La DHT Kademlia stocke les enregistrements à proximité des nœuds dont l'identifiant est proche de la clé. Un adversaire contrôlant des nœuds dans une région peut altérer silencieusement les enregistrements confiés à ces nœuds. La mitigation standard, enregistrements signés par leur créateur, détecte toute altération, à condition que la clé publique du créateur soit connue et authentique. Ce qui ramène au problème de la distribution des cs publiques.
La mitigation standard repose sur les enregistrements signés : chaque enregistrement porte la signature de son créateur, permettant de détecter toute altération. Cependant, cette protection suppose que la clé publique du créateur est connue et authentique — ce qui ramène au problème de la distribution des clés publiques.
### 4.2 Replay Attacks sur les Records Signés
### 4.2 Replay Attacks
Un adversaire peut capturer un enregistrement signé valide et le rejouer ultérieurement, même après que son auteur a révoqué ou remplacé cet enregistrement. En l'absence de mécanisme de nonce ou de timestamp vérifié cryptographiquement, les enregistrements capturés restent valides indéfiniment du point de vue de leur signature.
Un adversaire peut capturer un enregistrement signé valide et le rejouer ultérieurement, même après révocation. La protection combine nonces et timestamps dans les données signées, mais dans un réseau DTN où les horloges ne sont pas nécessairement synchronisées, la vérification des timestamps introduit des contraintes supplémentaires.
La protection standard combine les timestamps et les numéros de séquence dans la donnée signée. Cependant, dans un réseau DTN où les horloges ne sont pas nécessairement synchronisées, la vérification des timestamps introduit des contraintes supplémentaires.
### 4.3 Tombstone Malveillant
### 4.3 Attaque de Tombstone Malveillante
Un tombstone signale la suppression d'un enregistrement précédent. Un adversaire en possession de la clé privée d'un pair compromis peut émettre de faux tombstones pour invalider des enregistrements légitimes, effaçant effectivement la présence d'un nœud ou la disponibilité d'une ressource. Dans les réseaux à haute durée de vie où les enregistrements ne périment pas rapidement, un tombstone malveillant peut effacer des années d'historique légitime.
Un tombstone est un enregistrement spécial signalant la suppression ou la révocation d'un enregistrement précédent. Un adversaire en possession de la clé privée d'un pair compromis peut émettre de faux tombstones pour invalider des enregistrements légitimes, effaçant effectivement la présence d'un nœud ou la disponibilité d'une ressource du point de vue du réseau.
### 4.4 Souveraineté de la Donnée
Cette attaque est particulièrement grave dans les réseaux à haute durée de vie où les enregistrements ne se périmissent pas rapidement : un tombstone malveillant peut effacer des années d'historique légitime.
### 4.4 Souveraineté de la Donnée : Contrôle du Cycle de Vie
La question de qui contrôle l'expiration et la révocation d'un enregistrement est non triviale dans un réseau décentralisé. Dans les architectures DHT standard, les enregistrements expirent naturellement après un TTL fixe, mais leur renouvellement est à la charge du créateur. Si le créateur est temporairement indisponible (contexte DTN), ses enregistrements expirent, le rendant invisible du réseau.
Inversement, si les enregistrements sont trop durables, un pair compromis ou supprimé reste visible dans la DHT pendant une durée excessive. L'équilibre entre durabilité et fraîcheur des enregistrements constitue un paramètre critique dont les valeurs optimales dépendent du profil de connectivité des nœuds.
Dans les architectures DHT standard, les enregistrements expirent après un TTL fixe et leur renouvellement est à la charge du créateur. Si ce créateur est temporairement indisponible, ce qui est la norme en contexte DTN, ses enregistrements expirent, le rendant invisible du réseau. Inversement, des enregistrements trop durables laissent visibles des pairs compromis ou supprimés. L'équilibre entre durabilité et fraîcheur est un paramètre critique dont les valeurs optimales dépendent du profil de connectivité des nœuds.
### 4.5 Inférence par Analyse de Présence
Même en supposant que le contenu des enregistrements est chiffré, l'analyse des patterns de présence révèle des informations sensibles. La fréquence des heartbeats d'un nœud révèle son cycle opérationnel. L'apparition simultanée de plusieurs nœuds révèle une coordination. La corrélation des moments d'apparition et de disparition avec des événements externes peut permettre de reconstruire des plans opérationnels.
Même avec un contenu entièrement chiffré, les patterns de présence révèlent des informations sensibles : fréquence des heartbeats (cycles opérationnels), apparition simultanée de plusieurs nœuds (coordination), corrélation des moments d'activité avec des événements externes (plans opérationnels). Ce risque est indépendant du chiffrement du contenu, les métadonnées seules constituent une source d'information substantielle.
Ce risque s'applique même dans un réseau entièrement chiffré : les métadonnées de trafic (qui contacte qui, quand, avec quelle fréquence) constituent une source d'information indépendante du contenu.
### 4.6 Linkabilité
### 4.6 Linkabilité : Corrélation d'Identités Pseudonymes
Dans les réseaux P2P utilisant des identités pseudonymes (clés publiques sans identité réelle associée), la corrélation de sessions successives peut permettre de relier différentes identités pseudonymes à un même acteur physique. Si un nœud utilise systématiquement les mêmes sous-ensembles de pairs pour se connecter, cette structure relationnelle constitue une empreinte distinctive.
La linkabilité est particulièrement problématique dans les contextes où un acteur doit interagir successivement avec des pairs dont certains peuvent être adversariaux.
La corrélation de sessions successives peut relier différentes identités pseudonymes à un même acteur physique. Si un nœud utilise systématiquement les mêmes sous-ensembles de pairs pour se connecter, cette structure relationnelle constitue une empreinte distinctive. La rotation d'identité atténue le risque mais crée une friction opérationnelle significative.
---
## 5. Risques des Transactions Monétaires Décentralisées
C'est pour cette couche que les risques sont les plus difficiles à adresser par des mécanismes P2P seuls. Les propriétés d'immuabilité, de finalité déterministe et de règles d'exécution vérifiables sont précisément ce que les transactions monétaires requièrent, et ce qu'une DHT pair-à-pair ne peut pas offrir nativement. C'est ici que l'argument en faveur d'une blockchain dédiée est le plus solide.
### 5.1 Double-Spend dans un Réseau AP
Nakamoto [Nakamoto, 2008] a proposé le premier mécanisme pratique de prévention du double-spend dans un réseau pair-à-pair sans autorité centrale, en s'appuyant sur une chaîne de blocs et une preuve de travail. Ce mécanisme offre une finalité probabiliste : une transaction devient de plus en plus difficile à annuler à mesure que des blocs s'accumulent au-dessus d'elle.
Dans un réseau AP (disponibilité prioritaire sur cohérence), deux nœuds partitionnés peuvent chacun valider indépendamment une transaction utilisant le même actif, créant un conflit qui ne pourra être résolu qu'à la réunification du réseau. Les protocoles classiques de consensus blockchain (PoW, PoS) supposent une connectivité suffisante pour que les messages de consensus atteignent une majorité de validateurs en temps raisonnable — hypothèse violée en contexte DTN.
Dans un réseau AP (disponibilité prioritaire sur cohérence), deux nœuds partitionnés peuvent chacun valider indépendamment une transaction utilisant le même actif. Le conflit ne peut être résolu qu'à la réunification. Nakamoto [19] a résolu ce problème via une chaîne de blocs avec preuve de travail, mais avec finalité probabiliste à l'heure. Les algorithmes de consensus BFT comme Tendermint [12] offrent une finalité déterministe dès la validation du bloc. Un validateur absent pendant une partition DTN est simplement exclu du quorum pour les blocs produits pendant son absence, sans invalider rétroactivement les transactions précédentes.
### 5.2 Front-Running et MEV
Daian et al. [Daian et al., 2020] ont documenté le phénomène de Miner Extractable Value (MEV) : les validateurs de transactions (mineurs ou stakers) peuvent réordonner, insérer ou censurer des transactions au sein d'un bloc pour extraire une valeur maximale, au détriment des utilisateurs ordinaires. Dans un marché de ressources décentralisé, ce phénomène peut prendre la forme d'enchères truquées, de saisie prioritaire de ressources convoitées, ou de censure de transactions concurrentes.
Les validateurs peuvent réordonner, insérer ou censurer des transactions au sein d'un bloc pour en extraire une valeur maximale, le MEV (Miner Extractable Value). Ce n'est pas une attaque au sens classique : c'est une exploitation parfaitement légale des règles du protocole. Dans un marché de ressources décentralisé, cela peut prendre la forme d'enchères truquées ou de saisie prioritaire de ressources convoitées.
Le MEV n'est pas une attaque dans le sens traditionnel du terme : c'est une exploitation parfaitement légale des règles du protocole par les validateurs. Sa prévention requiert des mécanismes de protection de l'ordre des transactions (commit-reveal schemes, batched auctions à ordonnancement aléatoire).
Les blockchains confidentielles suppriment structurellement le MEV basé sur l'information : un validateur qui ne peut pas lire le contenu des transactions ne peut pas les réordonner à son avantage. C'est l'une des propriétés les plus directement utiles des smart contracts confidentiels pour ce contexte.
### 5.3 Oracle Problem
Szabo [Szabo, 1997] a introduit la notion de smart contract — un contrat auto-exécutant dont les termes sont encodés directement dans du code informatique. Un smart contract de règlement de ressources doit typiquement se déclencher lorsqu'une ressource a été effectivement consommée. Mais comment un smart contract, exécuté dans un environnement blockchain fermé, peut-il vérifier un événement du monde réel (exécution d'un calcul, livraison d'une donnée) ?
Un smart contract de règlement doit se déclencher quand une ressource a été effectivement consommée. Mais comment un contrat exécuté dans un environnement blockchain fermé peut-il vérifier un événement du monde réel ? Ce problème d'oracle est fondamentalement non résolu. Les solutions existantes (oracles décentralisés, attestations TEE) réduisent la surface de confiance requise sans l'éliminer. Dans un contexte spatial ou embarqué, la latence de propagation et l'impossibilité d'une confirmation en temps réel rendent la conception de l'oracle particulièrement délicate.
Ce problème d'oracle est fondamentalement non résolu. Les solutions existantes (oracles décentralisés comme Chainlink, attestations TEE) réduisent la surface de confiance requise mais ne l'éliminent pas.
### 5.4 Smart Contract Bugs
### 5.4 Smart Contract Bugs et Reentrancy
L'exploit du DAO en 2016, un bug de reentrancy drainant 60 millions de dollars, a illustré de manière spectaculaire les risques des smart contracts [15]. La vérification formelle est possible pour des contrats simples mais reste hors de portée pour des contrats complexes.
L'exploit du DAO en 2016 a démontré de manière spectaculaire les risques des smart contracts : un bug de reentrancy dans le contrat a permis à un attaquant de drainer environ 60 millions de dollars. Luu et al. [Luu et al., 2016] ont documenté systématiquement les classes de vulnérabilités dans les smart contracts Ethereum, incluant la reentrancy, les problèmes de timestamp, les conditions de course, et les débordements arithmétiques.
CosmWasm, le framework de smart contracts de l'écosystème Cosmos, adopte un modèle d'exécution "actor" qui supprime structurellement les réentrances. Le langage Rust ajoute des garanties de sécurité mémoire à la compilation. Ces propriétés n'éliminent pas tous les bugs, mais éliminent des classes entières de vulnérabilités connues.
Dans un contexte de marché de ressources distribuées, les smart contracts gèrent potentiellement des actifs de valeur significative. La vérification formelle de ces contrats, quoique possible pour des contrats simples, reste hors de portée pour des contrats complexes.
### 5.5 Transparence Blockchain
### 5.5 Confidentialité des Transactions et Transparence Blockchain
La transparence totale des blockchains publiques est antagoniste à la souveraineté des données. Des travaux sur le réseau Bitcoin ont démontré que les transactions, supposément pseudonymes, peuvent être reliées à des entités réelles par analyse de graphe [17], corrélation avec des événements externes, et réutilisation d'adresses. Dans un contexte hostile, la simple visibilité des volumes de transactions entre acteurs révèle des informations stratégiques : qui paie qui, combien, à quelle fréquence.
La transparence totale des blockchains publiques comme Ethereum ou Bitcoin est antagoniste à la souveraineté des données. Meiklejohn et al. [Meiklejohn et al., 2013] ont démontré que les transactions Bitcoin, supposément pseudonymes, peuvent être reliées à des entités réelles avec un taux de succès élevé par analyse de graphe des transactions, corrélation avec des événements externes, et utilisation des adresses de réutilisation.
La réponse passe soit par les zk-SNARKs (Zcash, Penumbra), confidentialité cryptographique pure sans dépendance matérielle, soit par les TEE (Secret Network, Oasis), confidentialité des états de smart contracts dans des enclaves matérielles. L'approche TEE est aujourd'hui la plus mature pour des contrats complexes; l'approche ZK pure est préférable à long terme pour des garanties indépendantes du hardware.
Dans un contexte opérationnel hostile, la simple visibilité des volumes de transactions entre acteurs peut révéler des informations stratégiques critiques : qui paie qui, combien, à quelle fréquence, pour quel type de ressource.
### 5.6 Finalité en Contexte DTN
### 5.6 Finality et Latence : Inadaptation aux Environnements DTN
Les blockchains à preuve de travail offrent une finalité probabiliste : une transaction confirmée par 6 blocs sur Bitcoin est considérée pratiquement irréversible, mais ce processus prend environ une heure dans des conditions normales. Les blockchains à consensus BFT (Tendermint, HotStuff) offrent une finalité déterministe en quelques secondes, mais supposent une connectivité suffisante entre les validateurs.
Dans un réseau DTN à connectivité intermittente, un validateur peut être absent pendant plusieurs heures. Si sa participation est requise pour atteindre le quorum, les transactions sont bloquées pendant toute la durée de son absence.
Les blockchains BFT offrent une finalité déterministe en quelques secondes, mais supposent une connectivité suffisante entre validateurs. Un validateur absent pendant plusieurs heures bloque le quorum si sa participation est requise. La conception du validator set doit anticiper les fenêtres de déconnexion et maintenir un quorum parmi les nœuds présents à chaque instant, ce qui implique un redimensionnement du validator set au-delà du strict minimum nécessaire pour le consensus.
---
## 6. Risques Spécifiques au Contexte Spatial et Embarqué
### 6.1 Connectivité Intermittente et Impossibilité de Heartbeat Continu
### 6.1 Ambiguïté Panne / Absence
Les systèmes de détection de panne par heartbeat périodique supposent une connectivité continue entre les nœuds surveillés et les observateurs. Dans un contexte DTN, un nœud peut être legitimimement injoignable pendant plusieurs heures sans être défaillant. Un mécanisme de détection de panne naïf basé sur des timeouts courts produira des faux positifs massifs, dégradant la qualité du réseau de voisinage.
Dans un réseau DTN, un nœud peut être légitimement injoignable pendant plusieurs heures sans être défaillant. Un mécanisme de détection de panne naïf basé sur des timeouts courts produira des faux positifs massifs. La distinction entre "absent (normal)" et "défaillant ou malveillant" requiert une connaissance du calendrier de contact prévisible, information qui peut elle-même être sensible dans un réseau hostile.
La distinction entre "nœud absent (normal)" et "nœud défaillant ou malveillant" requiert une connaissance du calendrier de contact prévisible — information qui peut elle-même être sensible et non publiable dans un réseau hostile.
L'architecture Nano/Maître apporte une réponse partielle à ce problème. Le maître, présumé plus stable, connaît la feuille de route de ses nanos et peut distinguer une absence orbitale planifiée d'une indisponibilité inattendue, information qu'il peut propager aux autres participants.
### 6.2 Bande Passante Limitée
### 6.2 Bande Passante Contrainte
Les liens de communication satellites présentent des débits asymétriques et limités. Les protocoles P2P verbeux (abondance de messages de maintien de connexion, de propagation de rumeurs, de synchronisation de tables de routage) peuvent consommer une fraction substantielle de la bande passante disponible, laissant peu de capacité pour le trafic applicatif.
Les algorithmes de consensus blockchain (PoW en particulier) sont particulièrement inadaptés : la propagation de blocs volumineux sur des liens à bande passante limitée peut prendre plusieurs minutes, dégradant les performances et créant des conditions propices aux forks.
Les liens satellites présentent des débits asymétriques et limités. Les protocoles P2P verbeux peuvent consommer une fraction substantielle de la bande passante disponible. Le Proof of Work est particulièrement inadapté : la propagation de blocs volumineux sur des liens lents crée des conditions propices aux forks. Les consensus BFT produisent des blocs de taille contrôlée avec un overhead de messages limité, bien plus adaptés.
### 6.3 Contraintes Énergétiques
Les nœuds embarqués spatiaux opèrent sur des bilans énergétiques stricts. Le Proof of Work, qui requiert une dépense énergétique continue proportionnelle à la sécurité offerte, est structurellement incompatible avec ces contraintes. Les algorithmes de consensus alternatifs (Proof of Stake, BFT) présentent des profils énergétiques compatibles mais requièrent une disponibilité réseau plus élevée.
Les nœuds embarqués spatiaux opèrent sur des bilans énergétiques stricts. Le Proof of Work, qui requiert une dépense énergétique continue, est structurellement incompatible. Proof of Stake et BFT présentent des profils énergétiques compatibles.
### 6.4 Isolation Planifiée et Mode Dégradé
### 6.4 Isolation Planifiée et Mode Autonome
Dans les opérations spatiales, des périodes d'isolation planifiée (passage dans l'ombre, maintenance silence radio, orbite en dehors de la couverture sol) font partie du profil opérationnel normal. Le réseau doit être conçu pour fonctionner en mode complètement autonome pendant ces périodes, sans dégradation irréversible de l'état du réseau.
Des périodes d'isolation planifiée (passage dans l'ombre, silence radio, orbite hors couverture) font partie du profil opérationnel normal. Le réseau doit fonctionner en mode complètement autonome pendant ces périodes. Tout état critique doit être répliqué localement; les décisions opérationnelles ne doivent pas requérir de consensus réseau en temps réel; la resynchronisation après reconnexion doit être déterministe et complète.
Cette contrainte impose que tout état critique soit répliqué localement sur le nœud, que les décisions opérationnelles ne requièrent pas de consensus réseau en temps réel, et que la resynchronisation après reconnexion soit déterministe et complète.
### 6.5 Capture Physique et Extraction de Secrets
### 6.5 Attaque Physique : Extraction des Secrets
Un adversaire physiquement présent peut capturer un nœud et en extraire les secrets cryptographiques. La mitigation passe par des modules de sécurité matériels (HSM, Secure Enclave), une rotation régulière des clés, et des procédures de révocation réactives.
Un adversaire physiquement présent peut capturer un nœud embarqué et en extraire les secrets cryptographiques (clés privées, PSK, identifiants de réseau). Cette attaque compromet non seulement le nœud capturé mais potentiellement l'ensemble du réseau si les clés partagées ne sont pas renouvelées rapidement.
### 6.6 Compromission de Longue Durée (Stealthy Byzantine)
La mitigation passe par des modules de sécurité matériels (HSM, Secure Enclave) rendant l'extraction difficile, des mécanismes de rotation régulière des clés, et des procédures de révocation réactives permettant d'invalider rapidement les clés d'un nœud capturé.
### 6.6 Compromission de Longue Durée : Stealthy Byzantine
Amir et al. [Amir et al., 2011] ont documenté les "stealthy Byzantine attacks" : un nœud compromis peut se comporter normalement pendant une longue période pour éviter la détection, puis activer un comportement malveillant coordonné au moment le plus opportun. Ce mode d'attaque est particulièrement dangereux car les mécanismes de réputation basés sur l'historique comportemental accordent une haute confiance aux nœuds de longue date, précisément les cibles préférées de ce type de compromission.
La seule mitigation partielle est la vérification périodique de la cohérence des comportements sur des dimensions difficiles à simuler (précision des challenges cryptographiques, cohérence des données annoncées avec des sources indépendantes), combinée à une surveillance croisée par des témoins multiples.
Un nœud compromis peut se comporter normalement pendant une longue période pour éviter la détection, puis activer un comportement malveillant coordonné au moment opportun. Les mécanismes de réputation basés sur l'historique accordent précisément une haute confiance aux nœuds anciens, les cibles préférées de ce type de compromission. La seule mitigation partielle est la vérification périodique de la cohérence des comportements sur des dimensions difficiles à simuler, combinée à une surveillance croisée par des témoins multiples.
---
## 7. Gestion de la Confiance Relative et des Consortiums
### 7.1 Pourquoi la Confiance Binaire Échoue dans un Réseau Hostile
### 7.1 Pourquoi la Confiance Binaire Échoue
Un modèle de confiance binaire associe à chaque pair un état discret : "de confiance" ou "non-fiable". Ce modèle échoue dans les environnements complexes pour plusieurs raisons :
Un modèle binaire de confiance échoue pour trois raisons complémentaires : un pair peut être partiellement compromis (fiable pour certaines opérations, pas d'autres); la confiance est temporelle (hier fiable ne garantit pas aujourd'hui); le modèle est vulnérable aux promotions frauduleuses (se comporter parfaitement en attendant d'accumuler du crédit, puis exploiter ce crédit). Un modèle continu à score multidimensionnel rend la manipulation plus coûteuse et plus visible : altérer simultanément plusieurs dimensions comportementales de manière cohérente requiert une sophistication bien supérieure à la simple patience.
Premièrement, un pair peut être partiellement compromis — fiable pour certaines opérations mais non pour d'autres. Deuxièmement, la confiance est temporelle : un pair fiable hier peut être compromis aujourd'hui. Troisièmement, le modèle binaire est vulnérable aux promotions frauduleuses : un adversaire peut se comporter parfaitement pendant une longue période pour atteindre le statut "de confiance", puis exploiter ce statut.
### 7.2 TOFU et ses Limites
Un modèle continu à score multidimensionnel offre une résistance bien supérieure en rendant la manipulation plus coûteuse et plus facile à détecter : altérer simultanément plusieurs dimensions comportementales de manière cohérente requiert une sophistication bien supérieure à la simple patience.
Le paradigme TOFU (Trust On First Use) accepte la clé publique d'un pair au premier contact et la considère ensuite comme authentique. Pragmatique, mais vulnérable à ce premier contact : un adversaire capable d'intercepter la première connexion peut substituer sa propre clé. SSH couple TOFU à une alerte en cas de changement ultérieur, raisonnable pour une topologie stable, problématique quand les nœuds sont fréquemment remplacés ou réinitialisés.
### 7.2 Trust on First Use (TOFU) et ses Limites
### 7.3 Gouvernance des Consortiums
Le paradigme TOFU accepte la clé publique d'un pair lors du premier contact et la considère ensuite comme authentique. Cette approche est pragmatique mais présente une vulnérabilité critique au premier contact : un adversaire capable d'intercepter cette première connexion peut substituer sa propre clé.
Les consortiums définissent des sous-groupes de pairs avec une confiance a priori plus élevée, sur la base d'une relation organisationnelle hors-bande. La gouvernance soulève des questions précises : qui admet de nouveaux membres ? Quel quorum pour exclure un membre ? Ces décisions ne peuvent être prises de manière décentralisée que si un mécanisme de consensus approprié existe, et ces décisions partagent exactement les mêmes exigences que les transactions monétaires (finalité déterministe, résistance byzantine, auditabilité). Il est donc naturel d'utiliser la même infrastructure blockchain pour les deux.
SSH utilise TOFU couplé à une alerte en cas de changement ultérieur de la clé. Cette approche est raisonnable pour les réseaux à topologie relativement stable, mais problématique dans les réseaux où les nœuds sont fréquemment remplacés ou réinitialisés.
Dans l'écosystème Cosmos, chaque consortium peut opérer sa propre zone avec des propositions onchain pour l'admission et l'exclusion de validateurs, les mises à jour de protocole, et les modifications de paramètres. Cette convergence évite la fragmentation entre mécanismes de gouvernance hors-bande et mécanismes de règlement onchain.
### 7.3 Consortiums à Confiance Choisie : Modèles de Gouvernance
### 7.4 Révocation Sans Autorité Centrale
Les consortiums permettent de définir explicitement des sous-groupes de pairs pour lesquels une confiance a priori plus élevée est accordée, sur la base d'une relation organisationnelle hors-bande. Dans un contexte spatial ou militaire, ces consortiums correspondent typiquement à des coalitions ou à des unités opérationnelles.
La gouvernance de ces consortiums soulève des questions : qui peut admettre de nouveaux membres ? Selon quel mécanisme ? Quel quorum est requis pour l'exclusion d'un membre ? Ces décisions de gouvernance ne peuvent elles-mêmes être prises de manière décentralisée que si un mécanisme de consensus approprié existe pour les supporters.
### 7.4 Révocation de Confiance Sans Autorité Centrale : Le Problème Non Résolu
La révocation d'un membre d'un consortium sans autorité centrale est un problème partiellement ouvert. Les Certificate Revocation Lists (CRL) et l'OCSP des PKI traditionnelles supposent une autorité de révocation centrale. Dans un réseau décentralisé, la révocation doit être propagée de manière épidémique — mais une propagation épidémique peut être bloquée si l'adversaire contrôle les canaux de communication des nœuds informés de la révocation.
La révocation d'un membre sans autorité centrale est un problème partiellement ouvert. Dans un réseau décentralisé, la révocation doit être propagée de manière épidémique, mais une propagation épidémique peut être bloquée si l'adversaire contrôle les canaux de communication des nœuds informés de la révocation.
### 7.5 Propagation Épidémique des Signaux de Méfiance
Das, Gupta et Motivala [Das et al., 2002] ont proposé le protocole SWIM (Scalable Weakly-consistent Infection-style Process Group Membership) pour la détection de panne distribuée. Le principe de base — infection-style propagation — peut être étendu à la propagation de signaux de méfiance : un nœud ayant observé un comportement suspect diffuse cette information à un sous-ensemble aléatoire de ses pairs, qui la propagent à leur tour.
Cette approche offre une convergence probabiliste en O(log n) étapes, mais est vulnérable si l'adversaire contrôle une fraction significative des canaux de propagation ou peut identifier et bloquer sélectivement les messages de méfiance le concernant.
Le protocole SWIM [6] (Scalable Weakly-consistent Infection-style Process Group Membership) peut être étendu à la propagation de signaux de méfiance : un nœud ayant observé un comportement suspect diffuse cette information à un sous-ensemble aléatoire de ses pairs. Convergence probabiliste en O(log n) étapes. Vulnérable si l'adversaire contrôle une fraction significative des canaux ou peut identifier et bloquer sélectivement les messages de méfiance le concernant.
---
## 8. Synthèse et Classification des Risques
Le tableau suivant synthétise les risques identifiés, leur criticité selon le contexte, et les mitigations disponibles :
| Risque | Couche | Criticité (réseau privé) | Criticité (réseau hostile) | Mitigation principale | Limite résiduelle |
|---|---|---|---|---|---|
| MitM actif | Transport | Élevée | Critique | Noise Protocol Framework (mutual auth) | Vulnérabilité TOFU au premier contact |
| Eclipse attack | Réseau | Moyenne | Élevée | Diversification des connexions, multi-seeds | Adversaire contrôlant un ISP |
| Partitionnement réseau | Réseau | Faible | Élevée | Choix AP délibéré, cohérence relaxée | Forks d'état lors de la réunification |
| MitM actif | Transport | Élevée | Critique | Noise Protocol (mutual auth) | Vulnérabilité TOFU au premier contact |
| Eclipse attack | Réseau | Moyenne | Élevée | Diversification connexions, multi-seeds | Adversaire contrôlant un ISP |
| Partitionnement | Réseau | Faible | Élevée | AP délibéré (découverte) / BFT (règlement) | Forks d'état à la réunification |
| Traffic analysis | Transport | Faible | Critique | Padding, traffic shaping, mixnets | Coût prohibitif à grande échelle |
| Sybil attack | Découverte | Faible (PSK) | Élevée | PSK organisationnelle + scoring comportemental | Réseau ouvert hostile non résolu |
| Routing table poisoning | Découverte | Moyenne | Élevée | S/Kademlia (signatures sur messages) | Adversaire avec fraction > 1/3 |
| Eclipse sur DHT | Découverte | Moyenne | Élevée | Distribution des seeds, diversité des voisins | Compromis performance/sécurité |
| Bootstrap poisoning | Découverte | Faible | Critique | Multi-seeds distribués, clés codées en dur | Seeds = ancre de confiance unique |
| Churn adversarial | Découverte | Faible | Moyenne | Rate limiting, délai de grâce | Difficile à distinguer du churn normal |
| Collusion scoring | Découverte | Faible | Élevée | Témoin croisé, challenges multidimensionnels | Insoluble si adversaire > 1/3 |
| Sybil attack | Découverte P2P | Faible (PSK) | Élevée | PSK organisationnelle + scoring | Réseau ouvert hostile non résolu |
| Routing table poisoning | Découverte P2P | Moyenne | Élevée | S/Kademlia | Adversaire avec fraction > 1/3 |
| Eclipse sur DHT | Découverte P2P | Moyenne | Élevée | Multi-seeds, diversité des voisins | Compromis performance/sécurité |
| Bootstrap poisoning | Découverte P2P | Faible | Critique | Multi-seeds distribués | Seeds = ancre de confiance unique |
| Churn adversarial | Découverte P2P | Faible | Moyenne | Rate limiting, délai de grâce | Difficile à distinguer du churn normal |
| Collusion scoring | Découverte P2P | Faible | Élevée | Témoin croisé, challenges multidimensionnels | Insoluble si adversaire > 1/3 |
| Data poisoning | Données | Élevée | Critique | Records signés | Distribution des clés publiques |
| Replay attack | Données | Moyenne | Élevée | Nonce + timestamp dans payload signé | Synchronisation d'horloge en DTN |
| Tombstone malveillant | Données | Moyenne | Élevée | Signature + timestamp de révocation | Compromission de clé privée |
| Replay attack | Données | Moyenne | Élevée | Nonce + timestamp signé | Synchronisation d'horloge en DTN |
| Tombstone malveillant | Données | Moyenne | Élevée | Signature + timestamp révocation | Compromission de clé privée |
| Inférence par présence | Données | Faible | Critique | Padding temporel, faux heartbeats | Coût en bande passante |
| Linkabilité | Données | Faible | Élevée | Rotation d'identité, padding | Difficulté opérationnelle |
| Double-spend | Monétaire | Élevée | Élevée | Consensus BFT (finalité déterministe) | Indisponibilité des validateurs |
| MEV / Front-running | Monétaire | Moyenne | Élevée | Commit-reveal, batch auctions | Résistance imparfaite |
| Oracle problem | Monétaire | Élevée | Élevée | TEE attestations, ZK-proofs | Surface de confiance matérielle |
| Smart contract bug | Monétaire | Élevée | Élevée | Vérification formelle, audits | Impossibilité de vérification complète |
| Transparence blockchain | Monétaire | Moyenne | Critique | ZK-SNARKs, TEE confidential contracts | Maturité des solutions (ZK) |
| Stealthy Byzantine | Tous | Faible | Élevée | Scoring multidimensionnel + témoins | Détection possible seulement a posteriori |
| Capture physique | Tous | Faible | Critique | HSM, rotation régulière des clés | Fenêtre de compromission avant révocation |
| Linkabilité | Données | Faible | Élevée | Rotation d'identité, padding | Friction opérationnelle |
| Double-spend | **Règlement monétaire** | Élevée | Élevée | **Blockchain BFT (finalité déterministe)** | Indisponibilité des validateurs |
| MEV / Front-running | **Règlement monétaire** | Moyenne | Élevée | **Blockchain confidentielle (contrats chiffrés)** | Résistance imparfaite si contenu visible |
| Oracle problem | **Règlement monétaire** | Élevée | Élevée | TEE attestations, ZK-proofs | Surface de confiance matérielle ou crypto |
| Smart contract bug | **Règlement monétaire** | Élevée | Élevée | **CosmWasm/Rust (pas de reentrancy)** | Vérification formelle incomplète |
| Transparence blockchain | **Règlement monétaire** | Moyenne | Critique | **Blockchain confidentielle (Secret Network / ZK)** | Maturité ZK pure, dépendance SGX |
| Finalité en DTN | **Règlement monétaire** | Faible | Élevée | **BFT, validator set dimensionné pour absences** | Quorum impossible si partition longue |
| Stealthy Byzantine | Tous | Faible | Élevée | Scoring multidimensionnel + témoins | Détection a posteriori seulement |
| Capture physique | Tous | Faible | Critique | HSM, rotation régulière des clés | Fenêtre avant révocation |
Un patron clair se dégage : les risques de la couche de règlement monétaire forment une classe cohérente dont les mitigations convergent toutes vers le même outil, une blockchain à consensus BFT, idéalement confidentielle. Les couches de découverte P2P et de données relèvent de mécanismes distincts et complémentaires.
---
## 9. Conclusion
Quatre observations structurent la synthèse de cette analyse.
**Nécessitée de la séparation des couches** Les risques des trois couches analysées requièrent des mécanismes de mitigation fondamentalement différents. La séparation entre la couche de découverte (profil AP) et la couche de règlement monétaire (profil CP) est dictée par le théorème CAP : les prérequis des deux sont mutuellement incompatibles, et tenter de les couvrir avec un seul outil dégraderait inévitablement les garanties sur au moins une dimension.
**Les risques DTN dans les couches découverte et données ont trouvé des réponses concrètes.** Un cache de messages à deux niveaux de criticité, retry indéfini avec persistance chiffrée pour les mutations de ressources, retry limité pour les confirmations, protège contre les pertes dues à l'intermittence, avec des règles de cycle de vie qui garantissent la cohérence de l'état final quelle que soit la durée de l'interruption. Un mécanisme de réveil intégré aux heartbeats existants permet aux nœuds ayant des messages en attente de signaler cette attente sans canal dédié ni timer additionnel. L'architecture Nano/Maître fournit une délégation formelle pour les nœuds à très faible disponibilité, avec réconciliation déterministe des conflits de réservation. Ce sont des réponses architecturalement fondées, non des pistes prospectives.
**Pour le règlement monétaire, la blockchain** Double-spend, transparence transactionnelle, front-running, non-finalité, aucun de ces risques ne trouve de réponse robuste dans des mécanismes P2P seuls. La piste retenue, zones Cosmos souveraines par consortium + règlement inter-consortium confidentiel via Secret Network, avec migration anticipée vers Penumbra, est architecturalement solide. Elle n'est pas encore intégrée dans le projet; c'est le chantier qui reste ouvert.
**La confiance reste probabiliste.** Même avec une blockchain souveraine BFT pour le règlement et un système de scoring comportemental multidimensionnel pour la découverte, la confiance dans ce contexte ne peut être qu'approximative. Le résultat de Douceur sur les attaques Sybil, le théorème FLP sur l'impossibilité du consensus déterministe en système asynchrone, et les stealthy Byzantine attacks rappellent que les garanties absolues n'existent pas. L'objectif n'est pas d'éliminer le risque, c'est d'en rendre l'exploitation suffisamment coûteuse pour que l'adversaire, même bien doté, préfère d'autres vecteurs.
---
## Références Bibliographiques
**[Amir et al., 2011]** Amir, Y., Coan, B., Kirsch, J., & Lane, J. (2011). Prime: Byzantine Replication Under Attack. *IEEE Transactions on Dependable and Secure Computing*, 8(4), 564577.
**[1] [Amir et al., 2011]** Amir, Y., Coan, B., Kirsch, J., & Lane, J. (2011). Prime: Byzantine Replication Under Attack. *IEEE Transactions on Dependable and Secure Computing*, 8(4), 564577.
**[Baumgart & Meinert, 2007]** Baumgart, I., & Meinert, S. (2007). S/Kademlia: A practicable approach towards secure key-based routing. In *Proceedings of the 2007 International Conference on Parallel and Distributed Systems (ICPADS)*, pp. 18.
**[2] [Baumgart & Meinert, 2007]** Baumgart, I., & Meinert, S. (2007). S/Kademlia: A practicable approach towards secure key-based routing. In *Proceedings of ICPADS 2007*, pp. 18.
**[Brewer, 2000]** Brewer, E. A. (2000). Towards robust distributed systems. In *Proceedings of the 19th Annual ACM Symposium on Principles of Distributed Computing (PODC)*, pp. 7. (Keynote address).
**[3] [Brewer, 2000]** Brewer, E. A. (2000). Towards robust distributed systems. In *Proceedings of PODC 2000*, pp. 7.
**[Cerf et al., 2007]** Cerf, V., Burleigh, S., Hooke, A., Torgerson, L., Durst, R., Scott, K., Fall, K., & Weiss, H. (2007). Delay-Tolerant Networking Architecture. *RFC 4838*, IETF.
**[4] [Cerf et al., 2007]** Cerf, V., et al. (2007). Delay-Tolerant Networking Architecture. *RFC 4838*, IETF.
**[Daian et al., 2020]** Daian, P., Goldfeder, S., Kell, T., Li, Y., Zhao, X., Bentov, I., Breidenbach, L., & Juels, A. (2020). Flash Boys 2.0: Frontrunning in Decentralized Exchanges, Miner Extractable Value, and Consensus Instability. In *Proceedings of the 2020 IEEE Symposium on Security and Privacy (S&P)*, pp. 910927.
**[5] [Daian et al., 2020]** Daian, P., et al. (2020). Flash Boys 2.0. In *Proceedings of the 2020 IEEE S&P*, pp. 910927.
**[Das et al., 2002]** Das, A., Gupta, I., & Motivala, A. (2002). SWIM: Scalable Weakly-consistent Infection-style Process Group Membership Protocol. In *Proceedings of the 2002 International Conference on Dependable Systems and Networks (DSN)*, pp. 303312.
**[6] [Das et al., 2002]** Das, A., Gupta, I., & Motivala, A. (2002). SWIM: Scalable Weakly-consistent Infection-style Process Group Membership Protocol. In *Proceedings of DSN 2002*, pp. 303312.
**[Douceur, 2002]** Douceur, J. R. (2002). The Sybil Attack. In *Proceedings of the 1st International Workshop on Peer-to-Peer Systems (IPTPS)*, LNCS 2429, pp. 251260.
**[7] [Douceur, 2002]** Douceur, J. R. (2002). The Sybil Attack. In *Proceedings of IPTPS 2002*, LNCS 2429, pp. 251260.
**[Fall, 2003]** Fall, K. (2003). A delay-tolerant network architecture for challenged internets. In *Proceedings of the 2003 Conference on Applications, Technologies, Architectures, and Protocols for Computer Communications (SIGCOMM)*, pp. 2734.
**[8] [Fall, 2003]** Fall, K. (2003). A delay-tolerant network architecture for challenged internets. In *Proceedings of SIGCOMM 2003*, pp. 2734.
**[Fischer, Lynch & Paterson, 1985]** Fischer, M. J., Lynch, N. A., & Paterson, M. S. (1985). Impossibility of distributed consensus with one faulty process. *Journal of the ACM (JACM)*, 32(2), 374382.
**[9] [Fischer, Lynch & Paterson, 1985]** Fischer, M. J., Lynch, N. A., & Paterson, M. S. (1985). Impossibility of distributed consensus with one faulty process. *JACM*, 32(2), 374382.
**[Gilbert & Lynch, 2002]** Gilbert, S., & Lynch, N. (2002). Brewer's conjecture and the feasibility of consistent, available, partition-tolerant web services. *ACM SIGACT News*, 33(2), 5159.
**[10] [Gilbert & Lynch, 2002]** Gilbert, S., & Lynch, N. (2002). Brewer's conjecture and the feasibility of consistent, available, partition-tolerant web services. *ACM SIGACT News*, 33(2), 5159.
**[Heilman et al., 2015]** Heilman, E., Kendler, A., Zohar, A., & Goldberg, S. (2015). Eclipse Attacks on Bitcoin's Peer-to-Peer Network. In *Proceedings of the 24th USENIX Security Symposium*, pp. 129144.
**[11] [Heilman et al., 2015]** Heilman, E., et al. (2015). Eclipse Attacks on Bitcoin's Peer-to-Peer Network. In *Proceedings of the 24th USENIX Security Symposium*, pp. 129144.
**[Lamport, Shostak & Pease, 1982]** Lamport, L., Shostak, R., & Pease, M. (1982). The Byzantine Generals Problem. *ACM Transactions on Programming Languages and Systems (TOPLAS)*, 4(3), 382401.
**[12] [Kwon, 2014]** Kwon, J. (2014). *Tendermint: Consensus without Mining*. Draft whitepaper.
**[Luu et al., 2016]** Luu, L., Chu, D.-H., Olickel, H., Saxena, P., & Hobor, A. (2016). Making Smart Contracts Smarter. In *Proceedings of the 2016 ACM SIGSAC Conference on Computer and Communications Security (CCS)*, pp. 254269.
**[13] [Kwon & Buchman, 2016]** Kwon, J., & Buchman, E. (2016). *Cosmos: A Network of Distributed Ledgers*. Whitepaper.
**[Maymounkov & Mazières, 2002]** Maymounkov, P., & Mazières, D. (2002). Kademlia: A Peer-to-Peer Information System Based on the XOR Metric. In *Proceedings of the 1st International Workshop on Peer-to-Peer Systems (IPTPS)*, LNCS 2429, pp. 5365.
**[14] [Lamport, Shostak & Pease, 1982]** Lamport, L., Shostak, R., & Pease, M. (1982). The Byzantine Generals Problem. *ACM TOPLAS*, 4(3), 382401.
**[Meiklejohn et al., 2013]** Meiklejohn, S., Pomarole, M., Jordan, G., Levchenko, K., McCoy, D., Voelker, G. M., & Savage, S. (2013). A Fistful of Bitcoins: Characterizing Payments Among Men with No Names. In *Proceedings of the 2013 Internet Measurement Conference (IMC)*, pp. 127140.
**[15] [Luu et al., 2016]** Luu, L., et al. (2016). Making Smart Contracts Smarter. In *Proceedings of CCS 2016*, pp. 254269.
**[Murdoch & Danezis, 2005]** Murdoch, S. J., & Danezis, G. (2005). Low-Cost Traffic Analysis of Tor. In *Proceedings of the 2005 IEEE Symposium on Security and Privacy (S&P)*, pp. 183195.
**[16] [Maymounkov & Mazières, 2002]** Maymounkov, P., & Mazières, D. (2002). Kademlia: A Peer-to-Peer Information System Based on the XOR Metric. In *Proceedings of IPTPS 2002*, LNCS 2429, pp. 5365.
**[Nakamoto, 2008]** Nakamoto, S. (2008). Bitcoin: A Peer-to-Peer Electronic Cash System. *Whitepaper*. https://bitcoin.org/bitcoin.pdf
**[17] [Meiklejohn et al., 2013]** Meiklejohn, S., et al. (2013). A Fistful of Bitcoins. In *Proceedings of IMC 2013*, pp. 127140.
**[Rhea et al., 2004]** Rhea, S., Geels, D., Roscoe, T., & Kubiatowicz, J. (2004). Handling Churn in a DHT. In *Proceedings of the 2004 USENIX Annual Technical Conference*, pp. 127140.
**[18] [Murdoch & Danezis, 2005]** Murdoch, S. J., & Danezis, G. (2005). Low-Cost Traffic Analysis of Tor. In *Proceedings of the 2005 IEEE S&P*, pp. 183195.
**[Singh et al., 2006]** Singh, A., Castro, M., Druschel, P., & Rowstron, A. (2006). Defending against Eclipse attacks on overlay networks. In *Proceedings of the 11th Workshop on ACM SIGOPS European Workshop*, article 21.
**[19] [Nakamoto, 2008]** Nakamoto, S. (2008). Bitcoin: A Peer-to-Peer Electronic Cash System. https://bitcoin.org/bitcoin.pdf
**[Stoica et al., 2003]** Stoica, I., Morris, R., Liben-Nowell, D., Karger, D. R., Kaashoek, M. F., Dabek, F., & Balakrishnan, H. (2003). Chord: A scalable peer-to-peer lookup protocol for internet applications. *IEEE/ACM Transactions on Networking*, 11(1), 1732.
**[20] [Penumbra Labs, 2022]** Penumbra Labs (2022). *Penumbra: A Fully Private Proof-of-Stake Network for the Cosmos Ecosystem*. Technical specification. https://penumbra.zone
**[Sun et al., 2015]** Sun, Y., Edmundson, A., Vanbever, L., Li, O., Rexford, J., Chiang, M., & Mittal, P. (2015). RAPTOR: Routing Attacks on Privacy in Tor. In *Proceedings of the 24th USENIX Security Symposium*, pp. 271286.
**[21] [Perrin, 2018]** Perrin, T. (2018). *The Noise Protocol Framework*. https://noiseprotocol.org/noise.pdf
**[Szabo, 1997]** Szabo, N. (1997). Formalizing and securing relationships on public networks. *First Monday*, 2(9).
**[22] [Rhea et al., 2004]** Rhea, S., et al. (2004). Handling Churn in a DHT. In *Proceedings of USENIX ATC 2004*, pp. 127140.
**[23] [Singh et al., 2006]** Singh, A., Castro, M., Druschel, P., & Rowstron, A. (2006). Defending against Eclipse attacks on overlay networks. In *Proceedings of the 11th ACM SIGOPS European Workshop*, article 21.
**[24] [Stoica et al., 2003]** Stoica, I., et al. (2003). Chord: A scalable peer-to-peer lookup protocol for internet applications. *IEEE/ACM Transactions on Networking*, 11(1), 1732.
**[25] [Sun et al., 2015]** Sun, Y., et al. (2015). RAPTOR: Routing Attacks on Privacy in Tor. In *Proceedings of the 24th USENIX Security Symposium*, pp. 271286.
**[26] [Szabo, 1997]** Szabo, N. (1997). Formalizing and securing relationships on public networks. *First Monday*, 2(9).
+2
View File
@@ -175,3 +175,5 @@ require (
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
replace cloud.o-forge.io/core/oc-lib => ../oc-lib