create prototype that contains all common fields

This commit is contained in:
херетик
2023-06-05 21:42:04 +01:00
parent 46cf8b7010
commit e1140925d5
4 changed files with 266 additions and 80 deletions

View File

@@ -0,0 +1,127 @@
package adproto
import (
"github.com/indra-labs/indra"
"github.com/indra-labs/indra/pkg/ad"
"github.com/indra-labs/indra/pkg/crypto"
"github.com/indra-labs/indra/pkg/crypto/nonce"
"github.com/indra-labs/indra/pkg/crypto/sha256"
"github.com/indra-labs/indra/pkg/engine/coding"
"github.com/indra-labs/indra/pkg/engine/magic"
"github.com/indra-labs/indra/pkg/engine/sess"
"github.com/indra-labs/indra/pkg/onions/reg"
log2 "github.com/indra-labs/indra/pkg/proc/log"
"github.com/indra-labs/indra/pkg/util/qu"
"github.com/indra-labs/indra/pkg/util/slice"
"github.com/indra-labs/indra/pkg/util/splice"
"reflect"
"time"
)
var (
log = log2.GetLogger(indra.PathBase)
fails = log.E.Chk
)
const (
Magic = "prot"
Len = magic.Len +
nonce.IDLen +
crypto.PubKeyLen +
slice.Uint64Len +
crypto.SigLen
)
// Ad entries are stored with an index generated by concatenating the bytes
// of the public key with a string path "/address/N" where N is the index of the
// address. This means hidden service introducers for values over zero.
// Hidden services have no value in the zero index, which is "<hash>/address/0".
type Ad struct {
ID nonce.ID // To ensure no repeating message
Key *crypto.Pub
Expiry time.Time
Sig crypto.SigBytes
}
func (x *Ad) Decode(s *splice.Splice) (e error) {
if e = magic.TooShort(s.Remaining(), Len-magic.Len,
Magic); fails(e) {
return
}
s.ReadID(&x.ID).
ReadPubkey(&x.Key).
ReadTime(&x.Expiry).
ReadSignature(&x.Sig)
return
}
func (x *Ad) Encode(s *splice.Splice) (e error) {
log.T.S("encoding", reflect.TypeOf(x),
x.ID, x.Sig,
)
x.Splice(s)
return
}
func (x *Ad) GetOnion() interface{} { return x }
func (x *Ad) Gossip(sm *sess.Manager, c qu.C) {
log.D.F("propagating peer info for %s",
x.Key.ToBased32Abbreviated())
ad.Gossip(x, sm, c)
log.T.Ln("finished broadcasting peer info")
}
func (x *Ad) Len() int { return Len }
func (x *Ad) Magic() string { return Magic }
func (x *Ad) Splice(s *splice.Splice) {
x.SpliceWithoutSig(s)
s.Signature(x.Sig)
}
func (x *Ad) SpliceWithoutSig(s *splice.Splice) {
s.Magic(Magic).
ID(x.ID).
Pubkey(x.Key).
Time(x.Expiry)
}
func (x *Ad) Validate() bool {
s := splice.New(Len - magic.Len)
x.SpliceWithoutSig(s)
hash := sha256.Single(s.GetUntil(s.GetCursor()))
key, e := x.Sig.Recover(hash)
if fails(e) {
return false
}
if key.Equals(x.Key) {
return true
}
return false
}
func NewAddressAd(id nonce.ID, key *crypto.Prv,
expiry time.Time) (peerAd *Ad) {
pub := crypto.DerivePub(key)
peerAd = &Ad{
ID: id,
Key: pub,
Expiry: expiry,
}
s := splice.New(Len - magic.Len)
peerAd.SpliceWithoutSig(s)
hash := sha256.Single(s.GetUntil(s.GetCursor()))
var e error
if peerAd.Sig, e = crypto.Sign(key, hash); fails(e) {
return nil
}
return
}
func protGen() coding.Codec { return &Ad{} }
func init() { reg.Register(Magic, protGen) }

