Stubbed in wire message types and interface

This commit is contained in:
David Vennik
2022-12-11 14:18:08 +01:00
parent c8f58a25bf
commit 3d436e9c7c
3 changed files with 233 additions and 36 deletions

View File

@@ -90,7 +90,7 @@ func TestClient_GenerateCircuit(t *testing.T) {
IP: ci.Hops[len(ci.Hops)-i-1].IP,
Message: lastMsg,
}
rmm := rm.Serialize()
rmm := rm.Encode()
ep := message.EP{
To: address.
FromPubKey(ci.Hops[len(ci.Hops)-i-1].Key),
@@ -158,7 +158,7 @@ func TestClient_GenerateCircuit(t *testing.T) {
t.Error(e)
t.FailNow()
}
if rm, e = wire.ToReturnMessage(msg); check(e) {
if rm, e = wire.ToForward(msg); check(e) {
t.Error(e)
t.FailNow()
}

View File

@@ -6,22 +6,47 @@ import (
"reflect"
"github.com/Indra-Labs/indra/pkg/ifc"
"github.com/Indra-Labs/indra/pkg/key/pub"
"github.com/Indra-Labs/indra/pkg/nonce"
)
type MessageMagic byte
// MagicLen is 3 to make it nearly impossible that the wrong cipher will yield a
// valid Magic string as listed below.
const MagicLen = 3
type Message interface{}
type MessageMagic string
const (
ForwardMagic MessageMagic = iota
ExitMagic
ReturnMagic
func GetMagic(s string) (mm MessageMagic) {
return MessageMagic(s[:MagicLen])
}
type Message interface {
Encode() (o ifc.Message)
}
var (
ForwardMagic = MessageMagic("fwd")
ExitMagic = MessageMagic("exi")
ReturnMagic = MessageMagic("rtn")
CipherMagic = MessageMagic("cif")
PurchaseMagic = MessageMagic("prc")
SessionMagic = MessageMagic("ses")
)
func Serialize(message interface{}) (b ifc.Message, e error) {
switch m := message.(type) {
case Forward:
b = m.Serialize()
b = m.Encode()
case Exit:
case Return:
case Cipher:
case Purchase:
case Session:
default:
e = fmt.Errorf("unknown type %v", reflect.TypeOf(m))
}
@@ -29,21 +54,22 @@ func Serialize(message interface{}) (b ifc.Message, e error) {
}
func Deserialize(b ifc.Message) (out Message, e error) {
msgMagic := MessageMagic(b[0])
switch msgMagic {
mm := MessageMagic(b[:MagicLen])
switch mm {
case ForwardMagic:
out, e = DeserializeReturnMessage(b)
}
return
}
out, e = DecodeForward(b)
case ExitMagic:
case ReturnMagic:
case CipherMagic:
case PurchaseMagic:
case SessionMagic:
func ToReturnMessage(msg Message) (rm *Forward, e error) {
switch r := msg.(type) {
case *Forward:
rm = r
default:
e = fmt.Errorf("incorrect type returned %v expected %v",
reflect.TypeOf(r), reflect.TypeOf(&Forward{}))
e = fmt.Errorf("unknown message magic '%s'", mm)
}
return
}
@@ -54,28 +80,199 @@ type Forward struct {
ifc.Message
}
func (rm *Forward) Serialize() (o ifc.Message) {
func (rm *Forward) Encode() (o ifc.Message) {
ipLen := len(rm.IP)
totalLen := 1 + ipLen + len(rm.Message) + 1
o = make(ifc.Message, totalLen)
o[0] = byte(ForwardMagic)
o[1] = byte(ipLen)
copy(o[2:ipLen+2], rm.IP)
copy(o[ipLen+2:], rm.Message)
copy(o[:MagicLen], ForwardMagic)
o[MagicLen] = byte(ipLen)
copy(o[MagicLen+1:MagicLen+ipLen+2], rm.IP)
copy(o[MagicLen+ipLen+2:], rm.Message)
return
}
func DeserializeReturnMessage(msg ifc.Message) (rm *Forward, e error) {
ipLen := int(msg[1])
func DecodeForward(msg ifc.Message) (rm *Forward, e error) {
ipLen := int(msg[MagicLen])
rm = &Forward{
IP: net.IP(msg[2 : 2+ipLen]),
Message: msg[2+ipLen:],
IP: net.IP(msg[MagicLen+1 : MagicLen+1+ipLen]),
Message: msg[MagicLen+1+ipLen:],
}
return
}
type Exit struct {
// ToForward safely asserts the type of Message to be a Forward message.
func ToForward(msg Message) (f *Forward, e error) {
switch t := msg.(type) {
case *Forward:
f = t
default:
e = fmt.Errorf("incorrect type returned %v expected %v",
reflect.TypeOf(t), reflect.TypeOf(&Forward{}))
}
return
}
type Return struct {
// Exit messages are the layer of a message after two Forward packets that
// provides an exit address and
type Exit struct {
// Port identifies the type of service as well as being the port used
// by the service to be relayed to. Notice there is no IP address, this
// is because Indranet only forwards to exits of decentralised services
// also running on the same machine. This service could be a proxy, of
// course, if configured this way.
Port uint16
// Cipher is a set of 3 symmetric ciphers that are to be used in their
// given order over the reply message from the service.
Cipher [3][32]byte
// Return is the encoded message with the three hops using the Return
// keys for the relevant relays, encrypted progressively. Note that this
// message uses a different Cipher than the one above
Return ifc.Message
ifc.Message
}
func (rm *Exit) Encode() (o ifc.Message) {
return
}
func DecodeExit(msg ifc.Message) (rm *Exit, e error) {
return
}
// ToExit safely asserts the type of Message to be an Exit message.
func ToExit(msg Message) (x *Exit, e error) {
switch t := msg.(type) {
case *Exit:
x = t
default:
e = fmt.Errorf("incorrect type returned %v expected %v",
reflect.TypeOf(t), reflect.TypeOf(x))
}
return
}
// Return messages are distinct from Forward messages in that the header
// encryption uses a different secret than the payload. Relays identify this by
// encrypting the first 16 bytes of the header and if one of the magic bytes is
// not found
type Return struct {
nonce.ID
// IP is the address of the next relay in the return leg of a circuit.
net.IP
ifc.Message
}
func (rm *Return) Encode() (o ifc.Message) {
return
}
func DecodeReturn(msg ifc.Message) (rm *Return, e error) {
return
}
// ToReturn safely asserts the type of Message to be an Return message.
func ToReturn(msg Message) (rm *Return, e error) {
switch r := msg.(type) {
case *Return:
rm = r
default:
e = fmt.Errorf("incorrect type returned %v expected %v",
reflect.TypeOf(r), reflect.TypeOf(rm))
}
return
}
// Cipher delivers a public key to be used in association with a Return with the
// matching ID. This is wrapped in two Forward messages and contains two layers
// of Forward messages, ensuring that the node cannot discover where this comes
// from but allows a Return public key to be provided for a Purchase.
type Cipher struct {
nonce.ID
Key pub.Bytes
Forward
}
func (rm *Cipher) Encode() (o ifc.Message) {
return
}
func DecodeCipher(msg ifc.Message) (rm *Cipher, e error) {
return
}
// ToCipher safely asserts the type of Message to be a Cipher message.
func ToCipher(msg Message) (c *Cipher, e error) {
switch t := msg.(type) {
case *Cipher:
c = t
default:
e = fmt.Errorf("incorrect type returned %v expected %v",
reflect.TypeOf(t), reflect.TypeOf(c))
}
return
}
// Purchase is a message that is sent after first forwarding a Lighting payment
// of an amount corresponding to the number of bytes requested based on the
// price advertised for Exit traffic by a relay. The Receipt is the confirmation
// after requesting an Invoice for the amount and then paying it.
//
// This message contains a Return message, which enables payments to proxy
// forwards through two hops to the router that will issue the Session, plus two
// more Return layers for carrying the Session back to the client.
type Purchase struct {
Bytes int
Receipt ifc.Message
Return
}
func (rm *Purchase) Encode() (o ifc.Message) {
return
}
func DecodePurchase(msg ifc.Message) (rm *Purchase, e error) {
return
}
// ToPurchase safely asserts the type of Message to be a Purchase message.
func ToPurchase(msg Message) (p *Purchase, e error) {
switch t := msg.(type) {
case *Purchase:
p = t
default:
e = fmt.Errorf("incorrect type returned %v expected %v",
reflect.TypeOf(t), reflect.TypeOf(p))
}
return
}
// Session is a message containing two public keys which identify to a relay the
// session to account bytes on, this is wrapped in two Return message layers by
// the seller. Forward keys are used for encryption in Forward and Exit
// messages, and Return keys are separate and are only known to the client and
// relay that issues a Session, ensuring that the Exit cannot see the inner
// layers of the Return messages.
type Session struct {
Forward pub.Bytes
Return pub.Bytes
}
func (rm *Session) Encode() (o ifc.Message) {
return
}
func DecodeSession(msg ifc.Message) (rm *Session, e error) {
return
}
// ToSession safely asserts the type of Message to be a Purchase message.
func ToSession(msg Message) (s *Session, e error) {
switch t := msg.(type) {
case *Session:
s = t
default:
e = fmt.Errorf("incorrect type returned %v expected %v",
reflect.TypeOf(t), reflect.TypeOf(s))
}
return
}

View File

@@ -13,11 +13,11 @@ var (
// GitRef is the gitref, as in refs/heads/branchname.
GitRef = "refs/heads/main"
// ParentGitCommit is the commit hash of the parent HEAD.
ParentGitCommit = "9030a2f70411a2df3229a26e8114410cacbb35e3"
ParentGitCommit = "70ca966817cddb2e6916141b330c8764187c2b32"
// BuildTime stores the time when the current binary was built.
BuildTime = "2022-12-10T15:24:46+01:00"
BuildTime = "2022-12-11T14:18:08+01:00"
// SemVer lists the (latest) git tag on the build.
SemVer = "v0.0.177"
SemVer = "v0.0.178"
// PathBase is the path base returned from runtime caller.
PathBase = "/home/loki/src/github.com/Indra-Labs/indra/"
// Major is the major number from the tag.
@@ -25,7 +25,7 @@ var (
// Minor is the minor number from the tag.
Minor = 0
// Patch is the patch version number from the tag.
Patch = 177
Patch = 178
)
// Version returns a pretty printed version information string.