introquery ready to use
This commit is contained in:
@@ -28,8 +28,8 @@ func init() {
|
||||
pf.StringSliceVarP(&engineRPC, "relay-control", "r",
|
||||
[]string{"127.0.0.1:8339", "::1:8339"},
|
||||
"address/ports for IPv4 and v6 listeners")
|
||||
viper.BindPFlag("engineP2P-relay", seedCmd.PersistentFlags().Lookup("engineP2P-relay"))
|
||||
viper.BindPFlag("relay-control", seedCmd.PersistentFlags().Lookup(
|
||||
viper.BindPFlag("engineP2P-relay", seedCommand.PersistentFlags().Lookup("engineP2P-relay"))
|
||||
viper.BindPFlag("relay-control", seedCommand.PersistentFlags().Lookup(
|
||||
"relay-control"))
|
||||
rootCmd.AddCommand(relayCmd)
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@ package main
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(seedCmd)
|
||||
rootCmd.AddCommand(seedCommand)
|
||||
}
|
||||
|
||||
var seedCmd = &cobra.Command{
|
||||
var seedCommand = &cobra.Command{
|
||||
Use: "seed",
|
||||
Short: "run and manage your seed node",
|
||||
Long: `run and manage your seed node`,
|
||||
|
||||
@@ -54,7 +54,7 @@ func (x *Layer) Encode(b slice.Bytes, c *slice.Cursor) {
|
||||
ID(x.ID).
|
||||
Pubkey(x.Key).
|
||||
AddrPort(x.AddrPort).
|
||||
Signature(x.Bytes).
|
||||
Signature(x.Sig).
|
||||
Hash(x.Ciphers[0]).Hash(x.Ciphers[1]).Hash(x.Ciphers[2]).
|
||||
IV(x.Nonces[0]).IV(x.Nonces[1]).IV(x.Nonces[2])
|
||||
}
|
||||
@@ -67,7 +67,7 @@ func (x *Layer) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
ReadID(&x.ID).
|
||||
ReadPubkey(&x.Layer.Key).
|
||||
ReadAddrPort(&x.Layer.AddrPort).
|
||||
ReadSignature(&x.Layer.Bytes).
|
||||
ReadSignature(&x.Layer.Sig).
|
||||
ReadHash(&x.Ciphers[0]).ReadHash(&x.Ciphers[1]).ReadHash(&x.Ciphers[2]).
|
||||
ReadIV(&x.Nonces[0]).ReadIV(&x.Nonces[1]).ReadIV(&x.Nonces[2])
|
||||
return
|
||||
|
||||
@@ -34,7 +34,7 @@ var (
|
||||
type Layer struct {
|
||||
Key *pub.Key
|
||||
AddrPort *netip.AddrPort
|
||||
Bytes sig.Bytes
|
||||
Sig sig.Bytes
|
||||
}
|
||||
|
||||
func New(key *prv.Key, ap *netip.AddrPort) (in *Layer) {
|
||||
@@ -50,7 +50,7 @@ func New(key *prv.Key, ap *netip.AddrPort) (in *Layer) {
|
||||
in = &Layer{
|
||||
Key: pk,
|
||||
AddrPort: ap,
|
||||
Bytes: sign,
|
||||
Sig: sign,
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -59,7 +59,7 @@ func (im *Layer) Validate() bool {
|
||||
bap, _ := im.AddrPort.MarshalBinary()
|
||||
pkb := im.Key.ToBytes()
|
||||
hash := sha256.Single(append(pkb[:], bap...))
|
||||
key, e := im.Bytes.Recover(hash)
|
||||
key, e := im.Sig.Recover(hash)
|
||||
if check(e) {
|
||||
return false
|
||||
}
|
||||
@@ -78,7 +78,7 @@ func (im *Layer) Encode(b slice.Bytes, c *slice.Cursor) {
|
||||
Magic(Magic).
|
||||
Pubkey(im.Key).
|
||||
AddrPort(im.AddrPort).
|
||||
Signature(im.Bytes)
|
||||
Signature(im.Sig)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -86,6 +86,6 @@ func (im *Layer) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
splice.Splice(b, c).
|
||||
ReadPubkey(&im.Key).
|
||||
ReadAddrPort(&im.AddrPort).
|
||||
ReadSignature(&im.Bytes)
|
||||
ReadSignature(&im.Sig)
|
||||
return
|
||||
}
|
||||
|
||||
69
pkg/messages/introquery/introquery.go
Normal file
69
pkg/messages/introquery/introquery.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package introquery
|
||||
|
||||
import (
|
||||
"git-indra.lan/indra-labs/indra"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/key/pub"
|
||||
"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/messages/magicbytes"
|
||||
log2 "git-indra.lan/indra-labs/indra/pkg/proc/log"
|
||||
"git-indra.lan/indra-labs/indra/pkg/splice"
|
||||
"git-indra.lan/indra-labs/indra/pkg/types"
|
||||
"git-indra.lan/indra-labs/indra/pkg/util/slice"
|
||||
)
|
||||
|
||||
const (
|
||||
MagicString = "iq"
|
||||
Len = magicbytes.Len + pub.KeyLen +
|
||||
3*sha256.Len + nonce.IVLen*3
|
||||
)
|
||||
|
||||
var (
|
||||
log = log2.GetLogger(indra.PathBase)
|
||||
check = log.E.Chk
|
||||
Magic = slice.Bytes(MagicString)
|
||||
_ types.Onion = &Layer{}
|
||||
)
|
||||
|
||||
// Layer introquery is a request for the introduction point for a specified
|
||||
// public key of a hidden service. The reply is wrapped in a routing header
|
||||
// containing the full signed introduction message intro.Layer so the address is
|
||||
// verifiable.
|
||||
type Layer struct {
|
||||
*pub.Key
|
||||
// Ciphers is a set of 3 symmetric ciphers that are to be used in their
|
||||
// given order over the reply message from the service.
|
||||
Ciphers [3]sha256.Hash
|
||||
// Nonces are the nonces to use with the cipher when creating the
|
||||
// encryption for the reply message.
|
||||
Nonces [3]nonce.IV
|
||||
}
|
||||
|
||||
// func (x *Layer) String() string {
|
||||
// return spew.Sdump(x.Port, x.Ciphers, x.Nonces, x.Bytes.ToBytes())
|
||||
// }
|
||||
|
||||
func (x *Layer) Insert(o types.Onion) {}
|
||||
func (x *Layer) Len() int {
|
||||
return Len
|
||||
}
|
||||
|
||||
func (x *Layer) Encode(b slice.Bytes, c *slice.Cursor) {
|
||||
splice.Splice(b, c).
|
||||
Magic(Magic).
|
||||
Pubkey(x.Key).
|
||||
Hash(x.Ciphers[0]).Hash(x.Ciphers[1]).Hash(x.Ciphers[2]).
|
||||
IV(x.Nonces[0]).IV(x.Nonces[1]).IV(x.Nonces[2])
|
||||
}
|
||||
|
||||
func (x *Layer) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
if len(b[*c:]) < Len-magicbytes.Len {
|
||||
return magicbytes.TooShort(len(b[*c:]), Len-magicbytes.Len,
|
||||
string(Magic))
|
||||
}
|
||||
splice.Splice(b, c).
|
||||
ReadPubkey(&x.Key).
|
||||
ReadHash(&x.Ciphers[0]).ReadHash(&x.Ciphers[1]).ReadHash(&x.Ciphers[2]).
|
||||
ReadIV(&x.Nonces[0]).ReadIV(&x.Nonces[1]).ReadIV(&x.Nonces[2])
|
||||
return
|
||||
}
|
||||
@@ -252,7 +252,7 @@ out:
|
||||
}
|
||||
|
||||
func TestClient_HiddenService(t *testing.T) {
|
||||
log2.SetLogLevel(log2.Trace)
|
||||
log2.SetLogLevel(log2.Info)
|
||||
var clients []*Engine
|
||||
var e error
|
||||
const returns = 2
|
||||
@@ -284,7 +284,9 @@ func TestClient_HiddenService(t *testing.T) {
|
||||
log.D.F("%d %s %v", i, j, clients[0].SessionCache[j])
|
||||
}
|
||||
}
|
||||
for i := 0; i < 25; i++ {
|
||||
log2.SetLogLevel(log2.Debug)
|
||||
const nHiddenServices = 25
|
||||
for i := 0; i < nHiddenServices; i++ {
|
||||
var identPrv *prv.Key
|
||||
if identPrv, e = prv.GenerateKey(); check(e) {
|
||||
t.Error(e)
|
||||
@@ -292,64 +294,19 @@ func TestClient_HiddenService(t *testing.T) {
|
||||
}
|
||||
id := nonce.NewID()
|
||||
il := intro.New(identPrv, clients[0].GetLocalNodeAddress())
|
||||
clients[0].SendIntro(id, clients[0].Sessions[i+returns],
|
||||
il, func(id nonce.ID, b slice.Bytes) {
|
||||
log.I.Ln("success")
|
||||
})
|
||||
clients[0].SendIntro(id, clients[0].Sessions[i+returns], il)
|
||||
}
|
||||
time.Sleep(time.Second / 2)
|
||||
for _, v := range clients {
|
||||
v.Shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
func TestClient_HiddenServiceBroadcast(t *testing.T) {
|
||||
log2.SetLogLevel(log2.Info)
|
||||
var clients []*Engine
|
||||
var e error
|
||||
const returns = 2
|
||||
if clients, e = CreateNMockCircuits(false, 10, returns); check(e) {
|
||||
t.Error(e)
|
||||
t.FailNow()
|
||||
}
|
||||
// Start up the clients.
|
||||
for _, v := range clients {
|
||||
go v.Start()
|
||||
}
|
||||
// Fund the client for all hops on all nodes.
|
||||
var wg sync.WaitGroup
|
||||
var counter atomic.Int32
|
||||
for i := 0; i < 25; i++ {
|
||||
log.D.Ln("buying sessions", i)
|
||||
wg.Add(1)
|
||||
counter.Inc()
|
||||
e = clients[0].BuyNewSessions(1000000, func() {
|
||||
wg.Done()
|
||||
counter.Dec()
|
||||
})
|
||||
if check(e) {
|
||||
wg.Done()
|
||||
counter.Dec()
|
||||
time.Sleep(time.Second)
|
||||
for i, v := range clients {
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
wg.Wait()
|
||||
for j := range clients[0].SessionCache {
|
||||
log.D.F("%d %s %v", i, j, clients[0].SessionCache[j])
|
||||
if len(v.Introductions.KnownIntros) != nHiddenServices {
|
||||
log.E.Ln("did not find expected", nHiddenServices, "got",
|
||||
len(v.Introductions.KnownIntros))
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
var identPrv *prv.Key
|
||||
if identPrv, e = prv.GenerateKey(); check(e) {
|
||||
t.Error(e)
|
||||
t.FailNow()
|
||||
}
|
||||
log2.SetLogLevel(log2.Trace)
|
||||
// identPub := pub.Derive(identPrv)
|
||||
id := nonce.NewID()
|
||||
il := intro.New(identPrv, clients[0].GetLocalNodeAddress())
|
||||
clients[0].SendIntro(id, clients[0].Sessions[returns],
|
||||
il, func(id nonce.ID, b slice.Bytes) {
|
||||
log.I.Ln("success")
|
||||
})
|
||||
time.Sleep(time.Second * 60)
|
||||
for _, v := range clients {
|
||||
v.Shutdown()
|
||||
}
|
||||
@@ -393,19 +350,29 @@ func TestClient_HiddenServiceRequest(t *testing.T) {
|
||||
t.Error(e)
|
||||
t.FailNow()
|
||||
}
|
||||
log2.SetLogLevel(log2.Trace)
|
||||
log2.SetLogLevel(log2.Debug)
|
||||
// identPub := pub.Derive(identPrv)
|
||||
id := nonce.NewID()
|
||||
il := intro.New(identPrv, clients[0].GetLocalNodeAddress())
|
||||
clients[0].SendIntro(id, clients[0].Sessions[returns],
|
||||
il, func(id nonce.ID, b slice.Bytes) {
|
||||
log.I.Ln("success")
|
||||
})
|
||||
il)
|
||||
// In this test environment generally every node has the intro after 1
|
||||
// second.
|
||||
time.Sleep(time.Second)
|
||||
for _, v := range clients {
|
||||
// if i == 0 {
|
||||
// continue
|
||||
// }
|
||||
if len(v.Introductions.KnownIntros) != 1 {
|
||||
log.E.Ln("did not find expected", 1, "got",
|
||||
len(v.Introductions.KnownIntros))
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
// Now to test nodes requesting the address (even though they already know
|
||||
// it).
|
||||
|
||||
time.Sleep(time.Second)
|
||||
for _, v := range clients {
|
||||
v.Shutdown()
|
||||
}
|
||||
|
||||
@@ -31,7 +31,8 @@ func (p handlemessages) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
|
||||
func main() {
|
||||
typesList := []string{"balance", "confirm", "crypt", "delay", "dxresponse",
|
||||
"exit", "forward", "getbalance", "hiddenservice", "intro", "reverse",
|
||||
"exit", "forward", "getbalance", "hiddenservice", "intro", "introquery",
|
||||
"reverse",
|
||||
"response", "session"}
|
||||
sort.Strings(typesList)
|
||||
tpl := `package relay
|
||||
@@ -50,6 +51,7 @@ import (
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/forward"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/getbalance"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/hiddenservice"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/introquery"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/intro"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/magicbytes"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/response"
|
||||
@@ -101,6 +103,7 @@ func Peel(b slice.Bytes, c *slice.Cursor) (on types.Onion, e error) {
|
||||
{"forward", true},
|
||||
{"getbalance", true},
|
||||
{"hiddenservice", true},
|
||||
{"introquery", true},
|
||||
{"intro", false},
|
||||
{"reverse", false},
|
||||
{"response", true},
|
||||
@@ -121,6 +124,7 @@ import (
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/forward"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/getbalance"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/hiddenservice"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/introquery"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/intro"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/response"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/reverse"
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/getbalance"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/hiddenservice"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/intro"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/introquery"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/response"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/reverse"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/session"
|
||||
@@ -83,6 +84,13 @@ func (eng *Engine) handleMessage(b slice.Bytes, prev types.Onion) {
|
||||
case *intro.Layer:
|
||||
log.T.C(recLog(on, b, eng))
|
||||
eng.intro(on, b, c, prev)
|
||||
case *introquery.Layer:
|
||||
if prev == nil {
|
||||
log.E.Ln(reflect.TypeOf(on), "requests from outside? absurd!")
|
||||
return
|
||||
}
|
||||
log.T.C(recLog(on, b, eng))
|
||||
eng.introquery(on, b, c, prev)
|
||||
case *response.Layer:
|
||||
if prev == nil {
|
||||
log.E.Ln(reflect.TypeOf(on), "requests from outside? absurd!")
|
||||
|
||||
@@ -44,5 +44,5 @@ func (eng *Engine) hiddenservice(hs *hiddenservice.Layer, b slice.Bytes,
|
||||
hs.Layer.Key.ToBase32())
|
||||
eng.Introductions.AddIntro(hs.Layer.Key, b[*c:])
|
||||
log.I.Ln("stored new introduction, starting broadcast")
|
||||
go eng.introductionBroadcaster(&hs.Layer)
|
||||
go eng.gossipIntro(&hs.Layer)
|
||||
}
|
||||
|
||||
@@ -3,11 +3,16 @@ package relay
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"git-indra.lan/indra-labs/lnd/lnd/lnwire"
|
||||
"github.com/cybriq/qu"
|
||||
|
||||
"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/key/signer"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/nonce"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/crypt"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/intro"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/introquery"
|
||||
"git-indra.lan/indra-labs/indra/pkg/types"
|
||||
"git-indra.lan/indra-labs/indra/pkg/util/cryptorand"
|
||||
"git-indra.lan/indra-labs/indra/pkg/util/slice"
|
||||
@@ -15,8 +20,6 @@ import (
|
||||
|
||||
type Intros map[pub.Bytes]slice.Bytes
|
||||
|
||||
type NotifiedIntroducers map[pub.Bytes][]nonce.ID
|
||||
|
||||
type KnownIntros map[pub.Bytes]*intro.Layer
|
||||
|
||||
// Introductions is a map of existing known hidden service keys and the
|
||||
@@ -29,14 +32,12 @@ type KnownIntros map[pub.Bytes]*intro.Layer
|
||||
type Introductions struct {
|
||||
sync.Mutex
|
||||
Intros
|
||||
NotifiedIntroducers
|
||||
KnownIntros
|
||||
}
|
||||
|
||||
func NewIntroductions() *Introductions {
|
||||
return &Introductions{Intros: make(Intros),
|
||||
NotifiedIntroducers: make(NotifiedIntroducers),
|
||||
KnownIntros: make(KnownIntros)}
|
||||
KnownIntros: make(KnownIntros)}
|
||||
}
|
||||
|
||||
func (in *Introductions) Find(key pub.Bytes) (header slice.Bytes) {
|
||||
@@ -52,7 +53,6 @@ func (in *Introductions) Delete(key pub.Bytes) (header slice.Bytes) {
|
||||
in.Lock()
|
||||
var ok bool
|
||||
if header, ok = in.Intros[key]; ok {
|
||||
// If found, the header is not to be used again.
|
||||
delete(in.Intros, key)
|
||||
}
|
||||
in.Unlock()
|
||||
@@ -67,26 +67,11 @@ func (in *Introductions) AddIntro(pk *pub.Key, header slice.Bytes) {
|
||||
log.D.Ln("entry already exists for key %x", key)
|
||||
} else {
|
||||
in.Intros[key] = header
|
||||
in.NotifiedIntroducers[key] = []nonce.ID{}
|
||||
}
|
||||
in.Unlock()
|
||||
}
|
||||
|
||||
func (in *Introductions) AddNotified(nodeID nonce.ID, ident pub.Bytes) {
|
||||
in.Lock()
|
||||
var ok bool
|
||||
if _, ok = in.NotifiedIntroducers[ident]; ok {
|
||||
in.NotifiedIntroducers[ident] = append(in.NotifiedIntroducers[ident],
|
||||
nodeID)
|
||||
} else {
|
||||
in.NotifiedIntroducers[ident] = []nonce.ID{nodeID}
|
||||
}
|
||||
in.Unlock()
|
||||
}
|
||||
|
||||
func (eng *Engine) SendIntro(id nonce.ID, target *Session, intr *intro.Layer,
|
||||
hook func(id nonce.ID, b slice.Bytes)) {
|
||||
|
||||
func (eng *Engine) SendIntro(id nonce.ID, target *Session, intr *intro.Layer) {
|
||||
hops := []byte{0, 1, 2, 3, 4, 5}
|
||||
s := make(Sessions, len(hops))
|
||||
s[2] = target
|
||||
@@ -96,10 +81,12 @@ func (eng *Engine) SendIntro(id nonce.ID, target *Session, intr *intro.Layer,
|
||||
o := HiddenService(id, intr, se[len(se)-1], c, eng.KeySet)
|
||||
log.D.Ln("sending out intro onion")
|
||||
res := eng.PostAcctOnion(o)
|
||||
eng.SendWithOneHook(c[0].AddrPort, res, hook)
|
||||
eng.SendWithOneHook(c[0].AddrPort, res, func(id nonce.ID, b slice.Bytes) {
|
||||
log.I.Ln("received routing header request for %s", intr.Key.ToBase32())
|
||||
})
|
||||
}
|
||||
|
||||
func (eng *Engine) introductionBroadcaster(intr *intro.Layer) {
|
||||
func (eng *Engine) gossipIntro(intr *intro.Layer) {
|
||||
log.D.F("propagating hidden service introduction for %x", intr.Key.ToBytes())
|
||||
done := qu.T()
|
||||
msg := make(slice.Bytes, intro.Len)
|
||||
@@ -113,9 +100,9 @@ func (eng *Engine) introductionBroadcaster(intr *intro.Layer) {
|
||||
cryptorand.Shuffle(nPeers, func(i, j int) {
|
||||
peerIndices[i], peerIndices[j] = peerIndices[j], peerIndices[i]
|
||||
})
|
||||
// Since relays will also gossip this information, we will start a ticker
|
||||
// that sends out the hidden service introduction once a second until it
|
||||
// runs out of known relays to gossip to.
|
||||
// We broadcast the received introduction to two other randomly selected
|
||||
// nodes, which guarantees the entire network will see the intro at least
|
||||
// once.
|
||||
var cursor int
|
||||
for {
|
||||
select {
|
||||
@@ -141,11 +128,11 @@ func (eng *Engine) intro(intr *intro.Layer, b slice.Bytes,
|
||||
eng.Introductions.Lock()
|
||||
if intr.Validate() {
|
||||
if _, ok := eng.Introductions.KnownIntros[intr.Key.ToBytes()]; ok {
|
||||
log.T.Ln("received intro we already know about")
|
||||
eng.Introductions.Unlock()
|
||||
return
|
||||
}
|
||||
log.T.F("storing intro for %s", intr.Key.ToBase32())
|
||||
log.D.F("%s storing intro for %s", eng.GetLocalNodeAddress().String(),
|
||||
intr.Key.ToBase32())
|
||||
eng.Introductions.KnownIntros[intr.Key.ToBytes()] = intr
|
||||
log.D.F("%s sending out intro to %s at %s to all known peers",
|
||||
eng.GetLocalNodeAddress(), intr.Key.ToBase32(),
|
||||
@@ -171,3 +158,56 @@ func (eng *Engine) intro(intr *intro.Layer, b slice.Bytes,
|
||||
eng.Introductions.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func IntroQuery(hsk *pub.Key, client *Session, s Circuit,
|
||||
ks *signer.KeySet) Skins {
|
||||
|
||||
var prvs [3]*prv.Key
|
||||
for i := range prvs {
|
||||
prvs[i] = ks.Next()
|
||||
}
|
||||
n := GenNonces(6)
|
||||
var returnNonces [3]nonce.IV
|
||||
copy(returnNonces[:], n[3:])
|
||||
var pubs [3]*pub.Key
|
||||
pubs[0] = s[3].PayloadPub
|
||||
pubs[1] = s[4].PayloadPub
|
||||
pubs[2] = client.PayloadPub
|
||||
return Skins{}.
|
||||
ReverseCrypt(s[0], ks.Next(), n[0], 3).
|
||||
ReverseCrypt(s[1], ks.Next(), n[1], 2).
|
||||
ReverseCrypt(s[2], ks.Next(), n[2], 1).
|
||||
IntroQuery(hsk, prvs, pubs, returnNonces).
|
||||
ReverseCrypt(s[3], prvs[0], n[3], 3).
|
||||
ReverseCrypt(s[4], prvs[1], n[4], 2).
|
||||
ReverseCrypt(client, prvs[2], n[5], 1)
|
||||
}
|
||||
|
||||
func (eng *Engine) introquery(iq *introquery.Layer, b slice.Bytes,
|
||||
c *slice.Cursor, prev types.Onion) {
|
||||
|
||||
eng.Introductions.Lock()
|
||||
var ok bool
|
||||
var il *intro.Layer
|
||||
if il, ok = eng.Introductions.KnownIntros[iq.Key.ToBytes()]; !ok {
|
||||
// if the reply is zeroes the querant knows it needs to retry at a
|
||||
// different relay
|
||||
il = &intro.Layer{}
|
||||
}
|
||||
eng.Introductions.Unlock()
|
||||
header := b[*c:c.Inc(crypt.ReverseHeaderLen)]
|
||||
rb := FormatReply(header,
|
||||
Encode(il), iq.Ciphers, iq.Nonces)
|
||||
switch on1 := prev.(type) {
|
||||
case *crypt.Layer:
|
||||
sess := eng.FindSessionByHeader(on1.ToPriv)
|
||||
if sess != nil {
|
||||
in := sess.RelayRate *
|
||||
lnwire.MilliSatoshi(len(b)) / 2 / 1024 / 1024
|
||||
out := sess.RelayRate *
|
||||
lnwire.MilliSatoshi(len(rb)) / 2 / 1024 / 1024
|
||||
eng.DecSession(sess.ID, in+out, false, "introquery")
|
||||
}
|
||||
}
|
||||
eng.handleMessage(rb, iq)
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/getbalance"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/hiddenservice"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/intro"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/introquery"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/magicbytes"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/response"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/reverse"
|
||||
@@ -75,6 +76,11 @@ func Peel(b slice.Bytes, c *slice.Cursor) (on types.Onion, e error) {
|
||||
if e = on.Decode(b, c); check(e) {
|
||||
return
|
||||
}
|
||||
case introquery.MagicString:
|
||||
on = &introquery.Layer{}
|
||||
if e = on.Decode(b, c); check(e) {
|
||||
return
|
||||
}
|
||||
case response.MagicString:
|
||||
on = &response.Layer{}
|
||||
if e = on.Decode(b, c); check(e) {
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/getbalance"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/hiddenservice"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/intro"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/introquery"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/noop"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/response"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/reverse"
|
||||
@@ -124,6 +125,16 @@ func (o Skins) HiddenService(id nonce.ID, intr *intro.Layer, prvs [3]*prv.Key,
|
||||
})
|
||||
}
|
||||
|
||||
func (o Skins) IntroQuery(hsk *pub.Key, prvs [3]*prv.Key, pubs [3]*pub.Key,
|
||||
nonces [3]nonce.IV) Skins {
|
||||
|
||||
return append(o, &introquery.Layer{
|
||||
Key: hsk,
|
||||
Ciphers: GenCiphers(prvs, pubs),
|
||||
Nonces: nonces,
|
||||
})
|
||||
}
|
||||
|
||||
func (o Skins) Reverse(ip *netip.AddrPort) Skins {
|
||||
return append(o, &reverse.Layer{AddrPort: ip, Onion: nop})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user