-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from dedis/proof_12
Adding a proof
- Loading branch information
Showing
11 changed files
with
425 additions
and
80 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.tags |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,41 @@ | ||
package service_test | ||
|
||
import ( | ||
"testing" | ||
|
||
// We need to include the service so it is started. | ||
"gopkg.in/dedis/kyber.v2/suites" | ||
|
||
// We need to include the service so it is started. | ||
"github.com/dedis/student_18_omniledger/omniledger/service" | ||
"github.com/stretchr/testify/require" | ||
"gopkg.in/dedis/cothority.v2" | ||
"gopkg.in/dedis/onet.v2" | ||
) | ||
|
||
var tSuite = suites.MustFind("Ed25519") | ||
|
||
func TestClient_GetProof(t *testing.T) { | ||
l := onet.NewTCPTest(cothority.Suite) | ||
_, roster, _ := l.GenTree(3, true) | ||
defer l.CloseAll() | ||
c := service.NewClient() | ||
csr, err := c.CreateSkipchain(roster, service.Transaction{Key: []byte{1}}) | ||
require.Nil(t, err) | ||
|
||
key := []byte{1, 2, 3, 4} | ||
value := []byte{5, 6, 7, 8} | ||
_, err = c.SetKeyValue(roster, csr.Skipblock.SkipChainID(), | ||
service.Transaction{ | ||
Key: key, | ||
Value: value, | ||
}) | ||
require.Nil(t, err) | ||
|
||
p, err := c.GetProof(roster, csr.Skipblock.SkipChainID(), key) | ||
require.Nil(t, err) | ||
require.Nil(t, p.Proof.Verify(csr.Skipblock)) | ||
k, vs, err := p.Proof.KeyValue() | ||
require.Nil(t, err) | ||
require.Equal(t, k, key) | ||
require.Equal(t, value, vs[0]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package service | ||
|
||
import ( | ||
"bytes" | ||
"errors" | ||
|
||
"github.com/dedis/student_18_omniledger/omniledger/collection" | ||
"gopkg.in/dedis/cothority.v2" | ||
"gopkg.in/dedis/cothority.v2/skipchain" | ||
"gopkg.in/dedis/onet.v2/network" | ||
) | ||
|
||
// Proof represents everything necessary to verify a given | ||
// key/value pair is stored in a skipchain. The proof is in three parts: | ||
// 1. Collection proofs the presence or absence of the key. In case of | ||
// the key being present, the value is included in the proof | ||
// 2. Latest is used to verify the merkle tree root used in the collection-proof | ||
// is stored in the latest skipblock | ||
// 3. Links proves that the latest skipblock is part of the skipchain | ||
// | ||
// This Structure could later be moved to cothority/skipchain. | ||
type Proof struct { | ||
// InclusionProof is the deserialized InclusionProof | ||
InclusionProof collection.Proof | ||
// Providing the latest skipblock to retrieve the Merkle tree root. | ||
Latest skipchain.SkipBlock | ||
// Proving the path to the latest skipblock. | ||
Links []skipchain.ForwardLink | ||
} | ||
|
||
// NewProof creates a proof for key in the skipchain with the given id. It uses | ||
// the collectionDB to look up the key and the skipblockdb to create the correct | ||
// proof for the forward links. | ||
func NewProof(c *collectionDB, s *skipchain.SkipBlockDB, id skipchain.SkipBlockID, | ||
key []byte) (p *Proof, err error) { | ||
p = &Proof{} | ||
p.InclusionProof, err = c.coll.Get(key).Proof() | ||
if err != nil { | ||
return | ||
} | ||
sb := s.GetByID(id) | ||
if sb == nil { | ||
return nil, errors.New("didn't find skipchain") | ||
} | ||
for len(sb.ForwardLink) > 0 { | ||
link := sb.ForwardLink[len(sb.ForwardLink)-1] | ||
p.Links = append(p.Links, *link) | ||
sb = s.GetByID(link.To) | ||
if sb == nil { | ||
return nil, errors.New("missing block in chain") | ||
} | ||
} | ||
p.Latest = *sb | ||
// p.ProofBytes = p.proof.Consistent() | ||
return | ||
} | ||
|
||
// ErrorVerifyCollection is returned if the collection-proof itself | ||
// is not properly set up. | ||
var ErrorVerifyCollection = errors.New("collection inclusion proof is wrong") | ||
|
||
// ErrorVerifyMerkleRoot is returned if the root of the collection | ||
// is different than the stored value in the skipblock. | ||
var ErrorVerifyMerkleRoot = errors.New("root of collection is not in skipblock") | ||
|
||
// ErrorVerifySkipchain is returned if the stored skipblock doesn't | ||
// have a proper proof that it comes from the genesis block. | ||
var ErrorVerifySkipchain = errors.New("stored skipblock is not properly evolved from genesis block") | ||
|
||
// Verify takes a skipchain id and verifies that the proof is valid for this skipchain. | ||
// It verifies the collection-proof, that the merkle-root is stored in the skipblock | ||
// of the proof and the fact that the skipblock is indeed part of the skipchain. | ||
// If all verifications are correct, the error will be nil. | ||
func (p Proof) Verify(genesis *skipchain.SkipBlock) error { | ||
if !p.InclusionProof.Consistent() { | ||
return ErrorVerifyCollection | ||
} | ||
_, d, err := network.Unmarshal(p.Latest.Data, cothority.Suite) | ||
if err != nil { | ||
return err | ||
} | ||
if !bytes.Equal(p.InclusionProof.TreeRootHash(), d.(*Data).MerkleRoot) { | ||
return ErrorVerifyMerkleRoot | ||
} | ||
sbid := genesis.SkipChainID() | ||
publics := genesis.Roster.Publics() | ||
for _, l := range p.Links { | ||
if err = l.Verify(cothority.Suite, publics); err != nil { | ||
return ErrorVerifySkipchain | ||
} | ||
if !l.From.Equal(sbid) { | ||
return ErrorVerifySkipchain | ||
} | ||
sbid = l.To | ||
if l.NewRoster != nil { | ||
publics = l.NewRoster.Publics() | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// KeyValue returns the key and the values stored in the proof. | ||
func (p Proof) KeyValue() (key []byte, values [][]byte, err error) { | ||
key = p.InclusionProof.Key | ||
values, err = p.InclusionProof.RawValues() | ||
return | ||
} |
Oops, something went wrong.