Skip to content
Snippets Groups Projects
Commit 0ca8d355 authored by Jonah Husson's avatar Jonah Husson
Browse files

Merge branch 'release' into cloud/notificationbot

parents 4db59d0d 37c1c4d3
No related branches found
No related tags found
No related merge requests found
...@@ -6,12 +6,6 @@ cache: ...@@ -6,12 +6,6 @@ cache:
paths: paths:
- vendor/ - vendor/
variables:
REPO_DIR: gitlab.com/elixxir
REPO_NAME: primitives
DOCKER_IMAGE: elixxirlabs/cuda-go:latest
MIN_CODE_COVERAGE: "80.0"
before_script: before_script:
- go version || echo "Go executable not found." - go version || echo "Go executable not found."
- echo $CI_BUILD_REF - echo $CI_BUILD_REF
...@@ -21,10 +15,10 @@ before_script: ...@@ -21,10 +15,10 @@ before_script:
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
- mkdir -p ~/.ssh - mkdir -p ~/.ssh
- chmod 700 ~/.ssh - chmod 700 ~/.ssh
- ssh-keyscan -t rsa gitlab.com > ~/.ssh/known_hosts - ssh-keyscan -t rsa $GITLAB_SERVER > ~/.ssh/known_hosts
- git config --global url."git@gitlab.com:".insteadOf "https://gitlab.com/" - git config --global url."git@$GITLAB_SERVER:".insteadOf "https://gitlab.com/"
- export PATH=$HOME/go/bin:$PATH - export PATH=$HOME/go/bin:$PATH
- export GOPRIVATE=gitlab.com/elixxir/* - export GOPRIVATE=gitlab.com/elixxir/*,gitlab.com/xx_network/*
stages: stages:
- build - build
...@@ -32,7 +26,7 @@ stages: ...@@ -32,7 +26,7 @@ stages:
build: build:
stage: build stage: build
image: $DOCKER_IMAGE image: elixxirlabs/cuda-go:go1.13-cuda11.1
script: script:
- git clean -ffdx - git clean -ffdx
- go mod vendor -v - go mod vendor -v
...@@ -58,12 +52,11 @@ build: ...@@ -58,12 +52,11 @@ build:
- testdata/ - testdata/
- release/ - release/
trigger: trigger_integration:
stage: trigger_integration stage: trigger_integration
script: trigger:
# client project: elixxir/integration
- "curl -X POST -F token=$CLIENT_TRIGGER_KEY -F ref=master https://gitlab.com/api/v4/projects/5454785/trigger/pipeline" branch: $CI_COMMIT_REF_NAME
# server
- "curl -X POST -F token=$SERVER_TRIGGER_KEY -F ref=master https://gitlab.com/api/v4/projects/5014439/trigger/pipeline"
only: only:
- release
- master - master
...@@ -30,9 +30,11 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw ...@@ -30,9 +30,11 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
...@@ -44,6 +46,7 @@ github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0 ...@@ -44,6 +46,7 @@ github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/zeebo/assert v0.0.0-20181109011804-10f827ce2ed6/go.mod h1:yssERNPivllc1yU3BvpjYI5BUW+zglcz6QWqeVRL5t0= github.com/zeebo/assert v0.0.0-20181109011804-10f827ce2ed6/go.mod h1:yssERNPivllc1yU3BvpjYI5BUW+zglcz6QWqeVRL5t0=
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
...@@ -51,7 +54,6 @@ github.com/zeebo/blake3 v0.0.4/go.mod h1:YOZo8A49yNqM0X/Y+JmDUZshJWLt1laHsNSn5ny ...@@ -51,7 +54,6 @@ github.com/zeebo/blake3 v0.0.4/go.mod h1:YOZo8A49yNqM0X/Y+JmDUZshJWLt1laHsNSn5ny
github.com/zeebo/pcg v0.0.0-20181207190024-3cdc6b625a05/go.mod h1:Gr+78ptB0MwXxm//LBaEvBiaXY7hXJ6KGe2V32X2F6E= github.com/zeebo/pcg v0.0.0-20181207190024-3cdc6b625a05/go.mod h1:Gr+78ptB0MwXxm//LBaEvBiaXY7hXJ6KGe2V32X2F6E=
gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c= gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c=
gitlab.com/elixxir/crypto v0.0.3/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA= gitlab.com/elixxir/crypto v0.0.3/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA=
gitlab.com/elixxir/crypto v0.0.6 h1:c94CGzBTV7LgInGHfmeJHrqq9nIc/WEOLUd9OeQBN74=
gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg= gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg=
gitlab.com/elixxir/primitives v0.0.0-20200804170709-a1896d262cd9/go.mod h1:p0VelQda72OzoUckr1O+vPW0AiFe0nyKQ6gYcmFSuF8= gitlab.com/elixxir/primitives v0.0.0-20200804170709-a1896d262cd9/go.mod h1:p0VelQda72OzoUckr1O+vPW0AiFe0nyKQ6gYcmFSuF8=
gitlab.com/elixxir/primitives v0.0.0-20200804182913-788f47bded40/go.mod h1:tzdFFvb1ESmuTCOl1z6+yf6oAICDxH2NPUemVgoNLxc= gitlab.com/elixxir/primitives v0.0.0-20200804182913-788f47bded40/go.mod h1:tzdFFvb1ESmuTCOl1z6+yf6oAICDxH2NPUemVgoNLxc=
...@@ -119,8 +121,10 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi ...@@ -119,8 +121,10 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
package ephemeral package ephemeral
import ( import (
"bytes"
"crypto" "crypto"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"github.com/pkg/errors" "github.com/pkg/errors"
"gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id"
"hash"
"io" "io"
"math" "math"
"time" "time"
...@@ -15,6 +17,14 @@ const Period = int64(time.Hour * 24) ...@@ -15,6 +17,14 @@ const Period = int64(time.Hour * 24)
const NumOffsets int64 = 1 << 16 const NumOffsets int64 = 1 << 16
const NsPerOffset = Period / NumOffsets const NsPerOffset = Period / NumOffsets
// Ephemeral Ids reserved for specific actions:
// All zero's denote a dummy ID
// All one's denote a payment
var ReservedIDs = []Id{
{0, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 1, 1, 1, 1, 1, 1},
}
// Ephemeral ID type alias // Ephemeral ID type alias
type Id [8]byte type Id [8]byte
...@@ -144,19 +154,51 @@ func GetIdFromIntermediary(iid []byte, size uint, timestamp int64) (Id, time.Tim ...@@ -144,19 +154,51 @@ func GetIdFromIntermediary(iid []byte, size uint, timestamp int64) (Id, time.Tim
return Id{}, time.Time{}, time.Time{}, errors.New("Cannot generate ID with size > 64") return Id{}, time.Time{}, time.Time{}, errors.New("Cannot generate ID with size > 64")
} }
salt, start, end := getRotationSalt(iid, timestamp) salt, start, end := getRotationSalt(iid, timestamp)
_, err := b2b.Write(iid)
// Continually generate an ephemeral Id until we land on
// an id not within the reserved list of Ids
eid := Id{}
var err error
for reserved := true; reserved; reserved = IsReserved(eid) {
eid, err = getIdFromIntermediaryHelper(b2b, iid, salt, size)
if err != nil { if err != nil {
return Id{}, start, end, err return Id{}, start, end, err
} }
}
return eid, start, end, nil
}
// Helper function which generates a single ephemeral Id
func getIdFromIntermediaryHelper(b2b hash.Hash, iid, salt []byte, size uint) (Id, error) {
eid := Id{}
_, err := b2b.Write(iid)
if err != nil {
return Id{}, err
}
_, err = b2b.Write(salt) _, err = b2b.Write(salt)
if err != nil { if err != nil {
return Id{}, start, end, err return Id{}, err
} }
eid := Id{}
copy(eid[:], b2b.Sum(nil)) copy(eid[:], b2b.Sum(nil))
cleared := eid.Clear(size) cleared := eid.Clear(size)
copy(eid[:], cleared[:]) copy(eid[:], cleared[:])
return eid, start, end, nil
return eid, err
}
// Checks if the Id passed in is among
// the reserved global reserved ID list.
// Returns true if reserved, false if non-reserved
func IsReserved(eid Id) bool {
for _, r := range ReservedIDs {
if bytes.Equal(eid[:], r[:]) {
return true
}
}
return false
} }
// getRotationSalt returns rotation salt based on ID hash and timestamp // getRotationSalt returns rotation salt based on ID hash and timestamp
......
...@@ -2,11 +2,13 @@ package ephemeral ...@@ -2,11 +2,13 @@ package ephemeral
import ( import (
"bytes" "bytes"
"crypto"
"encoding/binary" "encoding/binary"
"gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/crypto/csprng"
"gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id"
_ "golang.org/x/crypto/blake2b" _ "golang.org/x/crypto/blake2b"
"math" "math"
"strconv"
"testing" "testing"
"time" "time"
) )
...@@ -88,6 +90,87 @@ func TestGetIdFromIntermediary(t *testing.T) { ...@@ -88,6 +90,87 @@ func TestGetIdFromIntermediary(t *testing.T) {
} }
} }
// Check that given precomputed input that should generate a reserved
// ephemeral ID, GetIdFromIntermediary does not generate a reserved Id
func TestGetIdFromIntermediary_Reserved(t *testing.T) {
// Hardcoded to ensure a collision with a reserved ID
hardcodedTimestamp := int64(1614199942358373731)
size := uint(4)
testId := id.NewIdFromString(strconv.Itoa(41), id.User, t)
// Intermediary ID expected to generate a reserved ephemeral ID
iid, err := GetIntermediaryId(testId)
if err != nil {
t.Errorf("Failed to get intermediary id: %+v", err)
}
// Generate an ephemeral Id given the input above. This specific
// call does not check if the outputted Id is reserved
salt, _, _ := getRotationSalt(iid, hardcodedTimestamp)
b2b := crypto.BLAKE2b_256.New()
expectedReservedEID, err := getIdFromIntermediaryHelper(b2b, iid, salt, size)
if err != nil {
t.Errorf("Failed to get id from intermediary: %+v", err)
}
// Check that the ephemeral Id generated with hardcoded data is a reserved ID
if !IsReserved(expectedReservedEID) {
t.Errorf("Expected reserved eid is no longer reserved, " +
"\n\tmay need to find a new ID. Use FindReservedID in this case.")
}
// Generate an ephemeral ID which given the same input above with the production facing call
eid, _, _, err := GetIdFromIntermediary(iid, size, hardcodedTimestamp)
if err != nil {
t.Errorf("Failed to get id from intermediary: %+v", err)
}
// Check that the ephemeralID generated is not reserved.
if IsReserved(eid) {
t.Errorf("Ephemeral ID generated should not be reserved!"+
"\n\tReserved IDs: %v"+
"\n\tGenerated ID: %v", ReservedIDs, eid)
}
}
// Will find a reserved ephemeral ID and returns the
// associated intermediary ID
func FindReservedID(size uint, timestamp int64, t *testing.T) []byte {
b2b := crypto.BLAKE2b_256.New()
// Loops through until a reserved ID is found
counter := 0
for {
testId := id.NewIdFromString(strconv.Itoa(counter), id.User, t)
iid, err := GetIntermediaryId(testId)
if err != nil {
t.Errorf("Failed to get intermediary id: %+v", err)
}
// Generate an ephemeral ID
salt, _, _ := getRotationSalt(iid, timestamp)
eid, err := getIdFromIntermediaryHelper(b2b, iid, salt, size)
if err != nil {
t.Errorf("Failed to get id from intermediary: %+v", err)
}
// Check if ephemeral ID is reserved exit
if IsReserved(eid) {
t.Logf("Found input which generates a reserved id. Input as follows."+
"\n\tSize: %d"+
"\n\tTimestamp: %d"+
"\n\tTestID: %v"+
"\n\tTestID generated using the following line of code: "+
"\n\t\ttestId := id.NewIdFromString(strconv.Itoa(%d), id.User, t)",
size, timestamp, testId, counter)
return iid
}
// Increment the counter
counter++
}
}
func TestId_Clear(t *testing.T) { func TestId_Clear(t *testing.T) {
eid := Id{} eid := Id{}
dummyData := []byte{201, 99, 103, 45, 68, 2, 56, 7} dummyData := []byte{201, 99, 103, 45, 68, 2, 56, 7}
......
...@@ -4,34 +4,26 @@ ...@@ -4,34 +4,26 @@
// Use of this source code is governed by a license that can be found in the LICENSE file // // Use of this source code is governed by a license that can be found in the LICENSE file //
//////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////
// Package ndf contains the structure for our network definition file. This object is used by // Package ndf contains the structure for the network definition file. It is
// various users, including our cMix nodes and clients of the xx Messenger, among others. // generated by permissioning and propagates to nodes, gateways, and clients in
// It also includes functions to unmarshal an NDF from a JSON file, separate the signature // the network.
// from the actual NDF content, and serialize the NDF structure into a byte slice
package ndf package ndf
import ( import (
"encoding/base64"
"encoding/json" "encoding/json"
"github.com/pkg/errors" "github.com/pkg/errors"
jww "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman"
"gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id"
"strings"
"time" "time"
) )
// This constant string is to be used by our users that request NDFs from permissioning. // NO_NDF is a string that the permissioning server responds with when a member
// Those that request include cMix nodes, gateways, notification bot and clients. // of the network requests an NDF from it but the NDF is not yet available.
// Permissioning builds and provides the ndf to those that request it. However, depending on
// the status of the cMix network, it might not have the the ndf ready upon request.
// Permissioning in this case tells the requester that it is not ready with an error message.
// The requester checks if the error message contains this string, and thus knows it needs to ask
// again.
const NO_NDF = "Contacted server does not have an ndf to give" const NO_NDF = "Contacted server does not have an ndf to give"
// NetworkDefinition structure matches the JSON structure generated in // NetworkDefinition structure hold connection and network information. It
// Terraform, which allows it to be decoded to Go. // matches the JSON structure generated in Terraform.
type NetworkDefinition struct { type NetworkDefinition struct {
Timestamp time.Time Timestamp time.Time
Gateways []Gateway Gateways []Gateway
...@@ -42,35 +34,39 @@ type NetworkDefinition struct { ...@@ -42,35 +34,39 @@ type NetworkDefinition struct {
E2E Group `json:"E2e"` E2E Group `json:"E2e"`
CMIX Group `json:"Cmix"` CMIX Group `json:"Cmix"`
AddressSpaceSize uint32 AddressSpaceSize uint32
ClientVersion string
} }
// Gateway is the structure for the gateways object in the JSON file. // Gateway contains the connection and identity information of a gateway on the
// network.
type Gateway struct { type Gateway struct {
ID []byte `json:"Id"` ID []byte `json:"Id"`
Address string Address string
TlsCertificate string `json:"Tls_certificate"` TlsCertificate string `json:"Tls_certificate"`
} }
// Node is the structure for the nodes object in the JSON file. // Node contains the connection and identity information of a node on the
// network.
type Node struct { type Node struct {
ID []byte `json:"Id"` ID []byte `json:"Id"`
Address string Address string
TlsCertificate string `json:"Tls_certificate"` TlsCertificate string `json:"Tls_certificate"`
} }
// Registration is the structure for the registration object in the JSON file. // Registration contains the connection information for the permissioning
// server.
type Registration struct { type Registration struct {
Address string Address string
TlsCertificate string `json:"Tls_certificate"` TlsCertificate string `json:"Tls_certificate"`
} }
// Notifications is the structure for the registration object in the JSON file. // Notification contains the connection information for the notification bot.
type Notification struct { type Notification struct {
Address string Address string
TlsCertificate string `json:"Tls_certificate"` TlsCertificate string `json:"Tls_certificate"`
} }
// UDB is the structure for the UDB object in the JSON file. // UDB contains the ID and public key in PEM form for user discovery.
type UDB struct { type UDB struct {
ID []byte `json:"Id"` ID []byte `json:"Id"`
Cert string `json:"Cert"` Cert string `json:"Cert"`
...@@ -78,8 +74,7 @@ type UDB struct { ...@@ -78,8 +74,7 @@ type UDB struct {
DhPubKey []byte `json:"DhPubKey"` DhPubKey []byte `json:"DhPubKey"`
} }
// Group is the structure for a group in the JSON file; it is used for the E2E // Group contains the information used to reconstruct a cyclic group.
// and CMIX objects.
type Group struct { type Group struct {
Prime string Prime string
SmallPrime string `json:"Small_prime"` SmallPrime string `json:"Small_prime"`
...@@ -95,42 +90,29 @@ func (g *Group) String() (string, error) { ...@@ -95,42 +90,29 @@ func (g *Group) String() (string, error) {
return string(data), nil return string(data), nil
} }
// DecodeNDF decodes the given JSON string into the NetworkDefinition structure // Marshal returns the JSON encoding of the NDF.
// and decodes the base 64 signature to a byte slice. The NDF string is expected func (ndf *NetworkDefinition) Marshal() ([]byte, error) {
// to have the JSON data on line 1 and its signature on line 2. Returns an error return json.Marshal(ndf)
// if separating the lines fails or if the JSON unmarshal fails.
func DecodeNDF(ndf string) (*NetworkDefinition, []byte, error) {
// Get JSON data and check if the separating failed
jsonData, signature := separate(ndf)
// Decode the signature form base 64 and check for errors
signatureBytes, err := base64.StdEncoding.DecodeString(signature)
if err != nil {
return nil, nil, err
}
// Unmarshal the JSON string into a structure
networkDefinition := &NetworkDefinition{}
err = json.Unmarshal([]byte(jsonData), networkDefinition)
if err != nil {
return nil, nil, err
} }
return networkDefinition, signatureBytes, nil // Unmarshal parses the JSON encoded data and returns the resulting
// NetworkDefinition.
func Unmarshal(data []byte) (*NetworkDefinition, error) {
ndf := &NetworkDefinition{}
err := json.Unmarshal(data, ndf)
return ndf, err
} }
// Returns a stripped down copy of the NDF object to be used by Clients // StripNdf returns a stripped down copy of the NetworkDefinition to be used by
// Clients.
func (ndf *NetworkDefinition) StripNdf() *NetworkDefinition { func (ndf *NetworkDefinition) StripNdf() *NetworkDefinition {
// Strip down nodes slice of addresses and certs // Remove address and TLS cert for every node.
var strippedNodes []Node var strippedNodes []Node
for _, node := range ndf.Nodes { for _, node := range ndf.Nodes {
newNode := Node{ strippedNodes = append(strippedNodes, Node{ID: node.ID})
ID: node.ID,
}
strippedNodes = append(strippedNodes, newNode)
} }
// Create a new Ndf with the stripped information // Create a new NetworkDefinition with the stripped information
return &NetworkDefinition{ return &NetworkDefinition{
Timestamp: ndf.Timestamp, Timestamp: ndf.Timestamp,
Gateways: ndf.Gateways, Gateways: ndf.Gateways,
...@@ -144,34 +126,9 @@ func (ndf *NetworkDefinition) StripNdf() *NetworkDefinition { ...@@ -144,34 +126,9 @@ func (ndf *NetworkDefinition) StripNdf() *NetworkDefinition {
} }
} }
// separate splits the JSON data from the signature. The NDF string is expected // Serialize serializes the NetworkDefinition into a byte slice.
// to have the JSON data starting on line 1 and its signature on the last line.
// Returns JSON data and signature as separate strings. If the signature is not
// present, it is returned as an empty string.
func separate(ndf string) (string, string) {
var jsonLineEnd int
var signature string
lines := strings.Split(ndf, "\n")
// Determine which line the JSON ends and which line the signature is on
for i := len(lines) - 1; i >= 0; i-- {
line := strings.TrimSpace(lines[i])
if line != "" {
if strings.HasSuffix(line, "}") {
jsonLineEnd = i
break
} else {
signature = line
}
}
}
return strings.Join(lines[0:jsonLineEnd+1], "\n"), signature
}
// Serialize converts the NetworkDefinition into a byte slice.
func (ndf *NetworkDefinition) Serialize() []byte { func (ndf *NetworkDefinition) Serialize() []byte {
b := make([]byte, 0) var b []byte
// Convert timestamp to a byte slice // Convert timestamp to a byte slice
timeBytes, err := ndf.Timestamp.MarshalBinary() timeBytes, err := ndf.Timestamp.MarshalBinary()
...@@ -218,34 +175,12 @@ func (ndf *NetworkDefinition) Serialize() []byte { ...@@ -218,34 +175,12 @@ func (ndf *NetworkDefinition) Serialize() []byte {
return b return b
} }
// Marshal returns a json marshal of the ndf // GetNodeId unmarshalls the Node's ID bytes into an id.ID and returns it.
func (ndf *NetworkDefinition) Marshal() ([]byte, error) {
ndfBytes, err := json.Marshal(ndf)
if err != nil {
return nil, err
}
return ndfBytes, nil
}
// GetNodeId marshals the node id into the ID type. Returns an error if Marshal
// fails.
func (n *Node) GetNodeId() (*id.ID, error) { func (n *Node) GetNodeId() (*id.ID, error) {
newID, err := id.Unmarshal(n.ID) return id.Unmarshal(n.ID)
if err != nil {
return nil, err
}
return newID, nil
}
// GetGatewayId formats the gateway id into the id format specified in the id package of this repo
func (n *Gateway) GetGatewayId() (*id.ID, error) {
newID, err := id.Unmarshal(n.ID)
if err != nil {
return nil, err
} }
return newID, nil // GetGatewayId unmarshalls the Gateway's ID bytes into an id.ID and returns it.
func (g *Gateway) GetGatewayId() (*id.ID, error) {
return id.Unmarshal(g.ID)
} }
This diff is collapsed.
///////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
///////////////////////////////////////////////////////////////////////////////
// Package netTime provides a custom time function that should provide the
// current accurate time used by the network from a custom time service.
package netTime
import (
"time"
)
type NowFunc func() time.Time
// Now returns the current accurate time. The function must be set an accurate
// time service that returns the current time with an accuracy of +/- 300 ms.
var Now NowFunc = time.Now
///////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
///////////////////////////////////////////////////////////////////////////////
package netTime
import (
"testing"
"time"
)
// Happy path: tests that Now() returns time.Now() if it is unset.
func TestNow(t *testing.T) {
expectedTime := time.Now().Round(time.Millisecond)
receivedTime := Now().Round(time.Millisecond)
if !expectedTime.Equal(receivedTime) {
t.Errorf("Returned incorrect time.\nexpected: %s\nreceived: %s",
expectedTime, receivedTime)
}
}
// Happy path: tests that setting Now works.
func TestNow_Set(t *testing.T) {
expectedTime := time.Now()
testNow := func() time.Time {
return expectedTime
}
Now = testNow
now := Now()
if !Now().Equal(expectedTime) {
t.Errorf("Returned incorrect time.\nexpected: %s\nreceived: %s",
expectedTime, now)
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment