Skip to content

Commit

Permalink
Merge pull request #1077 from ainblockchain/feature/platfowner/feature
Browse files Browse the repository at this point in the history
Use getTreeMaxSiblings() instead of numChildren() in max siblings limit check
  • Loading branch information
platfowner authored Jun 30, 2022
2 parents c6129aa + 2ddd007 commit ff3ff66
Show file tree
Hide file tree
Showing 12 changed files with 288 additions and 27 deletions.
3 changes: 2 additions & 1 deletion common/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -426,9 +426,10 @@ const StateLabelProperties = {
STATE_PROOF_HASH: '#state_ph',
VARIABLE_LABEL_PREFIX: '$', // Prefix of variable labels
VERSION: '#version',
TREE_BYTES: '#tree_bytes',
TREE_HEIGHT: '#tree_height',
TREE_MAX_SIBLINGS: '#tree_max_siblings',
TREE_SIZE: '#tree_size',
TREE_BYTES: '#tree_bytes',
};

/**
Expand Down
5 changes: 3 additions & 2 deletions db/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,7 @@ class DB {
[StateLabelProperties.TREE_HEIGHT]: stateNode.getTreeHeight(),
[StateLabelProperties.TREE_SIZE]: stateNode.getTreeSize(),
[StateLabelProperties.TREE_BYTES]: stateNode.getTreeBytes(),
[StateLabelProperties.TREE_MAX_SIBLINGS]: stateNode.getTreeMaxSiblings(),
[StateLabelProperties.STATE_PROOF_HASH]: stateNode.getProofHash(),
[StateLabelProperties.VERSION]: stateNode.getVersion(),
};
Expand Down Expand Up @@ -739,11 +740,11 @@ class DB {
static checkRespTreeLimits(stateNode, options) {
// NOTE: Skip sibling number limit check for isPartial = true cases.
if (!(options && options.isPartial)) {
if (stateNode.numChildren() > NodeConfigs.GET_RESP_MAX_SIBLINGS) {
if (stateNode.getTreeMaxSiblings() > NodeConfigs.GET_RESP_MAX_SIBLINGS) {
return {
code: JsonRpcApiResultCode.GET_EXCEEDS_MAX_SIBLINGS,
message: `The data exceeds the max sibling limit of the requested node: ` +
`${stateNode.numChildren()} > ${NodeConfigs.GET_RESP_MAX_SIBLINGS}`
`${stateNode.getTreeMaxSiblings()} > ${NodeConfigs.GET_RESP_MAX_SIBLINGS}`
};
}
}
Expand Down
29 changes: 26 additions & 3 deletions db/radix-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class RadixNode {
this.treeHeight = 0;
this.treeSize = 0;
this.treeBytes = 0;
this.treeMaxSiblings = 0;
}

reset() {
Expand All @@ -44,11 +45,12 @@ class RadixNode {
this.resetTreeHeight();
this.resetTreeSize();
this.resetTreeBytes();
this.resetTreeMaxSiblings();
}

static _create(
version, serial, parentStateNode, childStateNode, labelRadix, labelSuffix, proofHash,
treeHeight, treeSize, treeBytes) {
treeHeight, treeSize, treeBytes, treeMaxSiblings) {
const node = new RadixNode(version, serial, parentStateNode);
if (childStateNode) {
node.setChildStateNode(childStateNode);
Expand All @@ -59,14 +61,15 @@ class RadixNode {
node.setTreeHeight(treeHeight);
node.setTreeSize(treeSize);
node.setTreeBytes(treeBytes);
node.setTreeMaxSiblings(treeMaxSiblings);
return node;
}

clone(version, parentStateNode = null) {
const cloned = RadixNode._create(
version, this.getSerial(), parentStateNode, this.getChildStateNode(), this.getLabelRadix(),
this.getLabelSuffix(), this.getProofHash(), this.getTreeHeight(), this.getTreeSize(),
this.getTreeBytes());
this.getTreeBytes(), this.getTreeMaxSiblings());
for (const child of this.getChildNodes()) {
cloned.setChild(child.getLabelRadix(), child.getLabelSuffix(), child);
}
Expand Down Expand Up @@ -445,12 +448,25 @@ class RadixNode {
this.setTreeBytes(0);
}

getTreeMaxSiblings() {
return this.treeMaxSiblings;
}

setTreeMaxSiblings(treeMaxSiblings) {
this.treeMaxSiblings = treeMaxSiblings;
}

resetTreeMaxSiblings() {
this.setTreeMaxSiblings(0);
}

buildRadixInfo() {
let treeInfo = {
preimage: '',
treeHeight: 0,
treeSize: 0,
treeBytes: 0,
treeMaxSiblings: 0,
};
if (this.hasChildStateNode()) {
const childStateNode = this.getChildStateNode();
Expand All @@ -461,6 +477,7 @@ class RadixNode {
treeHeight: childStateNode.getTreeHeight(),
treeSize: childStateNode.getTreeSize(),
treeBytes: sizeof(childStateNodeLabel) + childStateNode.getTreeBytes(),
treeMaxSiblings: childStateNode.getTreeMaxSiblings(),
};
}
treeInfo.preimage += StateLabelProperties.HASH_DELIMITER;
Expand All @@ -473,11 +490,13 @@ class RadixNode {
const accTreeHeight = Math.max(acc.treeHeight, child.getTreeHeight());
const accTreeSize = acc.treeSize + child.getTreeSize();
const accTreeBytes = acc.treeBytes + child.getTreeBytes();
const accTreeMaxSiblings = Math.max(acc.treeMaxSiblings, child.getTreeMaxSiblings());
return {
preimage: accPreimage,
treeHeight: accTreeHeight,
treeSize: accTreeSize,
treeBytes: accTreeBytes,
treeMaxSiblings: accTreeMaxSiblings,
};
}, treeInfo);
}
Expand All @@ -487,6 +506,7 @@ class RadixNode {
treeHeight: treeInfo.treeHeight,
treeSize: treeInfo.treeSize,
treeBytes: treeInfo.treeBytes,
treeMaxSiblings: treeInfo.treeMaxSiblings,
};
}

Expand All @@ -496,14 +516,16 @@ class RadixNode {
this.setTreeHeight(treeInfo.treeHeight);
this.setTreeSize(treeInfo.treeSize);
this.setTreeBytes(treeInfo.treeBytes);
this.setTreeMaxSiblings(treeInfo.treeMaxSiblings);
}

verifyRadixInfo() {
const treeInfo = this.buildRadixInfo();
return this.getProofHash() === treeInfo.proofHash &&
this.getTreeHeight() === treeInfo.treeHeight &&
this.getTreeSize() === treeInfo.treeSize &&
this.getTreeBytes() === treeInfo.treeBytes;
this.getTreeBytes() === treeInfo.treeBytes &&
this.getTreeMaxSiblings() === treeInfo.treeMaxSiblings;
}

updateRadixInfoForRadixTree() {
Expand Down Expand Up @@ -735,6 +757,7 @@ class RadixNode {
obj[StateLabelProperties.TREE_HEIGHT] = this.getTreeHeight();
obj[StateLabelProperties.TREE_SIZE] = this.getTreeSize();
obj[StateLabelProperties.TREE_BYTES] = this.getTreeBytes();
obj[StateLabelProperties.TREE_MAX_SIBLINGS] = this.getTreeMaxSiblings();
}
if (withNumParents) {
obj[StateLabelProperties.NUM_PARENTS] = this.numParents();
Expand Down
4 changes: 4 additions & 0 deletions db/radix-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,10 @@ class RadixTree {
return this.root.getTreeBytes();
}

getRootTreeMaxSiblings() {
return this.root.getTreeMaxSiblings();
}

updateRadixInfoForRadixTree() {
return this.root.updateRadixInfoForRadixTree();
}
Expand Down
29 changes: 24 additions & 5 deletions db/state-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class StateNode {
this.treeHeight = 0;
this.treeSize = 0;
this.treeBytes = 0;
this.treeMaxSiblings = 0;
}

reset() {
Expand All @@ -38,10 +39,11 @@ class StateNode {
this.setTreeHeight(0);
this.setTreeSize(0);
this.setTreeBytes(0);
this.setTreeMaxSiblings(0);
}

static _create(
version, label, isLeaf, value, proofHash, treeHeight, treeSize, treeBytes) {
version, label, isLeaf, value, proofHash, treeHeight, treeSize, treeBytes, treeMaxSiblings) {
const node = new StateNode(version);
node.setLabel(label);
node.setIsLeaf(isLeaf);
Expand All @@ -50,6 +52,7 @@ class StateNode {
node.setTreeHeight(treeHeight);
node.setTreeSize(treeSize);
node.setTreeBytes(treeBytes);
node.setTreeMaxSiblings(treeMaxSiblings);
return node;
}

Expand All @@ -58,7 +61,7 @@ class StateNode {
const versionToSet = version ? version : this.version;
const cloned = StateNode._create(
versionToSet, this.label, this.isLeaf, this.value, this.proofHash,
this.treeHeight, this.treeSize, this.treeBytes);
this.treeHeight, this.treeSize, this.treeBytes, this.treeMaxSiblings);
if (!this.getIsLeaf()) {
cloned.setRadixTree(this.radixTree.clone(versionToSet, cloned));
}
Expand All @@ -69,6 +72,8 @@ class StateNode {
// from this calculation, since their sizes can vary and affect the gas costs and
// state proof hashes.
// 4(isLeaf) + 132(proofHash) + 8(treeHeight) + 8(treeSize) + 8(treeBytes) = 160
// NOTE(platfowner): treeMaxSiblings is not included in the node bytes computation since
// it was added later (see https://github.com/ainblockchain/ain-blockchain/issues/1067).
computeNodeBytes() {
return sizeof(this.value) + 160;
}
Expand Down Expand Up @@ -156,6 +161,7 @@ class StateNode {
obj[`${StateLabelProperties.TREE_HEIGHT}:${label}`] = childNode.getTreeHeight();
obj[`${StateLabelProperties.TREE_SIZE}:${label}`] = childNode.getTreeSize();
obj[`${StateLabelProperties.TREE_BYTES}:${label}`] = childNode.getTreeBytes();
obj[`${StateLabelProperties.TREE_MAX_SIBLINGS}:${label}`] = childNode.getTreeMaxSiblings();
}
if (includeProof) {
obj[`${StateLabelProperties.STATE_PROOF_HASH}:${label}`] = childNode.getProofHash();
Expand All @@ -179,6 +185,7 @@ class StateNode {
obj[`${StateLabelProperties.TREE_HEIGHT}`] = this.getTreeHeight();
obj[`${StateLabelProperties.TREE_SIZE}`] = this.getTreeSize();
obj[`${StateLabelProperties.TREE_BYTES}`] = this.getTreeBytes();
obj[`${StateLabelProperties.TREE_MAX_SIBLINGS}`] = this.getTreeMaxSiblings();
}
if (includeProof) {
obj[`${StateLabelProperties.STATE_PROOF_HASH}`] = this.getProofHash();
Expand Down Expand Up @@ -435,6 +442,14 @@ class StateNode {
this.treeBytes = treeBytes;
}

getTreeMaxSiblings() {
return this.treeMaxSiblings;
}

setTreeMaxSiblings(treeMaxSiblings) {
this.treeMaxSiblings = treeMaxSiblings;
}

/**
* Returns newly buildt proof hash. If updatedChildLabel is given, it signifies that
* only the child of the given child label among the children is not up-to-date now,
Expand All @@ -454,7 +469,8 @@ class StateNode {
proofHash,
treeHeight: 0,
treeSize: 1,
treeBytes: nodeBytes
treeBytes: nodeBytes,
treeMaxSiblings: 1
};
} else {
if (shouldRebuildRadixInfo) {
Expand All @@ -468,7 +484,8 @@ class StateNode {
proofHash: this.radixTree.getRootProofHash(),
treeHeight: 1 + this.radixTree.getRootTreeHeight(),
treeSize: 1 + this.radixTree.getRootTreeSize(),
treeBytes: nodeBytes + this.radixTree.getRootTreeBytes()
treeBytes: nodeBytes + this.radixTree.getRootTreeBytes(),
treeMaxSiblings: Math.max(this.numChildren(), this.radixTree.getRootTreeMaxSiblings())
};
}
}
Expand All @@ -479,14 +496,16 @@ class StateNode {
this.setTreeHeight(treeInfo.treeHeight);
this.setTreeSize(treeInfo.treeSize);
this.setTreeBytes(treeInfo.treeBytes);
this.setTreeMaxSiblings(treeInfo.treeMaxSiblings);
}

verifyStateInfo(updatedChildLabel = null) {
const treeInfo = this.buildStateInfo(updatedChildLabel, true);
return this.getProofHash() === treeInfo.proofHash &&
this.getTreeHeight() === treeInfo.treeHeight &&
this.getTreeSize() === treeInfo.treeSize &&
this.getTreeBytes() === treeInfo.treeBytes;
this.getTreeBytes() === treeInfo.treeBytes &&
this.getTreeMaxSiblings() === treeInfo.treeMaxSiblings;
}

getProofOfStateNode(childLabel = null, childProof = null) {
Expand Down
1 change: 1 addition & 0 deletions node/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,7 @@ class BlockchainNode {
tree_height: !CommonUtil.isEmpty(rawUsage) ? rawUsage[StateLabelProperties.TREE_HEIGHT] : 0,
tree_size: !CommonUtil.isEmpty(rawUsage) ? rawUsage[StateLabelProperties.TREE_SIZE] : 0,
tree_bytes: !CommonUtil.isEmpty(rawUsage) ? rawUsage[StateLabelProperties.TREE_BYTES] : 0,
tree_max_siblings: !CommonUtil.isEmpty(rawUsage) ? rawUsage[StateLabelProperties.TREE_MAX_SIBLINGS] : 0,
};
const availableTreeBytes = appStake > 0 ?
Math.max(0, appsStateBudget * appStakeRatio - usage.tree_bytes) :
Expand Down
Loading

0 comments on commit ff3ff66

Please sign in to comment.