Skip to content

Commit

Permalink
Merge pull request #262 from dedis/access_prefix
Browse files Browse the repository at this point in the history
Added prefix for DARC storage
  • Loading branch information
jbsv authored Aug 14, 2023
2 parents 613ab91 + 02ee68c commit 4bcfa79
Show file tree
Hide file tree
Showing 26 changed files with 369 additions and 144 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ ij_go_wrap_func_params_newline_after_lparen = true
ij_go_wrap_func_params_newline_before_rparen = true
ij_go_wrap_func_result = on_every_item
ij_go_wrap_func_result_newline_after_lparen = true
ij_go_wrap_func_result_newline_before_rparen = true
ij_go_wrap_func_result_newline_before_rparen = true
31 changes: 19 additions & 12 deletions contracts/access/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ import (
)

const (
// ContractUID is the unique (4-bytes) identifier of the contract, it is
// used to prefix keys in the K/V store and by DARCs for access control.
ContractUID = "DARC"

// ContractName is the name of the access contract.
ContractName = "go.dedis.ch/dela.Access"

Expand All @@ -50,9 +54,9 @@ const (
// run on the contract. Should be one of the Command type.
CmdArg = "access:command"

// credentialAllCommand defines the credential command that is allowed to
// CredentialAllCommand defines the credential command that is allowed to
// perform all commands.
credentialAllCommand = "all"
CredentialAllCommand = "all"
)

// Command defines a command for the command contract
Expand All @@ -64,8 +68,8 @@ const (
)

// NewCreds creates new credentials for an access contract execution.
func NewCreds(id []byte) access.Credential {
return access.NewContractCreds(id, ContractName, credentialAllCommand)
func NewCreds() access.Credential {
return access.NewContractCreds([]byte(ContractUID), ContractName, CredentialAllCommand)
}

// RegisterContract registers the access contract to the given execution
Expand All @@ -81,24 +85,20 @@ type Contract struct {
// access is the access service that will be modified.
access access.Service

// accessKey is the credential's ID allowed to use this smart contract
accessKey []byte

store store.Readable
}

// NewContract creates a new access contract
func NewContract(aKey []byte, srvc access.Service, store store.Readable) Contract {
func NewContract(srvc access.Service, store store.Readable) Contract {
return Contract{
access: srvc,
accessKey: aKey,
store: store,
access: srvc,
store: store,
}
}

// Execute implements native.Contract
func (c Contract) Execute(snap store.Snapshot, step execution.Step) error {
creds := NewCreds(c.accessKey)
creds := NewCreds()

err := c.access.Match(c.store, creds, step.Current.GetIdentity())
if err != nil {
Expand All @@ -123,6 +123,13 @@ func (c Contract) Execute(snap store.Snapshot, step execution.Step) error {
return nil
}

// UID returns the unique 4-bytes contract identifier.
//
// - implements native.Contract
func (c Contract) UID() string {
return ContractUID
}

// grant perform the GRANT command
func (c Contract) grant(snap store.Snapshot, step execution.Step) error {
idHex := step.Current.GetArg(GrantIDArg)
Expand Down
8 changes: 4 additions & 4 deletions contracts/access/access_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ import (
)

func TestExecute(t *testing.T) {
contract := NewContract([]byte{}, fakeAccess{err: fake.GetError()}, fakeStore{})
contract := NewContract(fakeAccess{err: fake.GetError()}, fakeStore{})
err := contract.Execute(fakeStore{}, makeStep(t, CmdArg, ""))
require.EqualError(t, err,
"identity not authorized: fake.PublicKey ("+fake.GetError().Error()+")")

contract = NewContract([]byte{}, fakeAccess{}, fakeStore{})
contract = NewContract(fakeAccess{}, fakeStore{})
err = contract.Execute(fakeStore{}, makeStep(t, CmdArg, ""))
require.EqualError(t, err, "'access:command' not found in tx arg")

Expand All @@ -44,7 +44,7 @@ func TestExecute(t *testing.T) {
}

func TestGrant(t *testing.T) {
contract := NewContract([]byte{}, fakeAccess{}, fakeStore{})
contract := NewContract(fakeAccess{}, fakeStore{})
err := contract.grant(fakeStore{}, makeStep(t))
require.EqualError(t, err, "'access:grant_id' not found in tx arg")

Expand Down Expand Up @@ -86,7 +86,7 @@ func TestGrant(t *testing.T) {
IdentityArg, id))
require.NoError(t, err)

contract = NewContract([]byte{}, fakeAccess{err: fake.GetError()}, fakeStore{})
contract = NewContract(fakeAccess{err: fake.GetError()}, fakeStore{})
err = contract.grant(fakeStore{}, makeStep(t, GrantIDArg, "deadbeef",
GrantContractArg, "fake contract",
GrantCommandArg, "fake command",
Expand Down
2 changes: 1 addition & 1 deletion contracts/access/controller/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (a addAction) Execute(ctx node.Context) error {
return xerrors.Errorf("failed to parse identities: %v", err)
}

err = asrv.Grant(accessStore, accessContract.NewCreds(aKey[:]), identities...)
err = asrv.Grant(accessStore, accessContract.NewCreds(), identities...)
if err != nil {
return xerrors.Errorf("failed to grant: %v", err)
}
Expand Down
4 changes: 1 addition & 3 deletions contracts/access/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import (
"golang.org/x/xerrors"
)

var aKey = [32]byte{1}

// newStore is the function used to create the new store. It allows us to create
// a different store in the tests.
var newStore = func(path string) (accessStore, error) {
Expand Down Expand Up @@ -68,7 +66,7 @@ func (m miniController) OnStart(flags cli.Flags, inj node.Injector) error {
return xerrors.Errorf("failed to create access store: %v", err)
}

contract := accessContract.NewContract(aKey[:], access, accessStore)
contract := accessContract.NewContract(access, accessStore)
accessContract.RegisterContract(exec, contract)

inj.Inject(accessStore)
Expand Down
5 changes: 1 addition & 4 deletions contracts/value/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ import (
"golang.org/x/xerrors"
)

// aKey is the access key used for the value contract
var aKey = [32]byte{2}

// miniController is a CLI initializer to register the value contract
//
// - implements node.Initializer
Expand Down Expand Up @@ -41,7 +38,7 @@ func (m miniController) OnStart(flags cli.Flags, inj node.Injector) error {
return xerrors.Errorf("failed to resolve native service: %v", err)
}

contract := value.NewContract(aKey[:], access)
contract := value.NewContract(access)

value.RegisterContract(exec, contract)

Expand Down
57 changes: 29 additions & 28 deletions contracts/value/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"go.dedis.ch/dela/core/execution"
"go.dedis.ch/dela/core/execution/native"
"go.dedis.ch/dela/core/store"
"go.dedis.ch/dela/core/store/prefixed"
"golang.org/x/xerrors"
)

Expand All @@ -26,6 +27,10 @@ type commands interface {
}

const (
// ContractUID is the unique (4-bytes) identifier of the contract, it is
// used to prefix keys in the K/V store and by DARCs for access control.
ContractUID = "VALU"

// ContractName is the name of the contract.
ContractName = "go.dedis.ch/dela.Value"

Expand All @@ -41,12 +46,9 @@ const (
// run on the contract. Should be one of the Command type.
CmdArg = "value:command"

// credentialAllCommand defines the credential command that is allowed to
// CredentialAllCommand defines the credential command that is allowed to
// perform all commands.
credentialAllCommand = "all"

// contractKeyPrefix is used to prefix keys in the K/V store.
contractKeyPrefix = "VALU" // intentionally 4 bytes only, not a typo!
CredentialAllCommand = "all"
)

// Command defines a type of command for the value contract
Expand All @@ -69,8 +71,8 @@ const (

// NewCreds creates new credentials for a value contract execution. We might
// want to use in the future a separate credential for each command.
func NewCreds(id []byte) access.Credential {
return access.NewContractCreds(id, ContractName, credentialAllCommand)
func NewCreds() access.Credential {
return access.NewContractCreds([]byte(ContractUID), ContractName, CredentialAllCommand)
}

// RegisterContract registers the value contract to the given execution service.
Expand All @@ -89,9 +91,6 @@ type Contract struct {
// access is the access control service managing this smart contract
access access.Service

// accessKey is the access identifier allowed to use this smart contract
accessKey []byte

// cmd provides the commands that can be executed by this smart contract
cmd commands

Expand All @@ -100,12 +99,11 @@ type Contract struct {
}

// NewContract creates a new Value contract
func NewContract(aKey []byte, srvc access.Service) Contract {
func NewContract(srvc access.Service) Contract {
contract := Contract{
index: map[string]struct{}{},
access: srvc,
accessKey: aKey,
printer: infoLog{},
index: map[string]struct{}{},
access: srvc,
printer: infoLog{},
}

contract.cmd = valueCommand{Contract: &contract}
Expand All @@ -115,7 +113,7 @@ func NewContract(aKey []byte, srvc access.Service) Contract {

// Execute implements native.Contract. It runs the appropriate command.
func (c Contract) Execute(snap store.Snapshot, step execution.Step) error {
creds := NewCreds(c.accessKey)
creds := NewCreds()

err := c.access.Match(snap, creds, step.Current.GetIdentity())
if err != nil {
Expand All @@ -128,6 +126,8 @@ func (c Contract) Execute(snap store.Snapshot, step execution.Step) error {
return xerrors.Errorf("'%s' not found in tx arg", CmdArg)
}

snap = prefixed.NewSnapshot(ContractUID, snap)

switch Command(cmd) {
case CmdWrite:
err := c.cmd.write(snap, step)
Expand Down Expand Up @@ -156,6 +156,13 @@ func (c Contract) Execute(snap store.Snapshot, step execution.Step) error {
return nil
}

// UID returns the unique 4-bytes contract identifier.
//
// - implements native.Contract
func (c Contract) UID() string {
return ContractUID
}

// valueCommand implements the commands of the value contract
//
// - implements commands
Expand All @@ -175,8 +182,7 @@ func (c valueCommand) write(snap store.Snapshot, step execution.Step) error {
return xerrors.Errorf("'%s' not found in tx arg", ValueArg)
}

snapKey := prefix(key)
err := snap.Set(snapKey, value)
err := snap.Set(key, value)
if err != nil {
return xerrors.Errorf("failed to set value: %v", err)
}
Expand All @@ -185,7 +191,7 @@ func (c valueCommand) write(snap store.Snapshot, step execution.Step) error {

dela.Logger.Info().
Str("contract", ContractName).
Msgf("setting value %x=%s", snapKey, value)
Msgf("setting value %x=%s", key, value)

return nil
}
Expand All @@ -197,7 +203,7 @@ func (c valueCommand) read(snap store.Snapshot, step execution.Step) error {
return xerrors.Errorf("'%s' not found in tx arg", KeyArg)
}

val, err := snap.Get(prefix(key))
val, err := snap.Get(key)
if err != nil {
return xerrors.Errorf("failed to get key '%s': %v", key, err)
}
Expand All @@ -214,8 +220,7 @@ func (c valueCommand) delete(snap store.Snapshot, step execution.Step) error {
return xerrors.Errorf("'%s' not found in tx arg", KeyArg)
}

snapKey := prefix(key)
err := snap.Delete(snapKey)
err := snap.Delete(key)
if err != nil {
return xerrors.Errorf("failed to delete key '%x': %v", key, err)
}
Expand All @@ -224,7 +229,7 @@ func (c valueCommand) delete(snap store.Snapshot, step execution.Step) error {

dela.Logger.Info().
Str("contract", ContractName).
Msgf("deleting value %x", snapKey)
Msgf("deleting value %x", key)

return nil
}
Expand All @@ -234,7 +239,7 @@ func (c valueCommand) list(snap store.Snapshot) error {
res := []string{}

for k := range c.index {
v, err := snap.Get(prefix([]byte(k)))
v, err := snap.Get([]byte(k))
if err != nil {
return xerrors.Errorf("failed to get key '%s': %v", k, err)
}
Expand All @@ -258,7 +263,3 @@ func (h infoLog) Write(p []byte) (int, error) {

return len(p), nil
}

func prefix(key []byte) []byte {
return append([]byte(contractKeyPrefix), key...)
}
Loading

0 comments on commit 4bcfa79

Please sign in to comment.