Completed pay/keysend test passing
This commit is contained in:
@@ -88,8 +88,8 @@ func (cl *Client) RegisterConfirmation(hook confirm.Hook,
|
|||||||
// FindCloaked searches the client identity key and the Sessions for a match. It
|
// FindCloaked searches the client identity key and the Sessions for a match. It
|
||||||
// returns the session as well, though not all users of this function will need
|
// returns the session as well, though not all users of this function will need
|
||||||
// this.
|
// this.
|
||||||
func (cl *Client) FindCloaked(clk cloak.PubKey) (hdr *prv.Key, pld *prv.Key,
|
func (cl *Client) FindCloaked(clk cloak.PubKey) (hdr *prv.Key,
|
||||||
sess *node.Session) {
|
pld *prv.Key, sess *node.Session) {
|
||||||
|
|
||||||
var b cloak.Blinder
|
var b cloak.Blinder
|
||||||
copy(b[:], clk[:cloak.BlindLen])
|
copy(b[:], clk[:cloak.BlindLen])
|
||||||
@@ -103,7 +103,7 @@ func (cl *Client) FindCloaked(clk cloak.PubKey) (hdr *prv.Key, pld *prv.Key,
|
|||||||
for i := range cl.Sessions {
|
for i := range cl.Sessions {
|
||||||
hash = cloak.Cloak(b, cl.Sessions[i].HeaderBytes)
|
hash = cloak.Cloak(b, cl.Sessions[i].HeaderBytes)
|
||||||
if hash == clk {
|
if hash == clk {
|
||||||
log.T.F("found in session %d", i)
|
log.T.F("found cloaked key in session %d", i)
|
||||||
hdr = cl.Sessions[i].HeaderPrv
|
hdr = cl.Sessions[i].HeaderPrv
|
||||||
pld = cl.Sessions[i].PayloadPrv
|
pld = cl.Sessions[i].PayloadPrv
|
||||||
sess = cl.Sessions[i]
|
sess = cl.Sessions[i]
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/cybriq/qu"
|
"github.com/cybriq/qu"
|
||||||
|
"github.com/indra-labs/indra/pkg/key/prv"
|
||||||
"github.com/indra-labs/indra/pkg/node"
|
"github.com/indra-labs/indra/pkg/node"
|
||||||
"github.com/indra-labs/indra/pkg/nonce"
|
"github.com/indra-labs/indra/pkg/nonce"
|
||||||
"github.com/indra-labs/indra/pkg/sha256"
|
"github.com/indra-labs/indra/pkg/sha256"
|
||||||
@@ -13,6 +14,7 @@ import (
|
|||||||
"github.com/indra-labs/indra/pkg/transport"
|
"github.com/indra-labs/indra/pkg/transport"
|
||||||
"github.com/indra-labs/indra/pkg/wire"
|
"github.com/indra-labs/indra/pkg/wire"
|
||||||
"github.com/indra-labs/indra/pkg/wire/confirm"
|
"github.com/indra-labs/indra/pkg/wire/confirm"
|
||||||
|
"github.com/indra-labs/indra/pkg/wire/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPing(t *testing.T) {
|
func TestPing(t *testing.T) {
|
||||||
@@ -139,7 +141,47 @@ func TestSendKeys(t *testing.T) {
|
|||||||
quit.Q()
|
quit.Q()
|
||||||
// t.Error("SendKeys got stuck")
|
// t.Error("SendKeys got stuck")
|
||||||
}()
|
}()
|
||||||
|
// Create a new payment and drop on the payment channel.
|
||||||
|
sess := session.New()
|
||||||
|
pmt := sess.ToPayment(1000000)
|
||||||
|
clients[0].PaymentChan <- pmt
|
||||||
|
// Send the keys.
|
||||||
|
var circuit node.Circuit
|
||||||
|
for i := range circuit {
|
||||||
|
circuit[i] = clients[0].Sessions[i+1]
|
||||||
|
}
|
||||||
|
var hdr, pld [5]*prv.Key
|
||||||
|
hdr[0], pld[0] = sess.Header, sess.Payload
|
||||||
|
sk := wire.SendKeys(pmt.ID, hdr, pld, clients[0].Node,
|
||||||
|
circuit, clients[0].KeySet)
|
||||||
|
clients[0].RegisterConfirmation(func(cf nonce.ID) {
|
||||||
|
log.T.S("received payment confirmation ID", cf)
|
||||||
|
pp := clients[0].PendingPayments.Find(cf)
|
||||||
|
log.T.F("\nexpected %x\nreceived %x\nfrom\nhdr: %x\npld: %x",
|
||||||
|
sess.PreimageHash(),
|
||||||
|
pp.Preimage,
|
||||||
|
sess.Header.ToBytes(),
|
||||||
|
sess.Payload.ToBytes(),
|
||||||
|
)
|
||||||
|
if pp.Preimage != sess.PreimageHash() {
|
||||||
|
t.Errorf("did not find expected preimage: got"+
|
||||||
|
" %x expected %x",
|
||||||
|
pp.Preimage, sess.PreimageHash())
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
_ = pp
|
||||||
|
// if pp == nil {
|
||||||
|
// t.Errorf("did not find expected confirmation ID: got"+
|
||||||
|
// " %x expected %x", cf, pmt.ID)
|
||||||
|
// t.FailNow()
|
||||||
|
// }
|
||||||
|
log.T.F("SendKeys confirmed %x", cf)
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
quit.Q()
|
||||||
|
}, pmt.ID)
|
||||||
|
o := sk.Assemble()
|
||||||
|
b := wire.EncodeOnion(o)
|
||||||
|
clients[0].Send(clients[0].Nodes[0].AddrPort, b)
|
||||||
<-quit.Wait()
|
<-quit.Wait()
|
||||||
for _, v := range clients {
|
for _, v := range clients {
|
||||||
v.Shutdown()
|
v.Shutdown()
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/indra-labs/indra/pkg/slice"
|
"github.com/indra-labs/indra/pkg/slice"
|
||||||
"github.com/indra-labs/indra/pkg/types"
|
"github.com/indra-labs/indra/pkg/types"
|
||||||
"github.com/indra-labs/indra/pkg/wire"
|
"github.com/indra-labs/indra/pkg/wire"
|
||||||
"github.com/indra-labs/indra/pkg/wire/cipher"
|
|
||||||
"github.com/indra-labs/indra/pkg/wire/confirm"
|
"github.com/indra-labs/indra/pkg/wire/confirm"
|
||||||
"github.com/indra-labs/indra/pkg/wire/delay"
|
"github.com/indra-labs/indra/pkg/wire/delay"
|
||||||
"github.com/indra-labs/indra/pkg/wire/exit"
|
"github.com/indra-labs/indra/pkg/wire/exit"
|
||||||
@@ -20,6 +19,7 @@ import (
|
|||||||
"github.com/indra-labs/indra/pkg/wire/noop"
|
"github.com/indra-labs/indra/pkg/wire/noop"
|
||||||
"github.com/indra-labs/indra/pkg/wire/response"
|
"github.com/indra-labs/indra/pkg/wire/response"
|
||||||
"github.com/indra-labs/indra/pkg/wire/reverse"
|
"github.com/indra-labs/indra/pkg/wire/reverse"
|
||||||
|
"github.com/indra-labs/indra/pkg/wire/session"
|
||||||
"github.com/indra-labs/indra/pkg/wire/token"
|
"github.com/indra-labs/indra/pkg/wire/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -51,9 +51,9 @@ func (cl *Client) runner() (out bool) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
switch on := onion.(type) {
|
switch on := onion.(type) {
|
||||||
case *cipher.OnionSkin:
|
case *session.OnionSkin:
|
||||||
recLog(on, b, cl)
|
recLog(on, b, cl)
|
||||||
cl.cipher(on, b, c)
|
cl.session(on, b, c)
|
||||||
case *confirm.OnionSkin:
|
case *confirm.OnionSkin:
|
||||||
recLog(on, b, cl)
|
recLog(on, b, cl)
|
||||||
cl.confirm(on, b, c)
|
cl.confirm(on, b, c)
|
||||||
@@ -84,11 +84,15 @@ func (cl *Client) runner() (out bool) {
|
|||||||
default:
|
default:
|
||||||
log.I.S("unrecognised packet", b)
|
log.I.S("unrecognised packet", b)
|
||||||
}
|
}
|
||||||
|
case p := <-cl.PaymentChan:
|
||||||
|
cl.PendingPayments = cl.PendingPayments.Add(p)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cl *Client) cipher(on *cipher.OnionSkin, b slice.Bytes, c *slice.Cursor) {
|
func (cl *Client) session(on *session.OnionSkin, b slice.Bytes,
|
||||||
|
c *slice.Cursor) {
|
||||||
|
|
||||||
// This either is in a forward only SendKeys message or we are the buyer
|
// This either is in a forward only SendKeys message or we are the buyer
|
||||||
// and these are our session keys.
|
// and these are our session keys.
|
||||||
// log.I.S(on)
|
// log.I.S(on)
|
||||||
@@ -98,19 +102,25 @@ func (cl *Client) cipher(on *cipher.OnionSkin, b slice.Bytes, c *slice.Cursor) {
|
|||||||
|
|
||||||
func (cl *Client) confirm(on *confirm.OnionSkin, b slice.Bytes,
|
func (cl *Client) confirm(on *confirm.OnionSkin, b slice.Bytes,
|
||||||
c *slice.Cursor) {
|
c *slice.Cursor) {
|
||||||
|
|
||||||
// When a confirm arrives check if it is registered for and run
|
// When a confirm arrives check if it is registered for and run
|
||||||
// the hook that was registered with it.
|
// the hook that was registered with it.
|
||||||
|
log.T.S(cl.Confirms)
|
||||||
cl.Confirms.Confirm(on.ID)
|
cl.Confirms.Confirm(on.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cl *Client) delay(on *delay.OnionSkin, b slice.Bytes, cur *slice.Cursor) {
|
func (cl *Client) delay(on *delay.OnionSkin, b slice.Bytes,
|
||||||
|
cur *slice.Cursor) {
|
||||||
|
|
||||||
// this is a message to hold the message in the buffer until a duration
|
// this is a message to hold the message in the buffer until a duration
|
||||||
// elapses. The accounting for the remainder of the message adds a
|
// elapses. The accounting for the remainder of the message adds a
|
||||||
// factor to the effective byte consumption in accordance with the time
|
// factor to the effective byte consumption in accordance with the time
|
||||||
// to be stored.
|
// to be stored.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cl *Client) exit(on *exit.OnionSkin, b slice.Bytes, c *slice.Cursor) {
|
func (cl *Client) exit(on *exit.OnionSkin, b slice.Bytes,
|
||||||
|
c *slice.Cursor) {
|
||||||
|
|
||||||
// payload is forwarded to a local port and the result is forwarded
|
// payload is forwarded to a local port and the result is forwarded
|
||||||
// back with a reverse header.
|
// back with a reverse header.
|
||||||
var e error
|
var e error
|
||||||
@@ -156,7 +166,9 @@ func (cl *Client) forward(on *forward.OnionSkin, b slice.Bytes,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cl *Client) layer(on *layer.OnionSkin, b slice.Bytes, c *slice.Cursor) {
|
func (cl *Client) layer(on *layer.OnionSkin, b slice.Bytes,
|
||||||
|
c *slice.Cursor) {
|
||||||
|
|
||||||
// this is probably an encrypted layer for us.
|
// this is probably an encrypted layer for us.
|
||||||
hdr, _, _ := cl.FindCloaked(on.Cloak)
|
hdr, _, _ := cl.FindCloaked(on.Cloak)
|
||||||
if hdr == nil {
|
if hdr == nil {
|
||||||
@@ -168,7 +180,9 @@ func (cl *Client) layer(on *layer.OnionSkin, b slice.Bytes, c *slice.Cursor) {
|
|||||||
cl.Node.Send(b)
|
cl.Node.Send(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cl *Client) noop(on *noop.OnionSkin, b slice.Bytes, c *slice.Cursor) {
|
func (cl *Client) noop(on *noop.OnionSkin, b slice.Bytes,
|
||||||
|
c *slice.Cursor) {
|
||||||
|
|
||||||
// this won't happen normally
|
// this won't happen normally
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,6 +228,8 @@ func (cl *Client) reverse(on *reverse.OnionSkin, b slice.Bytes,
|
|||||||
}
|
}
|
||||||
cl.Node.Send(b[start:])
|
cl.Node.Send(b[start:])
|
||||||
default:
|
default:
|
||||||
|
// If a reverse is not followed by an onion layer the
|
||||||
|
// message is incorrectly formed, just drop it.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -223,12 +239,16 @@ func (cl *Client) reverse(on *reverse.OnionSkin, b slice.Bytes,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cl *Client) response(on *response.OnionSkin, b slice.Bytes, cur *slice.Cursor) {
|
func (cl *Client) response(on *response.OnionSkin, b slice.Bytes,
|
||||||
|
cur *slice.Cursor) {
|
||||||
|
|
||||||
// Response is a payload from an exit message.
|
// Response is a payload from an exit message.
|
||||||
cl.ExitHooks.Find(on.Hash, on.Bytes)
|
cl.ExitHooks.Find(on.Hash, on.Bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cl *Client) token(t *token.OnionSkin, b slice.Bytes, cur *slice.Cursor) {
|
func (cl *Client) token(t *token.OnionSkin, b slice.Bytes,
|
||||||
|
cur *slice.Cursor) {
|
||||||
|
|
||||||
// not really sure if we are using these.
|
// not really sure if we are using these.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,8 +38,7 @@ func CreateMockCircuitClients() (clients []*Client, e error) {
|
|||||||
clients[i].Node = nodes[i]
|
clients[i].Node = nodes[i]
|
||||||
// create a session for all but the first
|
// create a session for all but the first
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
sessions[i-1] = node.NewSession(nonce.NewID(),
|
sessions[i-1] = node.NewSession(nonce.NewID(), nodes[i], math.MaxUint64, nil, nil)
|
||||||
nodes[i], math.MaxUint64)
|
|
||||||
// Add session to node, so it will be able to relay if
|
// Add session to node, so it will be able to relay if
|
||||||
// it gets a message with the key.
|
// it gets a message with the key.
|
||||||
nodes[i].Sessions = append(nodes[i].Sessions,
|
nodes[i].Sessions = append(nodes[i].Sessions,
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ func New(addr *netip.AddrPort, idPub *pub.Key, idPrv *prv.Key,
|
|||||||
IdentityPrv: idPrv,
|
IdentityPrv: idPrv,
|
||||||
PaymentChan: make(PaymentChan),
|
PaymentChan: make(PaymentChan),
|
||||||
}
|
}
|
||||||
n.Sessions = append(n.Sessions, NewSession(id, n, 0))
|
n.Sessions = append(n.Sessions, NewSession(id, n, 0, nil, nil))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ package node
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/indra-labs/indra/pkg/lnwire"
|
"github.com/indra-labs/indra/pkg/lnwire"
|
||||||
|
"github.com/indra-labs/indra/pkg/nonce"
|
||||||
"github.com/indra-labs/indra/pkg/sha256"
|
"github.com/indra-labs/indra/pkg/sha256"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Payment struct {
|
type Payment struct {
|
||||||
|
nonce.ID
|
||||||
Preimage sha256.Hash
|
Preimage sha256.Hash
|
||||||
Amount lnwire.MilliSatoshi
|
Amount lnwire.MilliSatoshi
|
||||||
}
|
}
|
||||||
@@ -32,9 +34,9 @@ func (p PendingPayments) Delete(preimage sha256.Hash) (pp PendingPayments) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PendingPayments) Find(preimage sha256.Hash) (pp *Payment) {
|
func (p PendingPayments) Find(id nonce.ID) (pp *Payment) {
|
||||||
for i := range p {
|
for i := range p {
|
||||||
if p[i].Preimage == preimage {
|
if p[i].ID == id {
|
||||||
return p[i]
|
return p[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,15 +22,17 @@ type Session struct {
|
|||||||
//
|
//
|
||||||
// Purchasing a session the seller returns a token, based on a requested data
|
// Purchasing a session the seller returns a token, based on a requested data
|
||||||
// allocation.
|
// allocation.
|
||||||
func NewSession(id nonce.ID, node *Node, rem uint64) (s *Session) {
|
func NewSession(id nonce.ID, node *Node, rem uint64,
|
||||||
|
hdrPrv *prv.Key, pldPrv *prv.Key) (s *Session) {
|
||||||
|
|
||||||
var e error
|
var e error
|
||||||
var hdrPrv, pldPrv *prv.Key
|
if hdrPrv == nil || pldPrv == nil {
|
||||||
if hdrPrv, e = prv.GenerateKey(); check(e) {
|
if hdrPrv, e = prv.GenerateKey(); check(e) {
|
||||||
|
}
|
||||||
|
if pldPrv, e = prv.GenerateKey(); check(e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
hdrPub := pub.Derive(hdrPrv)
|
hdrPub := pub.Derive(hdrPrv)
|
||||||
if pldPrv, e = prv.GenerateKey(); check(e) {
|
|
||||||
}
|
|
||||||
pldPub := pub.Derive(pldPrv)
|
pldPub := pub.Derive(pldPrv)
|
||||||
s = &Session{
|
s = &Session{
|
||||||
ID: id,
|
ID: id,
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
package cipher
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/indra-labs/indra"
|
|
||||||
"github.com/indra-labs/indra/pkg/key/prv"
|
|
||||||
"github.com/indra-labs/indra/pkg/key/pub"
|
|
||||||
log2 "github.com/indra-labs/indra/pkg/log"
|
|
||||||
"github.com/indra-labs/indra/pkg/slice"
|
|
||||||
"github.com/indra-labs/indra/pkg/types"
|
|
||||||
"github.com/indra-labs/indra/pkg/wire/magicbytes"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
MagicString = "cf"
|
|
||||||
Len = magicbytes.Len + pub.KeyLen*2
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
log = log2.GetLogger(indra.PathBase)
|
|
||||||
check = log.E.Chk
|
|
||||||
Magic = slice.Bytes(MagicString)
|
|
||||||
_ types.Onion = &OnionSkin{}
|
|
||||||
)
|
|
||||||
|
|
||||||
// OnionSkin cipher delivers a pair of private keys to be used in association
|
|
||||||
// with a reply.Type specifically in the situation of a node bootstrapping
|
|
||||||
// sessions.
|
|
||||||
//
|
|
||||||
// After ~10 seconds these can be purged from the cache as they are otherwise a
|
|
||||||
// DoS vector buffer flooding.
|
|
||||||
type OnionSkin struct {
|
|
||||||
Header, Payload *prv.Key
|
|
||||||
types.Onion
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *OnionSkin) Inner() types.Onion { return x.Onion }
|
|
||||||
func (x *OnionSkin) Insert(o types.Onion) { x.Onion = o }
|
|
||||||
func (x *OnionSkin) Len() int { return Len + x.Onion.Len() }
|
|
||||||
func (x *OnionSkin) Encode(b slice.Bytes, c *slice.Cursor) {
|
|
||||||
copy(b[*c:c.Inc(magicbytes.Len)], Magic)
|
|
||||||
hdr := x.Header.ToBytes()
|
|
||||||
pld := x.Payload.ToBytes()
|
|
||||||
copy(b[*c:c.Inc(prv.KeyLen)], hdr[:])
|
|
||||||
copy(b[*c:c.Inc(prv.KeyLen)], pld[:])
|
|
||||||
x.Onion.Encode(b, c)
|
|
||||||
}
|
|
||||||
func (x *OnionSkin) 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))
|
|
||||||
}
|
|
||||||
x.Header = prv.PrivkeyFromBytes(b[*c:c.Inc(prv.KeyLen)])
|
|
||||||
x.Payload = prv.PrivkeyFromBytes(b[*c:c.Inc(prv.KeyLen)])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
log2 "github.com/indra-labs/indra/pkg/log"
|
log2 "github.com/indra-labs/indra/pkg/log"
|
||||||
"github.com/indra-labs/indra/pkg/slice"
|
"github.com/indra-labs/indra/pkg/slice"
|
||||||
"github.com/indra-labs/indra/pkg/types"
|
"github.com/indra-labs/indra/pkg/types"
|
||||||
"github.com/indra-labs/indra/pkg/wire/cipher"
|
|
||||||
"github.com/indra-labs/indra/pkg/wire/confirm"
|
"github.com/indra-labs/indra/pkg/wire/confirm"
|
||||||
"github.com/indra-labs/indra/pkg/wire/delay"
|
"github.com/indra-labs/indra/pkg/wire/delay"
|
||||||
"github.com/indra-labs/indra/pkg/wire/exit"
|
"github.com/indra-labs/indra/pkg/wire/exit"
|
||||||
@@ -17,6 +16,7 @@ import (
|
|||||||
"github.com/indra-labs/indra/pkg/wire/magicbytes"
|
"github.com/indra-labs/indra/pkg/wire/magicbytes"
|
||||||
"github.com/indra-labs/indra/pkg/wire/response"
|
"github.com/indra-labs/indra/pkg/wire/response"
|
||||||
"github.com/indra-labs/indra/pkg/wire/reverse"
|
"github.com/indra-labs/indra/pkg/wire/reverse"
|
||||||
|
"github.com/indra-labs/indra/pkg/wire/session"
|
||||||
"github.com/indra-labs/indra/pkg/wire/token"
|
"github.com/indra-labs/indra/pkg/wire/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,8 +35,8 @@ func EncodeOnion(on types.Onion) (b slice.Bytes) {
|
|||||||
|
|
||||||
func PeelOnion(b slice.Bytes, c *slice.Cursor) (on types.Onion, e error) {
|
func PeelOnion(b slice.Bytes, c *slice.Cursor) (on types.Onion, e error) {
|
||||||
switch b[*c:c.Inc(magicbytes.Len)].String() {
|
switch b[*c:c.Inc(magicbytes.Len)].String() {
|
||||||
case cipher.MagicString:
|
case session.MagicString:
|
||||||
o := &cipher.OnionSkin{}
|
o := &session.OnionSkin{}
|
||||||
if e = o.Decode(b, c); check(e) {
|
if e = o.Decode(b, c); check(e) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import (
|
|||||||
"github.com/indra-labs/indra/pkg/slice"
|
"github.com/indra-labs/indra/pkg/slice"
|
||||||
"github.com/indra-labs/indra/pkg/tests"
|
"github.com/indra-labs/indra/pkg/tests"
|
||||||
"github.com/indra-labs/indra/pkg/types"
|
"github.com/indra-labs/indra/pkg/types"
|
||||||
"github.com/indra-labs/indra/pkg/wire/cipher"
|
|
||||||
"github.com/indra-labs/indra/pkg/wire/confirm"
|
"github.com/indra-labs/indra/pkg/wire/confirm"
|
||||||
"github.com/indra-labs/indra/pkg/wire/delay"
|
"github.com/indra-labs/indra/pkg/wire/delay"
|
||||||
"github.com/indra-labs/indra/pkg/wire/exit"
|
"github.com/indra-labs/indra/pkg/wire/exit"
|
||||||
@@ -23,6 +22,7 @@ import (
|
|||||||
"github.com/indra-labs/indra/pkg/wire/layer"
|
"github.com/indra-labs/indra/pkg/wire/layer"
|
||||||
"github.com/indra-labs/indra/pkg/wire/response"
|
"github.com/indra-labs/indra/pkg/wire/response"
|
||||||
"github.com/indra-labs/indra/pkg/wire/reverse"
|
"github.com/indra-labs/indra/pkg/wire/reverse"
|
||||||
|
"github.com/indra-labs/indra/pkg/wire/session"
|
||||||
"github.com/indra-labs/indra/pkg/wire/token"
|
"github.com/indra-labs/indra/pkg/wire/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -40,9 +40,9 @@ func TestOnionSkins_Cipher(t *testing.T) {
|
|||||||
if onc, e = PeelOnion(onb, c); check(e) {
|
if onc, e = PeelOnion(onb, c); check(e) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
var ci *cipher.OnionSkin
|
var ci *session.OnionSkin
|
||||||
var ok bool
|
var ok bool
|
||||||
if ci, ok = onc.(*cipher.OnionSkin); !ok {
|
if ci, ok = onc.(*session.OnionSkin); !ok {
|
||||||
t.Error("did not unwrap expected type")
|
t.Error("did not unwrap expected type")
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
"github.com/indra-labs/indra/pkg/sha256"
|
"github.com/indra-labs/indra/pkg/sha256"
|
||||||
"github.com/indra-labs/indra/pkg/slice"
|
"github.com/indra-labs/indra/pkg/slice"
|
||||||
"github.com/indra-labs/indra/pkg/types"
|
"github.com/indra-labs/indra/pkg/types"
|
||||||
"github.com/indra-labs/indra/pkg/wire/cipher"
|
|
||||||
"github.com/indra-labs/indra/pkg/wire/confirm"
|
"github.com/indra-labs/indra/pkg/wire/confirm"
|
||||||
"github.com/indra-labs/indra/pkg/wire/delay"
|
"github.com/indra-labs/indra/pkg/wire/delay"
|
||||||
"github.com/indra-labs/indra/pkg/wire/exit"
|
"github.com/indra-labs/indra/pkg/wire/exit"
|
||||||
@@ -19,6 +18,7 @@ import (
|
|||||||
"github.com/indra-labs/indra/pkg/wire/noop"
|
"github.com/indra-labs/indra/pkg/wire/noop"
|
||||||
"github.com/indra-labs/indra/pkg/wire/response"
|
"github.com/indra-labs/indra/pkg/wire/response"
|
||||||
"github.com/indra-labs/indra/pkg/wire/reverse"
|
"github.com/indra-labs/indra/pkg/wire/reverse"
|
||||||
|
"github.com/indra-labs/indra/pkg/wire/session"
|
||||||
"github.com/indra-labs/indra/pkg/wire/token"
|
"github.com/indra-labs/indra/pkg/wire/token"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ func (o OnionSkins) Cipher(hdr, pld *prv.Key) OnionSkins {
|
|||||||
if hdr == nil || pld == nil {
|
if hdr == nil || pld == nil {
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
return append(o, &cipher.OnionSkin{
|
return append(o, &session.OnionSkin{
|
||||||
Header: hdr,
|
Header: hdr,
|
||||||
Payload: pld,
|
Payload: pld,
|
||||||
Onion: &noop.OnionSkin{},
|
Onion: &noop.OnionSkin{},
|
||||||
|
|||||||
@@ -92,8 +92,8 @@ func SendExit(payload slice.Bytes, port uint16, client *node.Node,
|
|||||||
//
|
//
|
||||||
// This message's last layer is a Confirmation, which allows the client to know
|
// This message's last layer is a Confirmation, which allows the client to know
|
||||||
// that the keys were successfully delivered.
|
// that the keys were successfully delivered.
|
||||||
func SendKeys(id nonce.ID, hdr, pld []*prv.Key,
|
func SendKeys(id nonce.ID, hdr, pld [5]*prv.Key,
|
||||||
client *node.Node, hop []*node.Node, set *signer.KeySet) OnionSkins {
|
client *node.Node, hop node.Circuit, set *signer.KeySet) OnionSkins {
|
||||||
|
|
||||||
n := GenNonces(6)
|
n := GenNonces(6)
|
||||||
return OnionSkins{}.
|
return OnionSkins{}.
|
||||||
|
|||||||
105
pkg/wire/session/session.go
Normal file
105
pkg/wire/session/session.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package session
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/indra-labs/indra"
|
||||||
|
"github.com/indra-labs/indra/pkg/key/prv"
|
||||||
|
"github.com/indra-labs/indra/pkg/lnwire"
|
||||||
|
log2 "github.com/indra-labs/indra/pkg/log"
|
||||||
|
"github.com/indra-labs/indra/pkg/node"
|
||||||
|
"github.com/indra-labs/indra/pkg/nonce"
|
||||||
|
"github.com/indra-labs/indra/pkg/sha256"
|
||||||
|
"github.com/indra-labs/indra/pkg/slice"
|
||||||
|
"github.com/indra-labs/indra/pkg/types"
|
||||||
|
"github.com/indra-labs/indra/pkg/wire/magicbytes"
|
||||||
|
"github.com/indra-labs/indra/pkg/wire/noop"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MagicString = "ss"
|
||||||
|
Len = magicbytes.Len + prv.KeyLen*2
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
log = log2.GetLogger(indra.PathBase)
|
||||||
|
check = log.E.Chk
|
||||||
|
Magic = slice.Bytes(MagicString)
|
||||||
|
_ types.Onion = &OnionSkin{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// OnionSkin session delivers a pair of private keys to a relay that represent
|
||||||
|
// the preimage referred to in a Lightning payment for a session.
|
||||||
|
//
|
||||||
|
// The preimage is hashed by the buyer to use in the payment, and when the relay
|
||||||
|
// receives it, it can then hash the two private keys to match it with the
|
||||||
|
// payment preimage hash, which proves the buyer paid, and simultaneously
|
||||||
|
// provides the session keys that both forward and reverse messages will use,
|
||||||
|
// each in different ways.
|
||||||
|
//
|
||||||
|
// Exit nodes are provided the ciphers to encrypt for the three hops back to the
|
||||||
|
// client, but they do not have either public or private part of the Header or
|
||||||
|
// Payload keys of the return hops, which are used to conceal their respective
|
||||||
|
// message sections.
|
||||||
|
//
|
||||||
|
// Thus, they cannot decrypt the header, but they can encrypt the payload with
|
||||||
|
// the three layers of encryption that the reverse path hops have the private
|
||||||
|
// keys to decrypt. By this, the path in the header is concealed and the payload
|
||||||
|
// is concealed to the hops except for the encryption layer they decrypt using
|
||||||
|
// their Payload key, delivered in this message.
|
||||||
|
type OnionSkin struct {
|
||||||
|
Header, Payload *prv.Key
|
||||||
|
types.Onion
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() (x *OnionSkin) {
|
||||||
|
var e error
|
||||||
|
var hdrPrv, pldPrv *prv.Key
|
||||||
|
if hdrPrv, e = prv.GenerateKey(); check(e) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if pldPrv, e = prv.GenerateKey(); check(e) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return &OnionSkin{
|
||||||
|
Header: hdrPrv,
|
||||||
|
Payload: pldPrv,
|
||||||
|
Onion: &noop.OnionSkin{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *OnionSkin) PreimageHash() sha256.Hash {
|
||||||
|
h, p := x.Header.ToBytes(), x.Payload.ToBytes()
|
||||||
|
return sha256.Single(append(h[:], p[:]...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *OnionSkin) ToPayment(amount lnwire.
|
||||||
|
MilliSatoshi) (p *node.Payment) {
|
||||||
|
|
||||||
|
p = &node.Payment{
|
||||||
|
ID: nonce.NewID(),
|
||||||
|
Preimage: x.PreimageHash(),
|
||||||
|
Amount: amount,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *OnionSkin) Inner() types.Onion { return x.Onion }
|
||||||
|
func (x *OnionSkin) Insert(o types.Onion) { x.Onion = o }
|
||||||
|
func (x *OnionSkin) Len() int { return Len + x.Onion.Len() }
|
||||||
|
func (x *OnionSkin) Encode(b slice.Bytes, c *slice.Cursor) {
|
||||||
|
copy(b[*c:c.Inc(magicbytes.Len)], Magic)
|
||||||
|
hdr := x.Header.ToBytes()
|
||||||
|
pld := x.Payload.ToBytes()
|
||||||
|
copy(b[*c:c.Inc(prv.KeyLen)], hdr[:])
|
||||||
|
copy(b[*c:c.Inc(prv.KeyLen)], pld[:])
|
||||||
|
x.Onion.Encode(b, c)
|
||||||
|
}
|
||||||
|
func (x *OnionSkin) 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))
|
||||||
|
}
|
||||||
|
x.Header = prv.PrivkeyFromBytes(b[*c:c.Inc(prv.KeyLen)])
|
||||||
|
x.Payload = prv.PrivkeyFromBytes(b[*c:c.Inc(prv.KeyLen)])
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -10,9 +10,9 @@ var (
|
|||||||
// GitRef is the gitref, as in refs/heads/branchname.
|
// GitRef is the gitref, as in refs/heads/branchname.
|
||||||
GitRef = "refs/heads/protocol"
|
GitRef = "refs/heads/protocol"
|
||||||
// ParentGitCommit is the commit hash of the parent HEAD.
|
// ParentGitCommit is the commit hash of the parent HEAD.
|
||||||
ParentGitCommit = "6f271556c60e5ff2a5915d48a1b4f9ed7559dff4"
|
ParentGitCommit = "33257572125b76ba2bcad68dd54c92e2a4f44158"
|
||||||
// BuildTime stores the time when the current binary was built.
|
// BuildTime stores the time when the current binary was built.
|
||||||
BuildTime = "2023-01-14T08:54:21Z"
|
BuildTime = "2023-01-14T16:05:17Z"
|
||||||
// SemVer lists the (latest) git tag on the release.
|
// SemVer lists the (latest) git tag on the release.
|
||||||
SemVer = "v0.1.7"
|
SemVer = "v0.1.7"
|
||||||
// PathBase is the path base returned from runtime caller.
|
// PathBase is the path base returned from runtime caller.
|
||||||
|
|||||||
Reference in New Issue
Block a user