Skip to content

Commit

Permalink
Byzcoin: implement roster task fingerprint
Browse files Browse the repository at this point in the history
  • Loading branch information
Gilthoniel committed May 12, 2020
1 parent b314715 commit 1b094c6
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 16 deletions.
34 changes: 31 additions & 3 deletions ledger/byzcoin/roster/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,27 @@ func (t clientTask) Fingerprint(w io.Writer, e encoding.ProtoMarshaler) error {
return xerrors.Errorf("couldn't write remove indices: %v", err)
}

// TODO: add
if t.player != nil {
buffer, err = t.player.Address.MarshalText()
if err != nil {
return xerrors.Errorf("couldn't marshal address: %v", err)
}

_, err = w.Write(buffer)
if err != nil {
return xerrors.Errorf("couldn't write address: %v", err)
}

buffer, err = t.player.PublicKey.MarshalBinary()
if err != nil {
return xerrors.Errorf("couldn't marshal public key: %v", err)
}

_, err = w.Write(buffer)
if err != nil {
return xerrors.Errorf("couldn't write public key: %v", err)
}
}

return nil
}
Expand All @@ -135,10 +155,12 @@ type serverTask struct {
encoder encoding.ProtoMarshaler
rosterFactory viewchange.AuthorityFactory
bag *changeSetBag
inventory inventory.Inventory
}

// Consume implements basic.ServerTask. It executes the task and write the
// changes to the page.
// changes to the page. If multiple roster transactions are executed for the
// same page, only the latest will be taken in account.
func (t serverTask) Consume(ctx basic.Context, page inventory.WritablePage) error {
// 1. Access rights control
// TODO: implement
Expand All @@ -151,7 +173,12 @@ func (t serverTask) Consume(ctx basic.Context, page inventory.WritablePage) erro
})

// 3. Update the roster stored in the inventory.
value, err := page.Read(rosterValueKey)
prev, err := t.inventory.GetPage(page.GetIndex() - 1)
if err != nil {
return xerrors.Errorf("couldn't get previous page: %v", err)
}

value, err := prev.Read(rosterValueKey)
if err != nil {
return xerrors.Errorf("couldn't read roster: %v", err)
}
Expand Down Expand Up @@ -281,6 +308,7 @@ func (f TaskManager) FromProto(in proto.Message) (basic.ServerTask, error) {
encoder: f.encoder,
rosterFactory: f.rosterFactory,
bag: f.bag,
inventory: f.inventory,
}
return task, nil
}
Expand Down
54 changes: 41 additions & 13 deletions ledger/byzcoin/roster/task_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ func TestClientTask_Pack(t *testing.T) {
}

func TestClientTask_Fingerprint(t *testing.T) {
// Client task with indices to remove.
task := NewRemove([]uint32{0x02, 0x01, 0x03})

buffer := new(bytes.Buffer)
Expand All @@ -62,40 +63,67 @@ func TestClientTask_Fingerprint(t *testing.T) {

err = task.Fingerprint(fake.NewBadHash(), nil)
require.EqualError(t, err, "couldn't write remove indices: fake error")

// Client task with a player to add.
task = NewAdd(fake.NewAddress(5), fake.PublicKey{})

buffer = new(bytes.Buffer)

err = task.Fingerprint(buffer, nil)
require.NoError(t, err)
require.Equal(t, "\x05\x00\x00\x00\xdf", buffer.String())

err = task.Fingerprint(fake.NewBadHashWithDelay(1), nil)
require.EqualError(t, err, "couldn't write address: fake error")

err = task.Fingerprint(fake.NewBadHashWithDelay(2), nil)
require.EqualError(t, err, "couldn't write public key: fake error")

task = NewAdd(fake.NewBadAddress(), fake.PublicKey{})
err = task.Fingerprint(buffer, nil)
require.EqualError(t, err, "couldn't marshal address: fake error")

task = NewAdd(fake.NewAddress(0), fake.NewBadPublicKey())
err = task.Fingerprint(buffer, nil)
require.EqualError(t, err, "couldn't marshal public key: fake error")
}

func TestServerTask_Consume(t *testing.T) {
roster := rosterFactory{}.New(fake.NewAuthority(3, fake.NewSigner))
rosterpb, err := roster.Pack(encoding.NewProtoEncoder())
require.NoError(t, err)

task := serverTask{
clientTask: clientTask{remove: []uint32{2}},
rosterFactory: NewRosterFactory(fake.AddressFactory{}, fake.PublicKeyFactory{}),
encoder: encoding.NewProtoEncoder(),
bag: &changeSetBag{},
inventory: fakeInventory{value: rosterpb},
}

roster := task.rosterFactory.New(fake.NewAuthority(3, fake.NewSigner))
rosterpb, err := roster.Pack(task.encoder)
require.NoError(t, err)

values := map[string]proto.Message{
RosterValueKey: rosterpb,
}

err = task.Consume(nil, fakePage{values: values})
err = task.Consume(nil, fakePage{values: map[string]proto.Message{}})
require.NoError(t, err)
require.Len(t, task.bag.store, 1)

err = task.Consume(nil, fakePage{errRead: xerrors.New("oops")})
task.inventory = fakeInventory{err: xerrors.New("oops")}
err = task.Consume(nil, fakePage{})
require.EqualError(t, err, "couldn't get previous page: oops")

task.inventory = fakeInventory{errPage: xerrors.New("oops")}
err = task.Consume(nil, fakePage{})
require.EqualError(t, err, "couldn't read roster: oops")

err = task.Consume(nil, fakePage{values: map[string]proto.Message{}})
task.inventory = fakeInventory{value: nil}
err = task.Consume(nil, fakePage{})
require.EqualError(t, err, "couldn't decode roster: invalid message type '<nil>'")

task.inventory = fakeInventory{value: rosterpb}
task.encoder = fake.BadPackEncoder{}
err = task.Consume(nil, fakePage{values: values})
err = task.Consume(nil, fakePage{})
require.EqualError(t, err, "couldn't encode roster: fake error")

task.encoder = encoding.NewProtoEncoder()
err = task.Consume(nil, fakePage{values: values, errWrite: xerrors.New("oops")})
err = task.Consume(nil, fakePage{errWrite: xerrors.New("oops")})
require.EqualError(t, err, "couldn't write roster: oops")
}

Expand Down

0 comments on commit 1b094c6

Please sign in to comment.