Value Store API Reference
A comprehensive reference guide to the complete value store API.
Overview
Here is the list of all methods used in the value store API.
Generate Stubs
memo exposes a gRPC API, offering a portable and language-agnostic channel of interaction. gRPC relies on Protocol Buffers (protobuf) to serialize the remote procedure calls' (RPC) messages. The protocol format and the list of RPCs is described in a simple .proto
file.
As a client, you need to download memo's official memo_vs.proto
file for interacting with the key-value store API. You then have to generate the package/module/header/class (depending on the language or your choice) that will provide you with functions to easily call the RPCs.
NOTE: In C++, you will need to build the gRPC plugin for protoc
. A clear procedure is given by the gRPC website.
$ go get -u github.com/golang/protobuf/protoc-gen-go
$ export KVS_PROTO_OUT=$GOPATH/src/google.golang.org/grpc/memo/kvs
$ mkdir -p $KVS_PROTO_OUT
$ protoc --proto_path=$HOME/Downloads --go_out=plugins=grpc:$KVS_PROTO_OUT $HOME/Downloads/memo_vs.proto
$ ls $KVS_PROTO_OUT
memo_vs.pb.go
$ export KVS_PROTO_OUT=$HOME/projects/memo/src
$ mkdir -p $KVS_PROTO_OUT
$ protoc --proto_path=$HOME/Downloads --cpp_out=$KVS_PROTO_OUT --plugin=protoc-gen-grpc=$(whereis grpc_cpp_plugin) --grpc_out=$KVS_PROTO_OUT $HOME/Downloads/memo_vs.proto
$ ls -lx $KVS_PROTO_OUT
memo_vs.grpc.pb.cc memo_vs.grpc.pb.h memo_vs.pb.cc memo_vs.pb.h
$ python3 -m pip install grpcio grpcio-tools
$ export KVS_PROTO_OUT=$HOME/projects/memo/src
$ mkdir -p $KVS_PROTO_OUT
$ python3 -m grpc_tools.protoc --proto_path=$HOME/Downloads --python_out=$KVS_PROTO_OUT --grpc_python_out=$KVS_PROTO_OUT $HOME/Downloads/memo_vs.proto
$ ls -lx $KVS_PROTO_OUT
memo_vs_pb2_grpc.py memo_vs_pb2.py
Deploy memo
To deploy a memo value store exposing a gRPC interface, please follow our "getting started with memo" guide.
Methods
MakeImmutableBlock(MakeImmutableBlockRequest) → Block
|
Ask for a brand new block, representing an ImmutableBlock.
The address of an ImmutableBlock is based on its owner public key and the payload of the block, given by the MakeImmutableBlockRequest. N.B. The Block is not pushed yet.
|
# Create the immutable block.
block = vs.MakeImmutableBlock(
MakeImmutableBlockRequest(data = b'some data'))
# Actually insert the block.
vs.Insert(InsertRequest(block = block))
// Create the immutable block with a payload.
iblock, _ := client.MakeImmutableBlock(
context.Background(),
&vs.MakeImmutableBlockRequest{Data: []byte("some data")})
// Actually insert the block.
client.Insert(context.Background(), &vs.InsertRequest{Block: iblock})
// Create an immutable block creation request.
::memo::vs::MakeImmutableBlockRequest make_block;
// Set the payload.
make_block.set_data("some data");
// Create an empty block.
::memo::vs::Block block;
{
// Create a context.
grpc::ClientContext ctx;
// Construct the immutable block and store it in `block`.
auto status = vs->MakeImmutableBlock(&ctx, make_block, &block);
if (!status.ok())
throw std::runtime_error("Cannot make immutable block");
}
// Create a insertion response.
::memo::vs::InsertResponse insertion;
{
// Create a context.
grpc::ClientContext ctx;
// Create an insertion request.
::memo::vs::InsertRequest insert;
// Set the block to the insertion request using the setter.
//
// N.B. `mutable_block` is to access to a mutable version of the attribute
// `block`. It's not correlated with MutableBlock or ImmutableBlock.
insert.mutable_block()->CopyFrom(block);
// Actually insert the block.
auto status = vs->Insert(&ctx, insert, &insertion);
if (!status.ok())
throw std::runtime_error("Cannot insert block");
}
|
Arguments
MakeImmutableBlockRequest
{
bytes
data,
bytes
owner }
|
bytes |
data |
bytes |
owner |
|
Return
Block
{
string
type,
bytes
address,
oneof
payload,
bytes
salt,
bytes
owner...
see all
|
string |
type |
bytes |
address |
oneof |
payload
— bytes data
— bytes data_plain
|
bytes |
salt |
bytes |
owner |
bytes |
signature |
bytes |
owner_rsa |
bytes |
name |
Key |
key_koh |
int64 |
version |
int64 |
editor |
bytes |
owner_token |
repeated ACLEntry |
acl |
int64 |
data_version |
bytes |
data_signature |
bool |
world_readable |
bool |
world_writable |
repeated ACLEntry |
group_acl |
repeated int64 |
group_version |
bool |
deleted |
Version |
seal_version |
int64 |
next_seal_version |
|
MakeMutableBlock(MakeMutableBlockRequest) → Block
|
Ask for a brand new Block, representing a MutableBlock.
The address is chosen randomly by the key-value store. Hence, the MakeMutableBlockRequest has no attributes. N.B. The Block is not pushed yet.
|
# Create the block, empty.
block = vs.MakeMutableBlock(MakeMutableBlockRequest())
# Set the block payload.
block.data_plain = b'some data'
# Actually insert the block.
vs.Insert(InsertRequest(block = block))
// Create the block, empty.
mblock, _ := client.MakeMutableBlock(context.Background(),
&vs.MakeMutableBlockRequest{})
// Create a payload.
payload := []byte("some data")
// Set the block payload.
mblock.Payload = &vs.Block_DataPlain{payload}
// Actually insert the block.
client.Insert(context.Background(),
&vs.InsertRequest{Block: mblock})
// Create an insertion request.
::memo::vs::InsertRequest insert;
// Create a mutable block creation request.
::memo::vs::MakeMutableBlockRequest empty;
// Construction.
{
// Set a context.
grpc::ClientContext ctx;
// Create the mutable block and store the result in the insertion request
// field.
//
// N.B. `mutable_` is to access to a mutable version of the attribute
// `block`. It's not correlated with MutableBlock or ImmutableBlock.
auto status = vs->MakeMutableBlock(&ctx, empty, insert.mutable_block());
if (!status.ok())
throw std::runtime_error("Cannot make mutable block");
// Set the payload.
insert.mutable_block()->set_data_plain("some data");
}
{
// Create an insertion response.
::memo::vs::InsertResponse insertion;
// Set a context.
grpc::ClientContext ctx;
// Actually insert the block.
auto status = vs->Insert(&ctx, insert, &insertion);
if (!status.ok())
throw std::runtime_error("Cannot insert block");
}
|
Arguments
MakeMutableBlockRequest
{
}
|
|
Return
Block
{
string
type,
bytes
address,
oneof
payload,
bytes
salt,
bytes
owner...
see all
|
string |
type |
bytes |
address |
oneof |
payload
— bytes data
— bytes data_plain
|
bytes |
salt |
bytes |
owner |
bytes |
signature |
bytes |
owner_rsa |
bytes |
name |
Key |
key_koh |
int64 |
version |
int64 |
editor |
bytes |
owner_token |
repeated ACLEntry |
acl |
int64 |
data_version |
bytes |
data_signature |
bool |
world_readable |
bool |
world_writable |
repeated ACLEntry |
group_acl |
repeated int64 |
group_version |
bool |
deleted |
Version |
seal_version |
int64 |
next_seal_version |
|
Fetch(FetchRequest) → FetchResponse
|
Fetch the block at given address.
|
# Fetch a block at the address given by `address`.
block = vs.Fetch(FetchRequest(address = address)).block
// Fetch a block at the address given by `address`.
res, _ := client.Fetch(context.Background(), &vs.FetchRequest{Address: address})
block := res.Block
// Create a fetch response.
::memo::vs::FetchResponse res;
// Create a context.
grpc::ClientContext ctx;
// Create a fetch request.
::memo::vs::FetchRequest fetch;
// Set the address to fetch request.
fetch.set_address(address);
// Actually fetch the block.
{
auto status = vs->Fetch(&ctx, fetch, &res);
if (!status.ok())
throw std::runtime_error("Unable to fetch block");
}
// Retrieve the block.
auto block = res.block();
|
Arguments
FetchRequest
{
bytes
address,
bool
decrypt_data }
|
bytes |
address |
bool |
decrypt_data |
|
Return
FetchResponse
{
string
type,
Block
block }
|
|
Exceptions
|
INVALID_ARGUMENT : The address format is invalid.
|
NOT_FOUND : Nothing at the given address.
|
|
Insert(InsertRequest) → InsertResponse
|
Insert a new Block.
The Block to insert is given by the InsertRequest. The Block should have been created by using Make<...>Block. Insert returns an InsertResponse, containing the information related to the Insertion.
|
# Given a block `block`, insert the block.
vs.Insert(InsertRequest(block = block))
// Given a block `block`, insert the block.
//
client.Insert(context.Background(),
&vs.InsertRequest{Block: block})
// XXX: wrong.
//
// Depending on the type of block (mutable or immutable), insertion differs.
//
// Given a mutable block `mblock`, insert the mutable block.
{
// Create an insert response.
::memo::vs::InsertResponse insertion;
// Create a context.
grpc::ClientContext ctx;
// Create an insertion request.
::memo::vs::InsertRequest insert;
// Set the block to the insertion request using the setter.
//
// N.B. `mutable_block` is to access to a mutable version of the attribute
// `block`. It's not correlated with MutableBlock or ImmutableBlock.
insert.mutable_block()->set_data_plain("some data");
// Actually insert the block.
auto status = vs->Insert(&ctx, insert, &insertion);
if (!status.ok())
throw std::runtime_error("Cannot insert block");
}
// Given a immutable block with a payload already set, insert a immutable block.
{
// Create an insert response.
::memo::vs::InsertResponse insertion;
// Create a context.
grpc::ClientContext ctx;
// Create an insertion request.
::memo::vs::InsertRequest insert;
// Set the block to the insertion request using the setter.
//
// N.B. `mutable_block` is to access to a mutable version of the attribute
// `block`. It's not correlated with MutableBlock or ImmutableBlock.
insert.mutable_block()->CopyFrom(block);
// Actually insert the block.
auto status = vs->Insert(&ctx, insert, &insertion);
if (!status.ok())
throw std::runtime_error("Cannot insert block");
}
|
Arguments
InsertRequest
{
Block
block }
|
Block |
block |
|
Return
InsertResponse
{
string
type,
bool
bool }
|
|
Exceptions
|
NOT_FOUND : Nothing at the given address.
|
INTERNAL : See message but can be: collision, etc.
|
|
Update(UpdateRequest) → UpdateResponse
|
Update an existing block.
The address and the new content of the Block are given by the UpdateRequest. Update doesn't perform an upsert, hence, the update will fail if the block doesn't exist, but also you are not allowed to update it. The UpdateResponse will contain the information related to the result of the insertion attempt.
|
# Given a block `block` and a payload `payload`.
#
# Set the block new payload.
block.data_plain = payload
# Perform the update.
#
# Setting the update request `decrypt_data` field to `True` so the `block`
# field of the update response will be decrypted. This is useful if you need
# to fix potential conflicts resulting of the update.
response = vs.Update(UpdateRequest(block = block,
decrypt_data = True))
if response.current:
# Solve conflict here, `response.current` contains the current version of
# the block in the value-store.
pass
// Given a block `block` and a payload `payload`.
//
// Set the block new payload.
block.Payload = &vs.Block_DataPlain{payload}
// Perform the update.
//
// Setting the update request `DecryptData` field to `true` so the `Block`
// field of the update response will be decrypted. This is useful if you need
// to fix potential conflicts resulting of the update.
status, _ := client.Update(context.Background(),
&vs.UpdateRequest{Block: block,
DecryptData: true})
// If there is a conflict.
if (status.GetCurrent() != nil) {
// Solve conflict here, `response.block` contains the current version of
// the block in the value-store.
}
// Given a block `block` and a payload `payload`.
//
// Create an update response.
::memo::vs::UpdateResponse response;
// Set the block new payload.
block.set_data_plain(payload);
{
// Create a context.
grpc::ClientContext ctx;
// Create an update request.
::memo::vs::UpdateRequest update;
// Set the update request `block` field with the updated version of the block.
update.mutable_block()->CopyFrom(block);
// Set the update request `decrypt_data` field to `true` so the `block` field
// of the update response will be decrypted. This is useful if you need to fix
// potential conflicts resulting of the update.
update.set_decrypt_data(true);
// Actually update the block.
auto status = vs->Update(&ctx, update, &response);
if (!status.ok())
throw std::runtime_error("Unable to update the block");
// If there is a conflict.
if (response.has_current())
{
// Solve conflict here, `response.block` contains the current version of
// the block in the value-store.
}
}
|
Arguments
UpdateRequest
{
Block
block,
bool
decrypt_data }
|
Block |
block |
bool |
decrypt_data |
|
Return
UpdateResponse
{
string
type,
bytes
message,
Block
current,
bool
bool }
|
string |
type |
bytes |
message |
Block |
current |
bool |
bool |
|
Exceptions
|
NOT_FOUND : Nothing at the given address.
|
|
Delete(DeleteRequest) → DeleteResponse
|
Erase the block at the given address.
The address of the Block is given by the DeleteRequest. The ability to remove a Block is determined by two factors: The existence of the Block and the permission to delete it. The DeleteResponse will contain the information related to result of the deletion attempt.
|
# Given an address `address`, remove the block at `address`.
#
vs.Delete(DeleteRequest(address = address))
// Given an address `address`, remove the block at `address`.
//
_, err := client.Delete(context.Background(),
&vs.DeleteRequest{Address: address})
if err != nil {
log.Fatal("Unable to remove block")
}
// Given an address `address`, remove the block at `address`.
// Create a remove request.
::memo::vs::DeleteRequest remove;
// Create a remove status.
::memo::vs::DeleteResponse removal;
// Set the address.
remove.set_address(address);
// Create a context.
grpc::ClientContext ctx;
// Actually remove the block.
auto status = vs->Delete(&ctx, remove, &removal);
if (!status.ok())
throw std::runtime_error("Cannot remove block");
|
Arguments
DeleteRequest
{
bytes
address }
|
bytes |
address |
|
Return
DeleteResponse
{
string
type,
bool
bool }
|
|
Exceptions
|
NOT_FOUND : Nothing at the given address.
|
|
Messages
MakeMutableBlockRequest
|
index |
name |
type |
abstract |
MakeImmutableBlockRequest
|
index |
name |
type |
abstract |
1 |
data |
bytes |
The payload of the ImmutableBlock |
2 |
owner |
bytes |
The address of the owner block |
InsertRequest
|
index |
name |
type |
abstract |
1 |
block |
Block |
The block to insert |
UpdateRequest
|
index |
name |
type |
abstract |
1 |
block |
Block |
The new value of the block |
2 |
decrypt_data |
bool |
Whether to decrypt data automatically |
FetchRequest
|
index |
name |
type |
abstract |
1 |
address |
bytes |
The address of the Block to fetch |
2 |
decrypt_data |
bool |
Whether to decrypt data automatically |
DeleteRequest
|
index |
name |
type |
abstract |
1 |
address |
bytes |
The address of the Block to remove |
Version
|
index |
name |
type |
abstract |
1 |
major |
int64 |
The major |
2 |
minor |
int64 |
The minor |
3 |
subminor |
int64 |
The subminor |
ACLEntry
|
index |
name |
type |
abstract |
1 |
key_koh |
Key |
The key public to manage permissions of |
2 |
read |
bool |
Whether read permission is granted |
3 |
write |
bool |
Whether write permission is granted |
4 |
token |
bytes |
Token, containing the secret to read encrypted data |
PublicKey
|
index |
name |
type |
abstract |
1 |
rsa |
bytes |
The DER representation of the PublicKey (RSA) |
Key
|
index |
name |
type |
abstract |
1 |
type |
string |
[internal] |
2 |
public_key |
PublicKey |
A public key, used for |
Block
|
index |
name |
type |
abstract |
1 |
type |
string |
The type of Block |
2 |
address |
bytes |
The address of the Block |
payload |
| oneof |
The payload of the block, data or data_plain, depeding of the Block |
3 |
data |
bytes |
The raw data of the block (N.B. This can be encrypted) |
22 |
data_plain |
bytes |
The decyphered data payload of the block |
4 |
salt |
bytes |
A constant salt, used when computing the address of the block |
5 |
owner |
bytes |
The representation of the owner public key |
6 |
signature |
bytes |
The signature of the block content. The signature proves the integrity of the block by ensuring data have been signed using the owner private key |
7 |
owner_rsa |
bytes |
[internal] |
8 |
name |
bytes |
The name of the block |
9 |
key_koh |
Key |
A Key object, that can be a hash, used to the find the a User Block (UB) or the public key of the owner of the Block |
10 |
version |
int64 |
The version of the Block |
11 |
editor |
int64 |
The index of the editor in the `acl` or `acl_group` to check permissions |
12 |
owner_token |
bytes |
A token, containing the secret used encipher the data |
13 |
acl |
repeated ACLEntry |
The list of ACL entries (one for each user referenced in the ACB) |
14 |
data_version |
int64 |
The version of the data |
15 |
data_signature |
bytes |
The signature of the data |
16 |
world_readable |
bool |
Whether the Block is readable by everybody |
17 |
world_writable |
bool |
Whether the Block is writable by everybody |
18 |
group_acl |
repeated ACLEntry |
A list of ACL entries (one for each group referenced in the ACB) |
19 |
group_version |
repeated int64 |
A list of indexes of the group key used to encipher the token |
20 |
deleted |
bool |
Wheter the Block was marked for deletion |
21 |
seal_version |
Version |
The version to determine the type of algorithm used / to use when sealing the Block |
23 |
next_seal_version |
int64 |
The version of the seal to use during next sealing |
FetchResponse
|
index |
name |
type |
abstract |
1 |
type |
string |
[internal] |
2 |
block |
Block |
The fetched Block, at it latest version |
InsertResponse
|
index |
name |
type |
abstract |
1 |
type |
string |
[internal] |
2 |
bool |
bool |
Whether the update succeeded |
UpdateResponse
|
index |
name |
type |
abstract |
1 |
type |
string |
[internal] |
2 |
message |
bytes |
A message describing the error |
3 |
current |
Block |
The current block stored at the address |
4 |
bool |
bool |
Whether the update succeeded |
DeleteResponse
|
index |
name |
type |
abstract |
1 |
type |
string |
[internal] |
2 |
bool |
bool |
Whether the update was successful |
Talk to us on the Internet!
Ask questions to our team or our contributors, get involved in the project...