fully working selectunusedcircuit.go and SendSessionKeys test

This commit is contained in:
херетик
2023-02-05 15:17:37 +00:00
parent fd34975e81
commit 03dc4b21d0
11 changed files with 104 additions and 94 deletions

View File

@@ -21,11 +21,9 @@ posting it, it became recognised that code, and encryption, are protected
speech.
With ubiquitous 128 and 256 bit AES encryption now in use by default, the
content of
messages is secure. However, the volume of messages and endpoints of signals are
still
useful intelligence data, enabling state level actors to attack internet
users and violate their privacy and threaten their safety.
content of messages is secure. However, the volume of messages and endpoints of
signals are still useful intelligence data, enabling state level actors to
attack internet users and violate their privacy and threaten their safety.
Protecting against this high level attack the main network currently doing
this work is the [Tor network](https://torproject.org). However, this system
@@ -46,14 +44,14 @@ for retaliation when used to abuse such external systems.
Indranet's purpose is to form an interconnect layer for decentralised network
protocols. It requires Lightning Network, as a primary requirement, to enable
the payment for bandwidth, and thus it also requires connectivity to the
Bitcoin network. Thus, all nodes, both relays and clients, will provide exit
traffic for these two protocols, especially Bitcoin, which has a very low
the payment for bandwidth, and thus it also requires connectivity to the
Bitcoin network. Thus, all nodes, both relays and clients, will provide exit
traffic for these two protocols, especially Bitcoin, which has a very low
bandwidth requirement for simple transaction publishing.
Users will potentially be able to set up arbitrary exit services, but the core
project will only target connectivity with decentralised peer to peer services.
Secondarily, it will be possible for users to set up private, non advertised
Secondarily, it will be possible for users to set up private, non advertised
exit services, protected via certificate authentication, such as SSH and other
remote access systems. This will serve to displace the use cases for Tor with
SSH and web services.

View File

@@ -2,6 +2,7 @@ package nonce
import (
"crypto/rand"
"encoding/hex"
"git-indra.lan/indra-labs/indra/pkg/crypto/sha256"
)
@@ -12,6 +13,10 @@ const IDLen = 8
// time it generates 2^32 new ID's.
type ID [IDLen]byte
func (id ID) String() string {
return hex.EncodeToString(id[:])
}
var seed sha256.Hash
var counter uint32

View File

@@ -5,10 +5,10 @@ import (
"sync"
"testing"
"time"
"github.com/cybriq/qu"
"go.uber.org/atomic"
"git-indra.lan/indra-labs/indra/pkg/crypto/nonce"
"git-indra.lan/indra-labs/indra/pkg/crypto/sha256"
log2 "git-indra.lan/indra-labs/indra/pkg/proc/log"
@@ -26,7 +26,7 @@ func TestClient_SendSessionKeys(t *testing.T) {
log2.SetLogLevel(log2.Debug)
var clients []*Engine
var e error
if clients, e = CreateNMockCircuits(false, 1); check(e) {
if clients, e = CreateNMockCircuits(false, 2); check(e) {
t.Error(e)
t.FailNow()
}
@@ -46,14 +46,10 @@ func TestClient_SendSessionKeys(t *testing.T) {
t.Error("SendSessionKeys test failed")
os.Exit(1)
}()
log.I.Ln(clients[0].GetLocalNodeAddress())
for i := 0; i < 10; i++ {
log.D.Ln("buying sessions", i)
wg.Add(1)
counter.Inc()
for i := range clients[0].SessionCache {
log.I.F("%x %v", i, clients[0].SessionCache[i])
}
e = clients[0].BuyNewSessions(1000000, func() {
wg.Done()
counter.Dec()
@@ -63,6 +59,9 @@ func TestClient_SendSessionKeys(t *testing.T) {
counter.Dec()
}
wg.Wait()
for j := range clients[0].SessionCache {
log.D.F("%d %s %v", i, j, clients[0].SessionCache[j])
}
}
for _, v := range clients {
v.Shutdown()

View File

@@ -3,9 +3,9 @@ package relay
import (
"fmt"
"reflect"
"github.com/davecgh/go-spew/spew"
"git-indra.lan/indra-labs/indra/pkg/onion"
"git-indra.lan/indra-labs/indra/pkg/onion/layers/balance"
"git-indra.lan/indra-labs/indra/pkg/onion/layers/confirm"
@@ -36,7 +36,7 @@ func (eng *Engine) handler() (out bool) {
case b := <-eng.ReceiveToLocalNode(0):
eng.handleMessage(b, prev)
case p := <-eng.GetLocalNode().PaymentChan.Receive():
log.D.F("incoming payment for %x: %v", p.ID, p.Amount)
log.D.F("incoming payment for %s: %v", p.ID, p.Amount)
topUp := false
eng.IterateSessions(func(s *traffic.Session) bool {
if s.Preimage == p.Preimage {

View File

@@ -2,9 +2,9 @@ package relay
import (
"fmt"
"git-indra.lan/indra-labs/lnd/lnd/lnwire"
"git-indra.lan/indra-labs/indra/pkg/crypto/nonce"
"git-indra.lan/indra-labs/indra/pkg/onion"
"git-indra.lan/indra-labs/indra/pkg/onion/layers/session"
@@ -18,10 +18,10 @@ import (
// the sessions will be paid the amount specified, not divided up.
func (eng *Engine) BuyNewSessions(amount lnwire.MilliSatoshi,
hook func()) (e error) {
log.D.Ln("buying new sessions")
var nodes [5]*traffic.Node
nodes = eng.SessionManager.SelectUnusedCircuit(nodes)
nodes = eng.SessionManager.SelectUnusedCircuit()
for i := range nodes {
if nodes[i] == nil {
e = fmt.Errorf("failed to find nodes %d", i)
@@ -60,20 +60,14 @@ func (eng *Engine) BuyNewSessions(amount lnwire.MilliSatoshi,
case success = <-confirmChans[0]:
if success {
pendingConfirms--
} else {
}
case success = <-confirmChans[1]:
if success {
pendingConfirms--
} else {
}
case success = <-confirmChans[2]:
if success {
pendingConfirms--
} else {
}
case success = <-confirmChans[3]:
if success {
@@ -82,22 +76,22 @@ func (eng *Engine) BuyNewSessions(amount lnwire.MilliSatoshi,
case success = <-confirmChans[4]:
if success {
pendingConfirms--
} else {
}
}
}
o := onion.SendKeys(conf, s, returnSession, nodes[:], eng.KeySet)
eng.SendOnion(nodes[0].AddrPort, o, func(id nonce.ID, b slice.Bytes) {
eng.SessionManager.Lock()
defer eng.SessionManager.Unlock()
var sessions [5]*traffic.Session
for i := range nodes {
log.D.F("confirming and storing session at hop %d %x for %s with"+
log.D.F("confirming and storing session at hop %d %s for %s with"+
" %v initial"+
" balance", i, s[i].ID, nodes[i].AddrPort.String(), amount)
sessions[i] = traffic.NewSession(s[i].ID, nodes[i], amount,
s[i].Header, s[i].Payload, byte(i))
eng.SessionManager.AddSession(sessions[i])
eng.SessionManager.DeletePendingPayment(s[i].PreimageHash())
eng.SessionManager.Add(sessions[i])
eng.SessionManager.PendingPayments.Delete(s[i].PreimageHash())
}
hook()
})

View File

@@ -2,7 +2,7 @@ package traffic
import (
"git-indra.lan/indra-labs/lnd/lnd/lnwire"
"git-indra.lan/indra-labs/indra/pkg/crypto/nonce"
"git-indra.lan/indra-labs/indra/pkg/crypto/sha256"
"git-indra.lan/indra-labs/indra/pkg/onion/layers/session"
@@ -20,7 +20,7 @@ type PaymentChan chan *Payment
// Send a payment on the PaymentChan.
func (pc PaymentChan) Send(amount lnwire.MilliSatoshi,
s *session.Layer) (confirmChan chan bool) {
confirmChan = make(chan bool)
pc <- &Payment{
ID: s.ID,
@@ -77,32 +77,33 @@ func (p PendingPayments) FindPreimage(pi sha256.Hash) (pp *Payment) {
func (sm *SessionManager) AddPendingPayment(
np *Payment) {
sm.Lock()
defer sm.Unlock()
log.D.F("%s adding pending payment %x for %v", sm.nodes[0].AddrPort.String(), np.ID,
log.D.F("%s adding pending payment %s for %v",
sm.nodes[0].AddrPort.String(), np.ID,
np.Amount)
sm.pendingPayments = sm.pendingPayments.Add(np)
sm.PendingPayments = sm.PendingPayments.Add(np)
}
func (sm *SessionManager) DeletePendingPayment(
preimage sha256.Hash) {
sm.Lock()
defer sm.Unlock()
sm.pendingPayments = sm.pendingPayments.Delete(preimage)
sm.PendingPayments = sm.PendingPayments.Delete(preimage)
}
func (sm *SessionManager) FindPendingPayment(
id nonce.ID) (pp *Payment) {
sm.Lock()
defer sm.Unlock()
return sm.pendingPayments.Find(id)
return sm.PendingPayments.Find(id)
}
func (sm *SessionManager) FindPendingPreimage(
pi sha256.Hash) (pp *Payment) {
log.T.F("searching preimage %x", pi)
sm.Lock()
defer sm.Unlock()
return sm.pendingPayments.FindPreimage(pi)
return sm.PendingPayments.FindPreimage(pi)
}

View File

@@ -6,7 +6,7 @@ import (
func (sm *SessionManager) SelectHops(hops []byte,
alreadyHave Sessions) (so Sessions) {
sm.Lock()
defer sm.Unlock()
ws := make(Sessions, 0)
@@ -64,42 +64,3 @@ out:
}
return
}
// SelectUnusedCircuit accepts an array of 5 Node entries where all or some are
// empty and picks nodes for the remainder that do not have a hop at that
// position.
func (sm *SessionManager) SelectUnusedCircuit(nodes [5]*Node) (c [5]*Node) {
sm.Lock()
defer sm.Unlock()
c = nodes
// Create a shuffled slice of Nodes to randomise the selection process.
nodeList := make([]*Node, len(sm.nodes)-1)
copy(nodeList, sm.nodes[1:])
cryptorand.Shuffle(len(nodeList), func(i, j int) {
nodeList[i], nodeList[j] = nodeList[j], nodeList[i]
})
for i := range c {
// We are only adding Node entries for spots that are not already
// filled.
if c[i] == nil {
for j := range nodeList {
if nodeList[j] == nil {
continue
}
if sc, ok := sm.SessionCache[nodeList[j].ID]; ok {
if sc[i] == nil {
c[i] = nodeList[j]
// nil the entry so it isn't selected again
nodeList[j] = nil
break
}
}
c[i] = nodeList[j]
// nil the entry so it isn't selected again
nodeList[j] = nil
break
}
}
}
return
}

View File

@@ -0,0 +1,37 @@
package traffic
// SelectUnusedCircuit accepts an array of 5 Node entries where all or some are
// empty and picks nodes for the remainder that do not have a hop at that
// position.
func (sm *SessionManager) SelectUnusedCircuit() (c [5]*Node) {
sm.Lock()
defer sm.Unlock()
// Create a shuffled slice of Nodes to randomise the selection process.
nodeList := make([]*Node, len(sm.nodes)-1)
copy(nodeList, sm.nodes[1:])
for i := range nodeList {
if _, ok := sm.SessionCache[nodeList[i].ID]; !ok {
log.T.F("adding session cache entry for node %s", nodeList[i].ID)
sm.SessionCache[nodeList[i].ID] = &Circuit{}
}
}
var counter int
out:
for counter < 5 {
for i := range sm.SessionCache {
if counter == 5 {
break out
}
if sm.SessionCache[i][counter] == nil {
for j := range nodeList {
if nodeList[j].ID == i {
c[counter] = nodeList[j]
counter++
break
}
}
}
}
}
return
}

View File

@@ -1,6 +1,8 @@
package traffic
import (
"encoding/hex"
"git-indra.lan/indra-labs/lnd/lnd/lnwire"
"git-indra.lan/indra-labs/indra/pkg/crypto/key/prv"
@@ -94,5 +96,18 @@ func (s *Session) DecSats(sats lnwire.MilliSatoshi,
// A Circuit is the generic fixed length path used for most messages.
type Circuit [5]*Session
func (c Circuit) String() (o string) {
o += "[ "
for i := range c {
if c[i] == nil {
o += " "
} else {
o += hex.EncodeToString(c[i].ID[:]) + " "
}
}
o += "]"
return
}
// Sessions are arbitrary length lists of sessions.
type Sessions []*Session

View File

@@ -24,7 +24,7 @@ func (sm *SessionManager) UpdateSessionCache() {
}
func (sc SessionCache) Add(s *Session) SessionCache {
log.I.Ln("adding session", s.AddrPort.String(), s.Hop)
log.T.F("adding session %s %s %d", s.ID, s.AddrPort.String(), s.Hop)
var sce *Circuit
var exists bool
if sce, exists = sc[s.Node.ID]; !exists {

View File

@@ -2,9 +2,9 @@ package traffic
import (
"sync"
"git-indra.lan/indra-labs/lnd/lnd/lnwire"
"git-indra.lan/indra-labs/indra/pkg/crypto/key/prv"
"git-indra.lan/indra-labs/indra/pkg/crypto/key/pub"
"git-indra.lan/indra-labs/indra/pkg/crypto/nonce"
@@ -24,7 +24,7 @@ import (
type SessionManager struct {
nodes []*Node
pendingPayments PendingPayments
PendingPayments PendingPayments
Sessions
SessionCache
sync.Mutex
@@ -40,7 +40,7 @@ func NewSessionManager() *SessionManager {
// payments, making the engine forget about payments it received.
func (sm *SessionManager) ClearPendingPayments() {
log.D.Ln("clearing pending payments")
sm.pendingPayments = sm.pendingPayments[:0]
sm.PendingPayments = sm.PendingPayments[:0]
}
// ClearSessions is used only for debugging, removing all but the first session,
@@ -52,7 +52,7 @@ func (sm *SessionManager) ClearSessions() {
func (sm *SessionManager) IncSession(id nonce.ID, sats lnwire.MilliSatoshi,
sender bool, typ string) {
sess := sm.FindSession(id)
if sess != nil {
sm.Lock()
@@ -62,7 +62,7 @@ func (sm *SessionManager) IncSession(id nonce.ID, sats lnwire.MilliSatoshi,
}
func (sm *SessionManager) DecSession(id nonce.ID, sats lnwire.MilliSatoshi,
sender bool, typ string) bool {
sess := sm.FindSession(id)
if sess != nil {
sm.Lock()
@@ -74,7 +74,7 @@ func (sm *SessionManager) DecSession(id nonce.ID, sats lnwire.MilliSatoshi,
func (sm *SessionManager) GetNodeCircuit(id nonce.ID) (sce *Circuit,
exists bool) {
sm.Lock()
defer sm.Unlock()
sce, exists = sm.SessionCache[id]
@@ -181,7 +181,7 @@ func (sm *SessionManager) IterateSessions(fn func(s *Session) bool) {
// Do not call SessionManager methods within this function.
func (sm *SessionManager) IterateSessionCache(fn func(n *Node,
c *Circuit) bool) {
sm.Lock()
defer sm.Unlock()
out: