fully working selectunusedcircuit.go and SendSessionKeys test
This commit is contained in:
16
README.md
16
README.md
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
37
pkg/traffic/selectunusedcircuit.go
Normal file
37
pkg/traffic/selectunusedcircuit.go
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user