Stubbed in wire message types and interface
This commit is contained in:
@@ -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()
|
||||
}
|
||||
|
||||
257
pkg/wire/wire.go
257
pkg/wire/wire.go
@@ -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
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user