Permalink
Browse files

Adding personhood service

The personhood service is a first example of how to use pop-tokens and pop-coins. For the first two services, we chose a messaging and a questionnaire service.
  • Loading branch information...
ineiti committed Sep 5, 2018
1 parent 268fe15 commit 89f6e29390361335baee3de1d69c28ed7ce23b0b
View
@@ -9,10 +9,10 @@ EXCLUDE_LINT = "should be.*UI|_test.go"
# for more than once in Travis. Change `make test` in .travis.yml
# to `make test_playground`.
test_playground:
cd omniledger/simulation; \
cd personhood; \
for a in $$( seq 100 ); do \
# if DEBUG_TIME=true go test -v -race > log.txt 2>&1; then \
if DEBUG_TIME=true go test -v -race; then \
if DEBUG_TIME=true go test -v -race > log.txt 2>&1; then \
echo Successfully ran \#$$a at $$(date); \
else \
echo Failed at $$(date); \
@@ -4,4 +4,4 @@ if [ ! -f /conode_data/private.toml ]; then
./conode setup --non-interactive
fi
./conode -debug 3 server
./conode -debug 2 server
@@ -29,11 +29,13 @@
class Pair<A, B> {
A a;
B b;
Pair(A a, B b) {
this.a = a;
this.b = b;
}
}
private OmniledgerRPC ol;
private CreateLTSReply ltsReply;
private Darc testDarc;
@@ -103,9 +105,9 @@ void testDecryptKey() throws Exception {
}
Pair<WriteRequest, WriterInstance> createWriterInstance(String secret) throws Exception {
WriteRequest wr = new WriteRequest(secret, 16, genesisDarc.getId());
WriterInstance w = new WriterInstance(ol, Arrays.asList(admin), genesisDarc.getId(), ltsReply, wr);
WriteRequest wr = new WriteRequest(secret, 16, testDarc.getId());
WriterInstance w = new WriterInstance(ol, Arrays.asList(testSigner), testDarc.getId(), ltsReply, wr);
Proof p = ol.getProof(w.getInstance().getId());
assertTrue(p.matches());
View
@@ -152,7 +152,6 @@ func TestIdentity_DataNewCheck(t *testing.T) {
defer l.CloseAll()
c1 := createIdentity(l, services, roster, "one")
data2 := c1.Data.Copy()
kp2 := key.NewKeyPair(tSuite)
data2.Device["two"] = &Device{kp2.Public}
View
@@ -9,58 +9,81 @@ import (
"github.com/dedis/kyber/sign/anon"
"github.com/dedis/kyber/util/key"
"github.com/dedis/onet"
"github.com/dedis/onet/log"
"github.com/dedis/onet/network"
"github.com/dedis/protobuf"
)
// DB-versioning, allows propoer passage from one version to another. This example
// shows how to handle the case where there was no previous versioning in the
// database, and we already have two possible incompatible versions out there,
// version 0a and 0b. Version 1 will be the correct one.
//
// loadVersion starts trying to get version 1, but only if the database returns
// the correct version. If the version is 0 (or nonexistant), then it calls first
// updateFrom0a, if that fails it tries updateFrom0b and if all fails it returns an error.
//
// In case of a future incompatible change, one would have to add `updateFrom1` which
// would call `updateFrom0` if the version < 1. `updateFrom1` would return `storage2`.
// And the `Service` structure would use `storage2` for the up-to-date storage
// version.
const dbVersion = 1
var storageKey = []byte("storage")
var versionKey = []byte("version")
func loadVersion(l onet.ContextDB) (*storage1, error) {
vers, err := l.LoadVersion()
func init() {
network.RegisterMessage(&storage1{})
}
// saves all data.
func (s *Service) save() error {
s.storageMutex.Lock()
defer s.storageMutex.Unlock()
err := s.Save(storageKey, s.Storage)
if err != nil {
log.Error("Couldn't save data:", err)
}
return nil
}
// Tries to load the configuration and updates the data in the service
// if it finds a valid config-file.
func (s *Service) tryLoad() error {
s.Storage = &storage1{}
defer func() {
if s.Storage.Identities == nil {
s.Storage.Identities = make(map[string]*IDBlock)
}
if s.Storage.Auth == nil {
s.Storage.Auth = &authData1{}
}
if len(s.Storage.Auth.Pins) == 0 {
s.Storage.Auth.Pins = map[string]bool{}
}
if len(s.Storage.Auth.Nonces) == 0 {
s.Storage.Auth.Nonces = map[string]bool{}
}
if s.Storage.Auth.Sets == nil {
s.Storage.Auth.Sets = []anonSet1{}
}
if s.Storage.Auth.AdminKeys == nil {
s.Storage.Auth.AdminKeys = []kyber.Point{}
}
}()
ver, err := s.LoadVersion()
if err != nil {
return nil, err
return err
}
if vers < dbVersion {
storage, err := updateFrom0(l, vers)
if ver < dbVersion {
// There are two version 0s...
s.Storage, err = updateFrom0(s, ver)
if err != nil {
return nil, err
return err
}
// TODO: this is really ugly...
if c, ok := l.(*onet.Context); ok {
err = c.Save(storageKey, storage)
if err = s.save(); err != nil {
return err
}
err = l.SaveVersion(dbVersion)
return storage, err
return s.SaveVersion(dbVersion)
}
sInt, err := l.Load(storageKey)
buf, err := s.LoadRaw(storageKey)
if err != nil {
return nil, err
return err
}
if sInt == nil {
return &storage1{}, nil
if len(buf) <= 16 {
return nil
}
return sInt.(*storage1), err
return protobuf.DecodeWithConstructors(buf[16:], s.Storage,
network.DefaultConstructors(cothority.Suite))
}
// storage1 holds the map to the storages so it can be marshaled.
// storage2 holds the map to the storages so it can be marshaled.
type storage1 struct {
Identities map[string]*IDBlock
// The key that is stored in the skipchain service to authenticate
View
@@ -39,7 +39,7 @@ func TestLoadVersion(t *testing.T) {
require.Nil(t, err)
ml.data[string(storageKey)] = s0aBuf
storage, err := loadVersion(ml)
storage, err := updateFrom0(ml, 1)
require.Nil(t, err)
require.True(t, s0a.SkipchainKeyPair.Public.Equal(storage.SkipchainKeyPair.Public))
require.Equal(t, s0a.Identities["abc"].Latest.Threshold,
@@ -68,7 +68,7 @@ func TestLoadVersion(t *testing.T) {
ml.data[string(storageKey)] = s0bBuf
ml.SaveVersion(0)
storage, err = loadVersion(ml)
storage, err = updateFrom0(ml, 1)
require.Nil(t, err)
require.True(t, s0b.SkipchainKeyPair.Public.Equal(storage.SkipchainKeyPair.Public))
require.Equal(t, s0b.Identities["abc"].Latest.Threshold,
View
@@ -686,9 +686,9 @@ func (s *Service) getIdentityStorage(id ID) *IDBlock {
// setIdentityStorage saves an IdentityStorage
func (s *Service) setIdentityStorage(id ID, is *IDBlock) {
s.storageMutex.Lock()
defer s.storageMutex.Unlock()
log.Lvlf3("%s %x %v", s.Context.ServerIdentity(), id[0:8], is.Latest.Device)
s.Storage.Identities[string(id)] = is
s.storageMutex.Unlock()
s.save()
}
@@ -709,52 +709,10 @@ func (s *Service) verifySkipchainAuth() kyber.Scalar {
return nil
}
// saves the actual identity
func (s *Service) save() {
log.Lvl3("Saving service")
err := s.Save(storageKey, s.Storage)
if err != nil {
log.Error("Couldn't save file:", err)
}
}
func (s *Service) clearIdentities() {
s.Storage.Identities = make(map[string]*IDBlock)
}
// Tries to load the configuration and updates if a configuration
// is found, else it returns an error.
func (s *Service) tryLoad() error {
var err error
s.Storage, err = loadVersion(s)
if err != nil {
return err
}
if s.Storage == nil {
s.Storage = &storage1{}
}
if s.Storage.Identities == nil {
s.Storage.Identities = make(map[string]*IDBlock)
}
if s.Storage.Auth == nil {
s.Storage.Auth = &authData1{}
}
if len(s.Storage.Auth.Pins) == 0 {
s.Storage.Auth.Pins = map[string]bool{}
}
if len(s.Storage.Auth.Nonces) == 0 {
s.Storage.Auth.Nonces = map[string]bool{}
}
if s.Storage.Auth.Sets == nil {
s.Storage.Auth.Sets = []anonSet1{}
}
if s.Storage.Auth.AdminKeys == nil {
s.Storage.Auth.AdminKeys = []kyber.Point{}
}
log.Lvl3("Successfully loaded")
return nil
}
func newIdentityService(c *onet.Context) (onet.Service, error) {
s := &Service{
ServiceProcessor: onet.NewServiceProcessor(c),
@@ -101,11 +101,6 @@ func ContractCoin(cdb ol.CollectionView, inst ol.Instruction, c []ol.Coin) (sc [
}
case "transfer":
// transfer sends a given amount of coins to another account.
err = ci.SafeSub(coinsArg)
if err != nil {
return
}
target := inst.Invoke.Args.Search("destination")
var (
v []byte
@@ -125,6 +120,10 @@ func ContractCoin(cdb ol.CollectionView, inst ol.Instruction, c []ol.Coin) (sc [
if err != nil {
return nil, nil, errors.New("couldn't unmarshal target account: " + err.Error())
}
err = ci.SafeSub(coinsArg)
if err != nil {
return
}
err = targetCI.SafeAdd(coinsArg)
if err != nil {
return
@@ -134,7 +133,7 @@ func ContractCoin(cdb ol.CollectionView, inst ol.Instruction, c []ol.Coin) (sc [
return nil, nil, errors.New("couldn't marshal target account: " + err.Error())
}
log.Lvlf3("transferring %d to %x", coinsArg, target)
log.Lvlf1("transferring %d to %x", coinsArg, target)
sc = append(sc, ol.NewStateChange(ol.Update, ol.NewInstanceID(target),
ContractCoinID, targetBuf, did))
case "fetch":
View
@@ -0,0 +1,111 @@
package lib
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/dedis/cothority"
"github.com/dedis/cothority/omniledger/darc"
ol "github.com/dedis/cothority/omniledger/service"
"github.com/dedis/cothority/skipchain"
"github.com/dedis/onet"
"github.com/dedis/onet/network"
"github.com/dedis/protobuf"
)
// ConfigPath points to where the files will be stored by default.
var ConfigPath = "."
// Config is the structure used by ol to save its configuration. It holds everything
// necessary to talk to an omniledger instance. The GenesisDarc and AdminIdentity
// can change over the time of an omniledger.
type Config struct {
Roster onet.Roster
OmniledgerID skipchain.SkipBlockID
GenesisDarc darc.Darc
AdminIdentity darc.Identity
}
// LoadKey returns the signer of a given identity. It searches it in the ConfigPath.
func LoadKey(id darc.Identity) (*darc.Signer, error) {
// Find private key file.
fn := fmt.Sprintf("key-%s.cfg", id)
fn = filepath.Join(ConfigPath, fn)
return LoadSigner(fn)
}
// LoadSigner loads a signer from a file given by fn.
func LoadSigner(fn string) (*darc.Signer, error) {
buf, err := ioutil.ReadFile(fn)
if err != nil {
return nil, err
}
var signer darc.Signer
err = protobuf.DecodeWithConstructors(buf, &signer,
network.DefaultConstructors(cothority.Suite))
return &signer, err
}
// SaveKey stores a signer in a file.
func SaveKey(signer darc.Signer) error {
os.MkdirAll(ConfigPath, 0755)
fn := fmt.Sprintf("key-%s.cfg", signer.Identity())
fn = filepath.Join(ConfigPath, fn)
// perms = 0400 because there is key material inside this file.
f, err := os.OpenFile(fn, os.O_RDWR|os.O_CREATE, 0400)
if err != nil {
return fmt.Errorf("could not write %v: %v", fn, err)
}
buf, err := protobuf.Encode(&signer)
if err != nil {
return err
}
_, err = f.Write(buf)
if err != nil {
return err
}
return f.Close()
}
// SaveConfig stores the config in the ConfigPath directory. It returns the
// pathname of the stored file.
func SaveConfig(cfg Config) (string, error) {
os.MkdirAll(ConfigPath, 0755)
fn := fmt.Sprintf("ol-%x.cfg", cfg.OmniledgerID)
fn = filepath.Join(ConfigPath, fn)
buf, err := protobuf.Encode(&cfg)
if err != nil {
return fn, err
}
err = ioutil.WriteFile(fn, buf, 0644)
if err != nil {
return fn, err
}
return fn, nil
}
// LoadConfig returns a config read from the file and an initialized omniledger
// Client that can be used to communicate with omniledger.
func LoadConfig(file string) (cfg Config, cl *ol.Client, err error) {
var cfgBuf []byte
cfgBuf, err = ioutil.ReadFile(file)
if err != nil {
return
}
err = protobuf.DecodeWithConstructors(cfgBuf, &cfg,
network.DefaultConstructors(cothority.Suite))
if err != nil {
return
}
cl = ol.NewClient(cfg.OmniledgerID, cfg.Roster)
return
}
Oops, something went wrong.

0 comments on commit 89f6e29

Please sign in to comment.