View File

@@ -0,0 +1,61 @@
package adproto
import (
"github.com/indra-labs/indra"
"github.com/indra-labs/indra/pkg/crypto"
"github.com/indra-labs/indra/pkg/crypto/nonce"
"github.com/indra-labs/indra/pkg/engine/coding"
"github.com/indra-labs/indra/pkg/onions/reg"
log2 "github.com/indra-labs/indra/pkg/proc/log"
"github.com/indra-labs/indra/pkg/util/splice"
"testing"
"time"
)
func TestProtoAd(t *testing.T) {
if indra.CI == "false" {
log2.SetLogLevel(log2.Trace)
}
var e error
pr, _, _ := crypto.NewSigner()
id := nonce.NewID()
aa := NewAddressAd(id, pr, time.Now().Add(time.Hour))
log.D.S("ad", aa)
s := splice.New(aa.Len())
if e = aa.Encode(s); fails(e) {
t.FailNow()
}
s.SetCursor(0)
var onc coding.Codec
if onc = reg.Recognise(s); onc == nil {
t.Error("did not unwrap")
t.FailNow()
}
if e = onc.Decode(s); fails(e) {
t.Error("did not decode")
t.FailNow()
}
log.D.S(onc)
var ad *Ad
var ok bool
if ad, ok = onc.(*Ad); !ok {
t.Error("did not unwrap expected type")
t.FailNow()
}
if ad.ID != aa.ID {
t.Errorf("ID did not decode correctly")
t.FailNow()
}
if ad.Expiry == aa.Expiry {
t.Errorf("expiry did not decode correctly")
t.FailNow()
}
if !ad.Key.Equals(crypto.DerivePub(pr)) {
t.Errorf("public key did not decode correctly")
t.FailNow()
}
if !ad.Validate() {
t.Errorf("received ad did not validate")
t.FailNow()
}
}

View File

