Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added prefix for DARC storage #262

Merged
merged 15 commits into from
Aug 14, 2023
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