Skip to content

Commit

Permalink
fix(vats): update chainStorage to use new vstorage API
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelfig committed Jun 7, 2022
1 parent 44cc69a commit 094044c
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 37 deletions.
16 changes: 16 additions & 0 deletions golang/cosmos/x/vstorage/vstorage.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ type vstorageMessage struct {
Value string `json:"value"`
}

type vstorageStoreKey struct {
StoreName string `json:"storeName"`
StoreSubkey string `json:"storeSubkey"`
}

func NewStorageHandler(keeper Keeper) vstorageHandler {
return vstorageHandler{keeper: keeper}
}
Expand Down Expand Up @@ -67,6 +72,17 @@ func (sh vstorageHandler) Receive(cctx *vm.ControllerContext, str string) (ret s
}
return string(bz), nil

case "getStoreKey":
value := vstorageStoreKey{
StoreName: keeper.GetStoreName(),
StoreSubkey: string(keeper.PathToEncodedKey(msg.Path)),
}
bz, err := json.Marshal(value)
if err != nil {
return "", err
}
return string(bz), nil

case "has":
value := keeper.GetData(cctx.Context, msg.Path)
if value == "" {
Expand Down
21 changes: 2 additions & 19 deletions packages/vats/src/lib-chainStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ export function makeChainStorageRoot(toStorage, storeName, rootPath) {
function makeChainStorageNode(path) {
const node = {
getStoreKey() {
// This duplicates the Go code at
// https://github.com/Agoric/agoric-sdk/blob/cb272ae97a042ceefd3af93b1b4601ca49dfe3a7/golang/cosmos/x/swingset/keeper/keeper.go#L295
return { storeName, storeSubkey: `swingset/data:${path}` };
return toStorage({ key: path, method: 'getStoreKey' });
},
getChildNode(name) {
assert.typeof(name, 'string');
Expand All @@ -44,22 +42,7 @@ export function makeChainStorageRoot(toStorage, storeName, rootPath) {
assert.typeof(value, 'string');
toStorage({ key: path, method: 'set', value });
},
async delete() {
assert(path !== rootPath);
// A 'set' with no value deletes a key if it has no children, but
// otherwise sets data to the empty string and leaves all nodes intact.
// We want to reject silently incomplete deletes (at least for now).
// This check is unfortunately racy (e.g., a vat could wake up
// and set data for a child before _this_ vat receives an
// already-enqueued response claiming no children), but we can tolerate
// that because transforming a deletion into a set-to-empty is
// effectively indistinguishable from a valid reordering where a fully
// successful 'delete' is followed by a child-key 'set' (for which
// absent parent keys are automatically created with empty-string data).
const childCount = await toStorage({ key: path, method: 'size' });
if (childCount > 0) {
assert.fail(X`Refusing to delete node with children: ${path}`);
}
clearValue() {
toStorage({ key: path, method: 'set' });
},
// Possible extensions:
Expand Down
36 changes: 18 additions & 18 deletions packages/vats/test/test-lib-chainStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ test('makeChainStorageRoot', async t => {
const toStorage = message => {
messages.push(message);
switch (message.method) {
case 'getStoreKey': {
return {
storeName: 'swingset',
storeSubkey: `swingset/data:${message.key}`,
};
}
case 'set':
if ('value' in message) {
data.set(message.key, message.value);
Expand Down Expand Up @@ -62,12 +68,7 @@ test('makeChainStorageRoot', async t => {
);
}

// The root node cannot be deleted, but is otherwise normal.
await t.throwsAsync(
rootNode.delete(),
undefined,
'root node deletion is disallowed',
);
rootNode.clearValue();
rootNode.setValue('foo');
t.deepEqual(
messages.slice(-1),
Expand Down Expand Up @@ -117,12 +118,11 @@ test('makeChainStorageRoot', async t => {
[{ key: childPath, method: 'set', value: 'foo' }],
'non-root setValue message',
);
// eslint-disable-next-line no-await-in-loop
await child.delete();
child.clearValue();
t.deepEqual(
messages.slice(-1),
[{ key: childPath, method: 'set' }],
'non-root delete message',
'non-root clearValue message',
);
}

Expand Down Expand Up @@ -172,22 +172,22 @@ test('makeChainStorageRoot', async t => {
'level-skipping setValue message',
);

// Deletion requires absence of children.
await t.throwsAsync(
childNode.delete(),
undefined,
'deleting a node with a child is disallowed',
childNode.clearValue();
t.deepEqual(
messages.slice(-1),
[{ key: childPath, method: 'set' }],
'child clearValue message',
);
await deepNode.delete();
deepNode.clearValue();
t.deepEqual(
messages.slice(-1),
[{ key: deepPath, method: 'set' }],
'granchild delete message',
'granchild clearValue message',
);
await childNode.delete();
childNode.clearValue();
t.deepEqual(
messages.slice(-1),
[{ key: childPath, method: 'set' }],
'child delete message',
'child clearValue message',
);
});

0 comments on commit 094044c

Please sign in to comment.