completed balance, confirmation, crypt, route

This commit is contained in:
l0k18
2023-07-06 07:07:32 +01:00
parent a1dc03a015
commit a24559d775
10 changed files with 918 additions and 49 deletions

799
go.sum

File diff suppressed because it is too large Load Diff

View File

@@ -22,24 +22,29 @@ var (
)
const (
BalanceMagic = "bala"
BalanceLen = magic.Len + nonce.IDLen + slice.Uint64Len
Magic = "bala"
Len = magic.Len + nonce.IDLen + slice.Uint64Len
)
// Balance is the balance with an ID the client has a pending balance update
// waiting on.
type Balance struct {
ID nonce.ID
lnwire.MilliSatoshi
}
// Account simply records the message ID, which will be recognised in the pending
// responses cache.
func (x *Balance) Account(res *sess.Data, sm *sess.Manager,
s *sessions.Data, last bool) (skip bool, sd *sessions.Data) {
res.ID = x.ID
return
}
// Decode a splice.Splice's next bytes into a Balance.
func (x *Balance) Decode(s *splice.Splice) (e error) {
if e = magic.TooShort(s.Remaining(), BalanceLen-magic.Len,
BalanceMagic); fails(e) {
if e = magic.TooShort(s.Remaining(), Len-magic.Len,
Magic); fails(e) {
return
}
s.ReadID(&x.ID).
@@ -47,20 +52,24 @@ func (x *Balance) Decode(s *splice.Splice) (e error) {
return
}
// Encode a Balance into a splice.Splice's next bytes.
func (x *Balance) Encode(s *splice.Splice) (e error) {
log.T.S("encoding", reflect.TypeOf(x),
x.ID,
x.MilliSatoshi,
)
s.
Magic(BalanceMagic).
Magic(Magic).
ID(x.ID).
Uint64(uint64(x.MilliSatoshi))
return
}
func (x *Balance) GetOnion() interface{} { return x }
// GetOnion returns nothing because there isn't an onion inside a Balance.
func (x *Balance) GetOnion() interface{} { return nil }
// Handle provides relay and accounting processing logic for receiving a Balance
// message.
func (x *Balance) Handle(s *splice.Splice, p ont.Onion, ng ont.Ngin) (e error) {
log.D.Ln("handling balance", x.ID)
log.D.S("pending", ng.Pending())
@@ -71,13 +80,14 @@ func (x *Balance) Handle(s *splice.Splice, p ont.Onion, ng ont.Ngin) (e error) {
out := int(session.Node.RelayRate) * s.Len()
if session != nil {
in := int(session.Node.RelayRate) * pending.SentSize
shb := session.Header.Bytes
switch {
case i < 2:
ng.Mgr().DecSession(session.Header.Bytes, in, true, "reverse")
ng.Mgr().DecSession(shb, in, true, "reverse")
case i == 2:
ng.Mgr().DecSession(session.Header.Bytes, (in+out)/2, true, "getbalance")
ng.Mgr().DecSession(shb, (in+out)/2, true, "getbalance")
case i > 2:
ng.Mgr().DecSession(session.Header.Bytes, out, true, "reverse")
ng.Mgr().DecSession(shb, out, true, "reverse")
}
}
}
@@ -100,13 +110,21 @@ func (x *Balance) Handle(s *splice.Splice, p ont.Onion, ng ont.Ngin) (e error) {
return
}
func (x *Balance) Len() int { return BalanceLen }
func (x *Balance) Magic() string { return BalanceMagic }
// Len returns the length of bytes required to encode the Balance.
func (x *Balance) Len() int { return Len }
// Magic bytes that identify this message
func (x *Balance) Magic() string { return Magic }
// Wrap is a no-op because a Balance is terminal.
func (x *Balance) Wrap(inner ont.Onion) {}
func NewBalance(id nonce.ID, amt lnwire.MilliSatoshi) ont.Onion {
// New creates a new Balance as an ont.Onion.
func New(id nonce.ID, amt lnwire.MilliSatoshi) ont.Onion {
return &Balance{ID: id, MilliSatoshi: amt}
}
func balanceGen() codec.Codec { return &Balance{} }
func init() { reg.Register(BalanceMagic, balanceGen) }
// Gen is a factory function to generate an Ad.
func Gen() codec.Codec { return &Balance{} }
func init() { reg.Register(Magic, Gen) }

View File

@@ -19,7 +19,7 @@ func TestOnions_Balance(t *testing.T) {
}
id := nonce.NewID()
sats := lnwire.MilliSatoshi(10000)
on := ont.Assemble([]ont.Onion{NewBalance(id, sats)})
on := ont.Assemble([]ont.Onion{New(id, sats)})
s := ont.Encode(on)
s.SetCursor(0)
var onc codec.Codec

View File

@@ -19,37 +19,47 @@ var (
)
const (
ConfirmationMagic = "conf"
ConfirmationLen = magic.Len + nonce.IDLen + 1
Magic = "conf"
Len = magic.Len + nonce.IDLen
)
// Confirmation is simply a nonce that associates with a pending circuit
// transmission.
//
// If a reply is required there needs to be a RoutingHeader and cipher/nonce set.
type Confirmation struct {
ID nonce.ID
Load byte
ID nonce.ID
}
// Account simply records the message ID, which will be recognised in the pending
// responses cache.
func (x *Confirmation) Account(res *sess.Data, sm *sess.Manager,
s *sessions.Data, last bool) (skip bool, sd *sessions.Data) {
res.ID = x.ID
return
}
// Decode a splice.Splice's next bytes into a Confirmation.
func (x *Confirmation) Decode(s *splice.Splice) (e error) {
if e = magic.TooShort(s.Remaining(), ConfirmationLen-magic.Len,
ConfirmationMagic); fails(e) {
if e = magic.TooShort(s.Remaining(), Len-magic.Len,
Magic); fails(e) {
return
}
s.ReadID(&x.ID).ReadByte(&x.Load)
s.ReadID(&x.ID)
return
}
// Encode a Balance into a splice.Splice's next bytes.
func (x *Confirmation) Encode(s *splice.Splice) (e error) {
s.Magic(ConfirmationMagic).ID(x.ID).Byte(x.Load)
s.Magic(Magic).ID(x.ID)
return
}
func (x *Confirmation) GetOnion() interface{} { return x }
// GetOnion returns nothing because there isn't an onion inside a Confirmation.
func (x *Confirmation) GetOnion() interface{} { return nil }
// Handle searches for a pending response and if it matches, runs the stored
// callbacks attached to it.
func (x *Confirmation) Handle(s *splice.Splice, p ont.Onion, ng ont.Ngin) (e error) {
// When a confirmation arrives check if it is registered for and run the
// hook that was registered with it.
@@ -57,9 +67,19 @@ func (x *Confirmation) Handle(s *splice.Splice, p ont.Onion, ng ont.Ngin) (e err
return
}
func (x *Confirmation) Len() int { return ConfirmationLen }
func (x *Confirmation) Magic() string { return ConfirmationMagic }
func (x *Confirmation) Wrap(inner ont.Onion) {}
func NewConfirmation(id nonce.ID, load byte) ont.Onion { return &Confirmation{ID: id, Load: load} }
func confirmationGen() codec.Codec { return &Confirmation{} }
func init() { reg.Register(ConfirmationMagic, confirmationGen) }
// Len returns the length of bytes required to encode the Confirmation.
func (x *Confirmation) Len() int { return Len }
// Magic bytes that identify this message
func (x *Confirmation) Magic() string { return Magic }
// Wrap is a no-op because a Confirmation is terminal.
func (x *Confirmation) Wrap(inner ont.Onion) {}
// New creates a new Confirmation.
func New(id nonce.ID) ont.Onion { return &Confirmation{ID: id} }
// Gen is a factory function to generate an Ad.
func Gen() codec.Codec { return &Confirmation{} }
func init() { reg.Register(Magic, Gen) }

View File

@@ -17,7 +17,7 @@ func TestOnions_Confirmation(t *testing.T) {
}
id := nonce.NewID()
var load byte = 128
on := ont.Assemble([]ont.Onion{NewConfirmation(id, load)})
on := ont.Assemble([]ont.Onion{New(id)})
s := ont.Encode(on)
s.SetCursor(0)
var onc codec.Codec

View File

@@ -33,18 +33,34 @@ const (
CryptMagic = "cryp"
)
// Crypt is an encrypted message, and forms the "skins" of the onions.
type Crypt struct {
Depth int
// Depth is used with RoutingHeaders to indicate which of the 3 layers in a
// ReverseCrypt section.
Depth int
// ToHeaderPub, ToPayloadPub are the public keys of the session.
ToHeaderPub, ToPayloadPub *crypto.Pub
From *crypto.Prv
IV nonce.IV
// From is usually a one-time generated private key for which the public
// counterpart combined with the recipient's private key generates the same
// secret via ECDH.
From *crypto.Prv
// IV is the Initialization Vector for the AES-CTR encryption used in a Crypt.
IV nonce.IV
// The remainder here are for Decode.
// Cloak
Cloak crypto.CloakedPubKey
ToPriv *crypto.Prv
FromPub *crypto.Pub
ont.Onion
}
// Account attaches the session, which is tied to the keys used in the crypt, to the pending result.
func (x *Crypt) Account(res *sess.Data, sm *sess.Manager, s *sessions.Data,
last bool) (skip bool, sd *sessions.Data) {
@@ -61,6 +77,7 @@ func (x *Crypt) Account(res *sess.Data, sm *sess.Manager, s *sessions.Data,
return
}
// Decode a splice.Splice's next bytes into a Crypt.
func (x *Crypt) Decode(s *splice.Splice) (e error) {
if e = magic.TooShort(s.Remaining(), consts.CryptLen-magic.Len,
CryptMagic); fails(e) {
@@ -78,6 +95,10 @@ func (x *Crypt) Decrypt(prk *crypto.Prv, s *splice.Splice) {
x.IV, s.GetRest())
}
// Encode a Crypt into a splice.Splice's next bytes.
//
// The crypt renders the inner contents first and once complete returns and
// encrypts everything after the Crypt header.
func (x *Crypt) Encode(s *splice.Splice) (e error) {
log.T.F("encoding %s %s %x %x", reflect.TypeOf(x),
x.ToHeaderPub, x.From.ToBytes(), x.IV,
@@ -120,8 +141,11 @@ func (x *Crypt) Encode(s *splice.Splice) (e error) {
return e
}
// GetOnion returns the layers inside the crypt..
func (x *Crypt) GetOnion() interface{} { return x }
// Handle provides relay and accounting processing logic for receiving a Crypt
// message.
func (x *Crypt) Handle(s *splice.Splice, p ont.Onion, ng ont.Ngin) (e error) {
hdr, _, _, identity := ng.Mgr().FindCloaked(x.Cloak)
if hdr == nil {
@@ -143,11 +167,17 @@ func (x *Crypt) Handle(s *splice.Splice, p ont.Onion, ng ont.Ngin) (e error) {
return e
}
func (x *Crypt) Len() int { return consts.CryptLen + x.Onion.Len() }
func (x *Crypt) Magic() string { return CryptMagic }
// Len returns the length of bytes required to encode the Crypt.
func (x *Crypt) Len() int { return consts.CryptLen + x.Onion.Len() }
// Magic bytes that identify this message
func (x *Crypt) Magic() string { return CryptMagic }
// Wrap inserts an onion inside a Crypt.
func (x *Crypt) Wrap(inner ont.Onion) { x.Onion = inner }
func NewCrypt(toHdr, toPld *crypto.Pub, from *crypto.Prv, iv nonce.IV,
// New creates a new crypt message with an empty slot for more messages.
func New(toHdr, toPld *crypto.Pub, from *crypto.Prv, iv nonce.IV,
depth int) ont.Onion {
return &Crypt{
Depth: depth,
@@ -159,5 +189,7 @@ func NewCrypt(toHdr, toPld *crypto.Pub, from *crypto.Prv, iv nonce.IV,
}
}
func cryptGen() codec.Codec { return &Crypt{} }
func init() { reg.Register(CryptMagic, cryptGen) }
// Gen is a factory function to generate an Crypt.
func Gen() codec.Codec { return &Crypt{} }
func init() { reg.Register(CryptMagic, Gen) }

View File

@@ -23,8 +23,8 @@ func TestOnions_SimpleCrypt(t *testing.T) {
prv1, prv2 := crypto.GetTwoPrvKeys()
pub1, pub2 := crypto.DerivePub(prv1), crypto.DerivePub(prv2)
on := ont.Assemble([]ont.Onion{
NewCrypt(pub1, pub2, prv2, n1, 0),
confirmation.NewConfirmation(n, 0),
New(pub1, pub2, prv2, n1, 0),
confirmation.New(n),
})
s := ont.Encode(on)
s.SetCursor(0)

View File

@@ -166,11 +166,11 @@ func (x *Route) Handle(s *splice.Splice, p ont.Onion, ng ont.Ngin) (e error) {
}
rh := []ont.Onion{
reverse.NewReverse(&addrs[0]),
crypt.NewCrypt(rt.Sessions[0].Header.Pub, rt.Sessions[0].Payload.Pub, rt.Keys[0], rt.Nonces[0], 3),
crypt.New(rt.Sessions[0].Header.Pub, rt.Sessions[0].Payload.Pub, rt.Keys[0], rt.Nonces[0], 3),
reverse.NewReverse(&addrs[1]),
crypt.NewCrypt(rt.Sessions[1].Header.Pub, rt.Sessions[1].Payload.Pub, rt.Keys[1], rt.Nonces[1], 2),
crypt.New(rt.Sessions[1].Header.Pub, rt.Sessions[1].Payload.Pub, rt.Keys[1], rt.Nonces[1], 2),
reverse.NewReverse(&addrs[2]),
crypt.NewCrypt(rt.Sessions[2].Header.Pub, rt.Sessions[2].Payload.Pub, rt.Keys[2], rt.Nonces[2], 1),
crypt.New(rt.Sessions[2].Header.Pub, rt.Sessions[2].Payload.Pub, rt.Keys[2], rt.Nonces[2], 1),
}
//.RoutingHeader(rt)
rHdr := ont.Encode(ont.Assemble(rh))
@@ -185,9 +185,9 @@ func (x *Route) Handle(s *splice.Splice, p ont.Onion, ng ont.Ngin) (e error) {
}
mr := []ont.Onion{
forward.NewForward(&addrs[3]),
crypt.NewCrypt(ss[3].Header.Pub, ss[3].Payload.Pub, ng.Keyset().Next(), n[3], 0),
crypt.New(ss[3].Header.Pub, ss[3].Payload.Pub, ng.Keyset().Next(), n[3], 0),
forward.NewForward(&addrs[4]),
crypt.NewCrypt(ss[4].Header.Pub, ss[4].Payload.Pub, ng.Keyset().Next(), n[4], 0),
crypt.New(ss[4].Header.Pub, ss[4].Payload.Pub, ng.Keyset().Next(), n[4], 0),
ready.NewReady(x.ID, x.HiddenService,
x.RoutingHeaderBytes,
hidden.GetRoutingHeaderFromCursor(rHdr),

View File

@@ -74,7 +74,7 @@ func TestDispatcher(t *testing.T) {
var load1 byte = 128
// var load2 byte = 32
on1 := ont.Assemble(engine.Skins{
confirmation.NewConfirmation(id1, load1)})
confirmation.New(id1)})
on2 := ont.Assemble(engine.Skins{
response.NewResponse(id2, 0, msg1, 0)})
s1 := ont.Encode(on1)

View File

@@ -34,7 +34,7 @@ import (
//}
func (o Skins) Confirmation(id nonce.ID, load byte) Skins {
return append(o, confirmation.NewConfirmation(id, load))
return append(o, confirmation.New(id))
}
//func (o Skins) Delay(d time.Duration) Skins { return append(o, delay.NewDelay(d)) }
@@ -143,7 +143,7 @@ func (o Skins) Reverse(ip *netip.AddrPort) Skins { return append(o, reverse.NewR
func (o Skins) Crypt(toHdr, toPld *crypto.Pub, from *crypto.Prv, iv nonce.IV,
depth int) Skins {
return append(o, crypt.NewCrypt(toHdr, toPld, from, iv, depth))
return append(o, crypt.New(toHdr, toPld, from, iv, depth))
}
// ReverseCrypt is a single layer of a RoutingHeader designating the session and relay for one of the hops in a Route.