Merge branch 'main' into ind-bootstrap
This commit is contained in:
@@ -2,6 +2,7 @@ package client
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/Indra-Labs/indra"
|
"github.com/Indra-Labs/indra"
|
||||||
"github.com/Indra-Labs/indra/pkg/ifc"
|
"github.com/Indra-Labs/indra/pkg/ifc"
|
||||||
@@ -41,6 +42,7 @@ type Client struct {
|
|||||||
*address.ReceiveCache
|
*address.ReceiveCache
|
||||||
Circuits
|
Circuits
|
||||||
Sessions
|
Sessions
|
||||||
|
sync.Mutex
|
||||||
qu.C
|
qu.C
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,101 +60,169 @@ func New(tpt ifc.Transport, hdrPrv *prv.Key, no *node.Node,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start a single thread of the Client.
|
||||||
func (c *Client) Start() {
|
func (c *Client) Start() {
|
||||||
out:
|
out:
|
||||||
for {
|
for {
|
||||||
select {
|
if c.runner() {
|
||||||
case <-c.C.Wait():
|
|
||||||
c.Cleanup()
|
|
||||||
break out
|
break out
|
||||||
case b := <-c.Node.Receive():
|
|
||||||
// process received message
|
|
||||||
var onion types.Onion
|
|
||||||
var e error
|
|
||||||
cursor := slice.NewCursor()
|
|
||||||
if onion, e = wire.PeelOnion(b, cursor); check(e) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
switch on := onion.(type) {
|
|
||||||
case *cipher.OnionSkin:
|
|
||||||
// This either is in a forward only SendKeys
|
|
||||||
// message or we are the buyer and these are our
|
|
||||||
// session keys.
|
|
||||||
break
|
|
||||||
|
|
||||||
case *confirmation.OnionSkin:
|
|
||||||
// This will be an 8 byte nonce that confirms a
|
|
||||||
// message passed, ping and cipher onions return
|
|
||||||
// these, as they are pure forward messages that
|
|
||||||
// send a message one way and the confirmation
|
|
||||||
// is the acknowledgement.
|
|
||||||
break
|
|
||||||
|
|
||||||
case *delay.OnionSkin:
|
|
||||||
|
|
||||||
break
|
|
||||||
|
|
||||||
case *exit.OnionSkin:
|
|
||||||
// payload is forwarded to a local port and the
|
|
||||||
// response is forwarded back with a reply
|
|
||||||
// header.
|
|
||||||
break
|
|
||||||
|
|
||||||
case *forward.OnionSkin:
|
|
||||||
// forward the whole buffer received onwards.
|
|
||||||
// Usually there will be an OnionSkin under this
|
|
||||||
// which will be unwrapped by the receiver.
|
|
||||||
if on.AddrPort.String() == c.Node.AddrPort.String() {
|
|
||||||
// it is for us, we want to unwrap the
|
|
||||||
// next part.
|
|
||||||
} else {
|
|
||||||
// we need to forward this message onion.
|
|
||||||
}
|
|
||||||
break
|
|
||||||
|
|
||||||
case *layer.OnionSkin:
|
|
||||||
// this is probably an encrypted layer for us.
|
|
||||||
break
|
|
||||||
|
|
||||||
case *noop.OnionSkin:
|
|
||||||
// this won't happen normally
|
|
||||||
break
|
|
||||||
|
|
||||||
case *purchase.OnionSkin:
|
|
||||||
// Purchase requires a return of arbitrary data.
|
|
||||||
break
|
|
||||||
|
|
||||||
case *reply.OnionSkin:
|
|
||||||
// Reply means another OnionSkin is coming and
|
|
||||||
// the payload encryption uses the Payload key.
|
|
||||||
break
|
|
||||||
|
|
||||||
case *response.OnionSkin:
|
|
||||||
// Response is a payload from an exit message.
|
|
||||||
break
|
|
||||||
|
|
||||||
case *session.OnionSkin:
|
|
||||||
// Session is returned from a Purchase message
|
|
||||||
// in the reply layers.
|
|
||||||
//
|
|
||||||
// Session has a nonce.ID that is given in the
|
|
||||||
// last layer of a LN sphinx Bolt 4 onion routed
|
|
||||||
// payment path that will cause the seller to
|
|
||||||
// activate the accounting onion the two keys it
|
|
||||||
// sent back with the nonce.
|
|
||||||
break
|
|
||||||
|
|
||||||
case *token.OnionSkin:
|
|
||||||
// not really sure if we are using these.
|
|
||||||
break
|
|
||||||
|
|
||||||
default:
|
|
||||||
log.I.S("unrecognised packet", b)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) runner() (out bool) {
|
||||||
|
select {
|
||||||
|
case <-c.C.Wait():
|
||||||
|
c.Cleanup()
|
||||||
|
out = true
|
||||||
|
break
|
||||||
|
case b := <-c.Node.Receive():
|
||||||
|
// process received message
|
||||||
|
var onion types.Onion
|
||||||
|
var e error
|
||||||
|
cursor := slice.NewCursor()
|
||||||
|
if onion, e = wire.PeelOnion(b, cursor); check(e) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
switch on := onion.(type) {
|
||||||
|
case *cipher.OnionSkin:
|
||||||
|
c.cipher(on, b)
|
||||||
|
break
|
||||||
|
|
||||||
|
case *confirmation.OnionSkin:
|
||||||
|
c.confirmation(on, b)
|
||||||
|
break
|
||||||
|
|
||||||
|
case *delay.OnionSkin:
|
||||||
|
c.delay(on, b)
|
||||||
|
break
|
||||||
|
|
||||||
|
case *exit.OnionSkin:
|
||||||
|
c.exit(on, b)
|
||||||
|
break
|
||||||
|
|
||||||
|
case *forward.OnionSkin:
|
||||||
|
c.forward(on, b)
|
||||||
|
break
|
||||||
|
|
||||||
|
case *layer.OnionSkin:
|
||||||
|
c.layer(on, b)
|
||||||
|
break
|
||||||
|
|
||||||
|
case *noop.OnionSkin:
|
||||||
|
c.noop(on, b)
|
||||||
|
break
|
||||||
|
|
||||||
|
case *purchase.OnionSkin:
|
||||||
|
c.purchase(on, b)
|
||||||
|
break
|
||||||
|
|
||||||
|
case *reply.OnionSkin:
|
||||||
|
c.reply(on, b)
|
||||||
|
break
|
||||||
|
|
||||||
|
case *response.OnionSkin:
|
||||||
|
c.response(on, b)
|
||||||
|
break
|
||||||
|
|
||||||
|
case *session.OnionSkin:
|
||||||
|
c.session(on, b)
|
||||||
|
break
|
||||||
|
|
||||||
|
case *token.OnionSkin:
|
||||||
|
c.token(on, b)
|
||||||
|
break
|
||||||
|
|
||||||
|
default:
|
||||||
|
log.I.S("unrecognised packet", b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) cipher(on *cipher.OnionSkin, b slice.Bytes) {
|
||||||
|
// This either is in a forward only SendKeys message or we are the buyer
|
||||||
|
// and these are our session keys.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) confirmation(on *confirmation.OnionSkin, b slice.Bytes) {
|
||||||
|
// This will be an 8 byte nonce that confirms a message passed, ping and
|
||||||
|
// cipher onions return these, as they are pure forward messages that
|
||||||
|
// send a message one way and the confirmation is the acknowledgement.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) delay(on *delay.OnionSkin, b slice.Bytes) {
|
||||||
|
// this is a message to hold the message in the buffer until a time
|
||||||
|
// elapses. The accounting for the remainder of the message adds a
|
||||||
|
// factor to the effective byte consumption in accordance with the time
|
||||||
|
// to be stored.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) exit(on *exit.OnionSkin, b slice.Bytes) {
|
||||||
|
// payload is forwarded to a local port and the response is forwarded
|
||||||
|
// back with a reply header.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) forward(on *forward.OnionSkin, b slice.Bytes) {
|
||||||
|
// forward the whole buffer received onwards. Usually there will be an
|
||||||
|
// OnionSkin under this which will be unwrapped by the receiver.
|
||||||
|
if on.AddrPort.String() == c.Node.AddrPort.String() {
|
||||||
|
// it is for us, we want to unwrap the next
|
||||||
|
// part.
|
||||||
|
c.Node.Send(b)
|
||||||
|
} else {
|
||||||
|
// we need to forward this message onion.
|
||||||
|
c.Send(on.AddrPort, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) layer(on *layer.OnionSkin, b slice.Bytes) {
|
||||||
|
// this is probably an encrypted layer for us.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) noop(on *noop.OnionSkin, b slice.Bytes) {
|
||||||
|
// this won't happen normally
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) purchase(on *purchase.OnionSkin, b slice.Bytes) {
|
||||||
|
// Create a new Session.
|
||||||
|
s := &Session{}
|
||||||
|
c.Mutex.Lock()
|
||||||
|
c.Sessions = append(c.Sessions, s)
|
||||||
|
c.Mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) reply(on *reply.OnionSkin, b slice.Bytes) {
|
||||||
|
// Reply means another OnionSkin is coming and the payload encryption
|
||||||
|
// uses the Payload key.
|
||||||
|
if on.AddrPort.String() == c.Node.AddrPort.String() {
|
||||||
|
// it is for us, we want to unwrap the next part.
|
||||||
|
c.Node.Send(b)
|
||||||
|
} else {
|
||||||
|
// we need to forward this message onion.
|
||||||
|
c.Send(on.AddrPort, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) response(on *response.OnionSkin, b slice.Bytes) {
|
||||||
|
// Response is a payload from an exit message.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) session(s *session.OnionSkin, b slice.Bytes) {
|
||||||
|
// Session is returned from a Purchase message in the reply layers.
|
||||||
|
//
|
||||||
|
// Session has a nonce.ID that is given in the last layer of a LN sphinx
|
||||||
|
// Bolt 4 onion routed payment path that will cause the seller to
|
||||||
|
// activate the accounting onion the two keys it sent back with the
|
||||||
|
// nonce, so long as it has not yet expired.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) token(t *token.OnionSkin, b slice.Bytes) {
|
||||||
|
// not really sure if we are using these.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) Cleanup() {
|
func (c *Client) Cleanup() {
|
||||||
// Do cleanup stuff before shutdown.
|
// Do cleanup stuff before shutdown.
|
||||||
}
|
}
|
||||||
@@ -160,3 +230,18 @@ func (c *Client) Cleanup() {
|
|||||||
func (c *Client) Shutdown() {
|
func (c *Client) Shutdown() {
|
||||||
c.C.Q()
|
c.C.Q()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) Send(addr *netip.AddrPort, b slice.Bytes) {
|
||||||
|
// first search if we already have the node available with connection
|
||||||
|
// open.
|
||||||
|
as := addr.String()
|
||||||
|
for i := range c.Nodes {
|
||||||
|
if as == c.Nodes[i].Addr {
|
||||||
|
c.Nodes[i].Transport.Send(b)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we got to here none of the addresses matched, and we need to
|
||||||
|
// establish a new peer connection to them.
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/Indra-Labs/indra/pkg/key/address"
|
"github.com/Indra-Labs/indra/pkg/key/address"
|
||||||
"github.com/Indra-Labs/indra/pkg/key/signer"
|
"github.com/Indra-Labs/indra/pkg/key/signer"
|
||||||
"github.com/Indra-Labs/indra/pkg/node"
|
"github.com/Indra-Labs/indra/pkg/node"
|
||||||
@@ -15,6 +17,7 @@ type Session struct {
|
|||||||
*node.Node
|
*node.Node
|
||||||
Remaining uint64
|
Remaining uint64
|
||||||
HeaderKey, PayloadKey *address.SendEntry
|
HeaderKey, PayloadKey *address.SendEntry
|
||||||
|
Deadline time.Time
|
||||||
*signer.KeySet
|
*signer.KeySet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ var (
|
|||||||
// except when the netip.AddrPort is known via the packet sender address.
|
// except when the netip.AddrPort is known via the packet sender address.
|
||||||
type Node struct {
|
type Node struct {
|
||||||
nonce.ID
|
nonce.ID
|
||||||
|
Addr string
|
||||||
*netip.AddrPort
|
*netip.AddrPort
|
||||||
HeaderPub, PayloadPub *pub.Key
|
HeaderPub, PayloadPub *pub.Key
|
||||||
HeaderPriv, PayloadPriv *prv.Key
|
HeaderPriv, PayloadPriv *prv.Key
|
||||||
@@ -33,13 +34,14 @@ type Node struct {
|
|||||||
|
|
||||||
// New creates a new Node. netip.AddrPort is optional if the counterparty is not
|
// New creates a new Node. netip.AddrPort is optional if the counterparty is not
|
||||||
// in direct connection.
|
// in direct connection.
|
||||||
func New(ip *netip.AddrPort, hdr, pld *pub.Key, hdrPriv, pldPriv *prv.Key,
|
func New(addr *netip.AddrPort, hdr, pld *pub.Key, hdrPriv, pldPriv *prv.Key,
|
||||||
tpt ifc.Transport) (n *Node, id nonce.ID) {
|
tpt ifc.Transport) (n *Node, id nonce.ID) {
|
||||||
|
|
||||||
id = nonce.NewID()
|
id = nonce.NewID()
|
||||||
n = &Node{
|
n = &Node{
|
||||||
ID: id,
|
ID: id,
|
||||||
AddrPort: ip,
|
Addr: addr.String(),
|
||||||
|
AddrPort: addr,
|
||||||
Transport: tpt,
|
Transport: tpt,
|
||||||
HeaderPub: hdr,
|
HeaderPub: hdr,
|
||||||
PayloadPub: pld,
|
PayloadPub: pld,
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ var (
|
|||||||
// GitRef is the gitref, as in refs/heads/branchname.
|
// GitRef is the gitref, as in refs/heads/branchname.
|
||||||
GitRef = "refs/heads/main"
|
GitRef = "refs/heads/main"
|
||||||
// ParentGitCommit is the commit hash of the parent HEAD.
|
// ParentGitCommit is the commit hash of the parent HEAD.
|
||||||
ParentGitCommit = "493e661bd056e6c6d21eab841dddea39788d62aa"
|
ParentGitCommit = "1f73709fbafd7e43150a298f32d9f00520e7e47b"
|
||||||
// BuildTime stores the time when the current binary was built.
|
// BuildTime stores the time when the current binary was built.
|
||||||
BuildTime = "2022-12-28T10:03:58Z"
|
BuildTime = "2022-12-28T12:22:54Z"
|
||||||
// SemVer lists the (latest) git tag on the build.
|
// SemVer lists the (latest) git tag on the build.
|
||||||
SemVer = "v0.0.252"
|
SemVer = "v0.0.253"
|
||||||
// PathBase is the path base returned from runtime caller.
|
// PathBase is the path base returned from runtime caller.
|
||||||
PathBase = "/home/loki/src/github.com/Indra-Labs/indra/"
|
PathBase = "/home/loki/src/github.com/Indra-Labs/indra/"
|
||||||
// Major is the major number from the tag.
|
// Major is the major number from the tag.
|
||||||
@@ -22,7 +22,7 @@ var (
|
|||||||
// Minor is the minor number from the tag.
|
// Minor is the minor number from the tag.
|
||||||
Minor = 0
|
Minor = 0
|
||||||
// Patch is the patch version number from the tag.
|
// Patch is the patch version number from the tag.
|
||||||
Patch = 252
|
Patch = 253
|
||||||
)
|
)
|
||||||
|
|
||||||
// Version returns a pretty printed version information string.
|
// Version returns a pretty printed version information string.
|
||||||
|
|||||||
Reference in New Issue
Block a user