Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 15 additions & 18 deletions merkletree/pad.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type PAD struct {

// NewPAD creates new PAD consisting of an array of hash chain
// indexed by the epoch and its maximum length is len
func NewPAD(policies Policies, signKey sign.PrivateKey, len uint64) (*PAD, error) {
func NewPAD(policies *Policies, signKey sign.PrivateKey, len uint64) (*PAD, error) {
if policies == nil {
panic(ErrorNilPolicies)
}
Expand All @@ -37,15 +37,14 @@ func NewPAD(policies Policies, signKey sign.PrivateKey, len uint64) (*PAD, error
if err != nil {
return nil, err
}
pad.policies = policies
pad.policies = *policies
pad.snapshots = make(map[uint64]*SignedTreeRoot, len)
pad.loadedEpochs = make([]uint64, 0, len)
pad.updateInternal(nil, 0)
return pad, nil
}

// if policies is nil, the previous policies will be used
func (pad *PAD) signTreeRoot(m *MerkleTree, epoch uint64) {
func (pad *PAD) signTreeRoot(epoch uint64) {
var prevHash []byte
if pad.latestSTR == nil {
var err error
Expand All @@ -57,30 +56,29 @@ func (pad *PAD) signTreeRoot(m *MerkleTree, epoch uint64) {
} else {
prevHash = crypto.Digest(pad.latestSTR.Signature)
}
pad.tree.recomputeHash()
m := pad.tree.Clone()
pad.latestSTR = NewSTR(pad.signKey, pad.policies, m, epoch, prevHash)
}

func (pad *PAD) updateInternal(policies Policies, epoch uint64) {
pad.tree.recomputeHash()
m := pad.tree.Clone()
func (pad *PAD) updateInternal(policies *Policies, epoch uint64) {
// create STR with the policies that were actually used in the prev.
// Set() operation
pad.signTreeRoot(m, epoch)
pad.signTreeRoot(epoch)
pad.snapshots[epoch] = pad.latestSTR
pad.loadedEpochs = append(pad.loadedEpochs, epoch)

if policies != nil { // update the policies if necessary
vrfKeyChanged := 1 != subtle.ConstantTimeCompare(
pad.policies.vrfPrivate(),
policies.vrfPrivate())
pad.policies = policies
pad.policies.vrfPrivateKey,
policies.vrfPrivateKey)
pad.policies = *policies
if vrfKeyChanged {
pad.reshuffle()
}
}
}

func (pad *PAD) Update(policies Policies) {
func (pad *PAD) Update(policies *Policies) {
// delete older str(s) as needed
if len(pad.loadedEpochs) == cap(pad.loadedEpochs) {
n := cap(pad.loadedEpochs) / 2
Expand All @@ -89,12 +87,11 @@ func (pad *PAD) Update(policies Policies) {
}
pad.loadedEpochs = append(pad.loadedEpochs[:0], pad.loadedEpochs[n:]...)
}

pad.updateInternal(policies, pad.latestSTR.Epoch+1)
}

func (pad *PAD) Set(name string, value []byte) error {
index, _ := pad.computePrivateIndex(name, pad.policies.vrfPrivate())
index, _ := pad.computePrivateIndex(name, pad.policies.vrfPrivateKey)
return pad.tree.Set(index, name, value)
}

Expand All @@ -107,7 +104,7 @@ func (pad *PAD) LookupInEpoch(name string, epoch uint64) (*AuthenticationPath, e
if str == nil {
return nil, ErrorSTRNotFound
}
lookupIndex, proof := pad.computePrivateIndex(name, str.Policies.vrfPrivate())
lookupIndex, proof := pad.computePrivateIndex(name, str.Policies.vrfPrivateKey)
ap := str.tree.Get(lookupIndex)
ap.VrfProof = proof
return ap, nil
Expand All @@ -125,7 +122,7 @@ func (pad *PAD) LatestSTR() *SignedTreeRoot {
}

func (pad *PAD) TB(name string, value []byte) (*TemporaryBinding, error) {
index, _ := pad.computePrivateIndex(name, pad.policies.vrfPrivate())
index, _ := pad.computePrivateIndex(name, pad.policies.vrfPrivateKey)
tb := NewTB(pad.signKey, pad.latestSTR.Signature, index, value)
err := pad.tree.Set(index, name, value)
return tb, err
Expand All @@ -142,7 +139,7 @@ func (pad *PAD) reshuffle() {
panic(err)
}
pad.tree.visitLeafNodes(func(n *userLeafNode) {
newIndex, _ := pad.computePrivateIndex(n.key, pad.policies.vrfPrivate())
newIndex, _ := pad.computePrivateIndex(n.key, pad.policies.vrfPrivateKey)
if err := newTree.Set(newIndex, n.key, n.value); err != nil {
panic(err)
}
Expand Down
34 changes: 7 additions & 27 deletions merkletree/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,55 +8,35 @@ import (

type TimeStamp uint64

type Policies interface {
EpDeadline() TimeStamp
Serialize() []byte
vrfPrivate() vrf.PrivateKey
}

type ConiksPolicies struct {
type Policies struct {
LibVersion string
HashID string
vrfPrivateKey vrf.PrivateKey
VrfPubKey []byte
VrfPublicKey vrf.PublicKey
EpochDeadline TimeStamp
}

var _ Policies = (*ConiksPolicies)(nil)

func NewPolicies(epDeadline TimeStamp, vrfPrivKey vrf.PrivateKey) Policies {
func NewPolicies(epDeadline TimeStamp, vrfPrivKey vrf.PrivateKey) *Policies {
vrfPublicKey, ok := vrfPrivKey.Public()
if !ok {
panic(vrf.ErrorGetPubKey)
}
return &ConiksPolicies{
return &Policies{
LibVersion: Version,
HashID: crypto.HashID,
vrfPrivateKey: vrfPrivKey,
VrfPubKey: vrfPublicKey,
VrfPublicKey: vrfPublicKey,
EpochDeadline: epDeadline,
}
}

// Serialize encodes the policy to a byte array with the following format:
// [lib version, cryptographic algorithm in use, epoch deadline, vrf public key]
func (p *ConiksPolicies) Serialize() []byte {
vrfPublicKey, ok := p.vrfPrivateKey.Public()
if !ok {
panic(vrf.ErrorGetPubKey)
}
func (p *Policies) Serialize() []byte {
var bs []byte
bs = append(bs, []byte(p.LibVersion)...) // lib Version
bs = append(bs, []byte(p.HashID)...) // cryptographic algorithms in use
bs = append(bs, util.ULongToBytes(uint64(p.EpochDeadline))...) // epoch deadline
bs = append(bs, vrfPublicKey...) // vrf public key
bs = append(bs, p.VrfPublicKey...) // vrf public key
return bs
}

func (p *ConiksPolicies) vrfPrivate() vrf.PrivateKey {
return p.vrfPrivateKey
}

func (p *ConiksPolicies) EpDeadline() TimeStamp {
return p.EpochDeadline
}
4 changes: 2 additions & 2 deletions protocol/directory.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type ConiksDirectory struct {
pad *merkletree.PAD
useTBs bool
tbs map[string]*merkletree.TemporaryBinding
policies merkletree.Policies
policies *merkletree.Policies
}

func InitDirectory(epDeadline merkletree.TimeStamp, vrfKey vrf.PrivateKey,
Expand Down Expand Up @@ -44,7 +44,7 @@ func (d *ConiksDirectory) SetPolicies(epDeadline merkletree.TimeStamp, vrfKey vr
}

func (d *ConiksDirectory) EpochDeadline() merkletree.TimeStamp {
return d.pad.LatestSTR().Policies.EpDeadline()
return d.pad.LatestSTR().Policies.EpochDeadline
}

func (d *ConiksDirectory) LatestSTR() *merkletree.SignedTreeRoot {
Expand Down
31 changes: 31 additions & 0 deletions protocol/directory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,3 +316,34 @@ func TestHandleOps(t *testing.T) {
t.Fatal("Expect error", ErrorMalformedClientMessage, "got", err)
}
}

func TestPoliciesChanges(t *testing.T) {
d := newDirectory(t, false)
if p := d.LatestSTR().Policies.EpochDeadline; p != 1 {
t.Fatal("Unexpected policies", "want", 1, "got", p)
}

// change the policies
vrfKey, err := vrf.GenerateKey(nil)
if err != nil {
t.Fatal(err)
}
d.SetPolicies(2, vrfKey)
d.Update()
// expect the policies doesn't change yet
if p := d.LatestSTR().Policies.EpochDeadline; p != 1 {
t.Fatal("Unexpected policies", "want", 1, "got", p)
}

d.Update()
// expect the new policies
if p := d.LatestSTR().Policies.EpochDeadline; p != 2 {
t.Fatal("Unexpected policies", "want", 2, "got", p)
}
p0 := d.pad.GetSTR(0).Policies.EpochDeadline
p1 := d.pad.GetSTR(1).Policies.EpochDeadline
p2 := d.pad.GetSTR(2).Policies.EpochDeadline
if p0 != 1 || p1 != 1 || p2 != 2 {
t.Fatal("Maybe the STR's policies were malformed")
}
}