@@ -1,7 +1,6 @@
package splice package splice
import ( import (
"encoding/hex"
"fmt" "fmt"
"github.com/gookit/color" "github.com/gookit/color"
"github.com/indra-labs/indra" "github.com/indra-labs/indra"
@@ -10,7 +9,6 @@ import (
"github.com/indra-labs/indra/pkg/crypto/sha256" "github.com/indra-labs/indra/pkg/crypto/sha256"
magic2 "github.com/indra-labs/indra/pkg/engine/magic" magic2 "github.com/indra-labs/indra/pkg/engine/magic"
log2 "github.com/indra-labs/indra/pkg/proc/log" log2 "github.com/indra-labs/indra/pkg/proc/log"
"github.com/indra-labs/indra/pkg/util/b32/based32"
"github.com/indra-labs/indra/pkg/util/slice" "github.com/indra-labs/indra/pkg/util/slice"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"net" "net"
@@ -456,78 +454,78 @@ func (s *Splice) StoreCursor(c *int) *Splice {
return s return s
} }
func (s *Splice) String() (o string) { //func (s *Splice) String() (o string) {
o = "splice:" // o = "splice:"
seg := s.GetSlicesFromSegments() // seg := s.GetSlicesFromSegments()
var prevString string // var prevString string
for i := range seg { // for i := range seg {
switch v := seg[i].(type) { // switch v := seg[i].(type) {
case string: // case string:
o += "\n" + v + " " // o += "\n" + v + " "
prevString = v // prevString = v
case slice.Bytes: // case slice.Bytes:
if len(v) > 72 { // if len(v) > 72 {
o += "\n " // o += "\n "
} // }
var oe string // var oe string
for j := range v { // for j := range v {
if (j)%4 == 0 && j != 0 { // if (j)%4 == 0 && j != 0 {
oe += "" // oe += ""
} // }
if j == 0 { // if j == 0 {
oe += "" // oe += ""
} // }
if v[j] >= '0' && v[j] <= '9' || // if v[j] >= '0' && v[j] <= '9' ||
v[j] >= 'a' && v[j] <= 'z' || // v[j] >= 'a' && v[j] <= 'z' ||
v[j] >= 'A' && v[j] <= 'Z' { // v[j] >= 'A' && v[j] <= 'Z' {
oe += string(v[j]) // oe += string(v[j])
} else { // } else {
oe += "." // oe += "."
} // }
} // }
if prevString == "magic" { // if prevString == "magic" {
o += color.Red.Sprint(oe) + " " // o += color.Red.Sprint(oe) + " "
} else { // } else {
o += color.Gray.Sprint(oe) + " " // o += color.Gray.Sprint(oe) + " "
} // }
if prevString != "remainder" { // if prevString != "remainder" {
hexed := hex.EncodeToString(v.ToBytes()) // hexed := hex.EncodeToString(v.ToBytes())
var oHexed string // var oHexed string
var revHex string // var revHex string
for { // for {
if len(hexed) >= 8 { // if len(hexed) >= 8 {
revHex, hexed = hexed[:8], hexed[8:] // revHex, hexed = hexed[:8], hexed[8:]
oHexed += revHex + " " // oHexed += revHex + " "
} else { // } else {
oHexed += hexed // oHexed += hexed
break // break
} // }
} // }
o += color.Gray.Sprint(color.Bold.Sprint(oHexed)) // o += color.Gray.Sprint(color.Bold.Sprint(oHexed))
} // }
if prevString == "pubkey" { // if prevString == "pubkey" {
var oo string // var oo string
if oo, s.E = based32.Codec.Encode(v.ToBytes()); fails(s.E) { // if oo, s.E = based32.Codec.Encode(v.ToBytes()); fails(s.E) {
o += "<error: " + s.E.Error() + " >" // o += "<error: " + s.E.Error() + " >"
} // }
oo = oo[3:] // oo = oo[3:]
tmp := make(slice.Bytes, 0, len(oo)) // tmp := make(slice.Bytes, 0, len(oo))
tmp = append(tmp[:13], append([]byte("..."), // tmp = append(tmp[:13], append([]byte("..."),
tmp[len(tmp)-8:]...)...) // tmp[len(tmp)-8:]...)...)
oo = string(tmp) // oo = string(tmp)
o += color.LightGreen.Sprint(" ", oo) // o += color.LightGreen.Sprint(" ", oo)
} // }
if prevString == "Keys" { // if prevString == "Keys" {
var oo string // var oo string
if oo, s.E = based32.Codec.Encode(v.ToBytes()); fails(s.E) { // if oo, s.E = based32.Codec.Encode(v.ToBytes()); fails(s.E) {
o += "<error: " + s.E.Error() + " >" // o += "<error: " + s.E.Error() + " >"
} // }
o += color.LightBlue.Sprint(oo[:13]) // o += color.LightBlue.Sprint(oo[:13])
} // }
} // }
} // }
return // return
} //}
func (s *Splice) Time(v time.Time) *Splice { func (s *Splice) Time(v time.Time) *Splice {
slice.EncodeUint64(s.b[*s.c:s.c.Inc(slice.Uint64Len)], uint64(v.UnixNano())) slice.EncodeUint64(s.b[*s.c:s.c.Inc(slice.Uint64Len)], uint64(v.UnixNano()))
@@ -562,11 +560,11 @@ func (s *Splice) Uint64(v uint64) *Splice {
return s return s
} }
func (s Segments) String() (o string) { //func (s Segments) String() (o string) {
for i := range s { // for i := range s {
o += fmt.Sprintf("%s %d ", s[i].Name, s[i].Offset) // o += fmt.Sprintf("%s %d ", s[i].Name, s[i].Offset)
} // }
return // return
} //}
func (s Segments) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s Segments) Swap(i, j int) { s[i], s[j] = s[j], s[i] }