Skip to content
This repository has been archived by the owner on Mar 15, 2024. It is now read-only.

Commit

Permalink
roll-back functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
krlosMata committed Feb 18, 2020
1 parent e8abf9b commit 6f08a40
Show file tree
Hide file tree
Showing 10 changed files with 788 additions and 120 deletions.
202 changes: 176 additions & 26 deletions js/batchbuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ module.exports = class BatchBuilder {
this.feePlan = Array(16).fill([0, bigInt(0)]);
this.counters = Array(16).fill(0);
this.nCoins = 0;
this.newBatchNumberDb = bigInt(batchNumber);
}

_addNopTx() {
Expand Down Expand Up @@ -94,7 +95,7 @@ module.exports = class BatchBuilder {
return bigInt(0);
}

async _addTx(tx) {
async _addTx(tx, numTx) {
const i = this.input.txData.length;

const amountF = utils.fix2float(tx.amount || 0);
Expand Down Expand Up @@ -202,7 +203,6 @@ module.exports = class BatchBuilder {
}
const newState2 = Object.assign({}, oldState2);
newState2.amount = oldState2.amount.add(effectiveAmount);

if (op1=="INSERT") {

const newValue = utils.hashState(newState1);
Expand All @@ -223,31 +223,104 @@ module.exports = class BatchBuilder {
this.input.oldKey1[i]= res.isOld0 ? 0 : res.oldKey;
this.input.oldValue1[i]= res.isOld0 ? 0 : res.oldValue;

// Database AxAy
const keyAxAy = Constants.DB_AxAy.add(this.input.ax[i]).add(this.input.ay[i]);
const keyEthAddr = Constants.DB_EthAddr.add(this.input.ethAddr[i]);
const lastVals = await this.dbState.multiGet([
keyAxAy,
keyEthAddr
const lastAxAyStates = await this.dbState.get(keyAxAy);

// get last state and add last batch number
let valStatesAxAy;
let lastAxAyState;
if (!lastAxAyStates) {
lastAxAyState = null;
valStatesAxAy = [];
valStatesAxAy.push(this.newBatchNumberDb);
}
else {
valStatesAxAy = [...lastAxAyStates];
await this._purgeStates(valStatesAxAy);
lastAxAyState = valStatesAxAy.slice(-1)[0];
valStatesAxAy.push(this.newBatchNumberDb);
}
if (numTx) lastAxAyState = valStatesAxAy.slice(-1)[0];

// get last state
let valOldAxAy = null;
if (lastAxAyState){
const keyOldAxAyBatch = poseidonHash([keyAxAy, lastAxAyState]);
valOldAxAy = await this.dbState.get(keyOldAxAyBatch);
}

let newValAxAy;
if (!valOldAxAy) newValAxAy = [];
else newValAxAy = [...valOldAxAy];
newValAxAy.push(bigInt(tx.fromIdx));
// new key newValAxAy
const newKeyAxAyBatch = poseidonHash([keyAxAy, this.newBatchNumberDb]);
await this.dbState.multiIns([
[keyAxAy, valStatesAxAy],
[newKeyAxAyBatch, newValAxAy],
]);

let valAxAy;
if (!lastVals[0]) valAxAy = [];
else valAxAy = [...lastVals[0]];
valAxAy.push(bigInt(tx.fromIdx));
// Database Ether address
const keyEth = Constants.DB_EthAddr.add(this.input.ethAddr[i]);
const lastEthStates = await this.dbState.get(keyEth);

// get last state and add last batch number
let valStatesEth;
let lastEthState;
if (!lastEthStates) {
lastEthState = null;
valStatesEth = [];
valStatesEth.push(this.newBatchNumberDb);
}
else {
valStatesEth = [...lastEthStates];
this._purgeStates(valStatesEth);
lastEthState = valStatesEth.slice(-1)[0];
valStatesEth.push(this.newBatchNumberDb);
}
if (numTx) lastEthState = valStatesEth.slice(-1)[0];

// get last state
let valOldEth = null;
if (lastEthState){
const keyOldEthBatch = poseidonHash([keyEth, lastEthState]);
valOldEth = await this.dbState.get(keyOldEthBatch);
}

let newValEth;
if (!valOldEth) newValEth = [];
else newValEth = [...valOldEth];
newValEth.push(bigInt(tx.fromIdx));

// new key newValEth
const newKeyEthBatch = poseidonHash([keyEth, this.newBatchNumberDb]);

await this.dbState.multiIns([
[keyEth, valStatesEth],
[newKeyEthBatch, newValEth],
]);

let valEthAddr;
if (!lastVals[1]) valEthAddr = [];
else valEthAddr = [...lastVals[1]];
valEthAddr.push(bigInt(tx.fromIdx));
// Database Idx
// get array of states saved by batch
const lastIdStates = await this.dbState.get(Constants.DB_Idx.add(bigInt(tx.fromIdx)));
// add last batch number
let valStatesId;
if (!lastIdStates) valStatesId = [];
else valStatesId = [...lastIdStates];
if (!valStatesId.includes(this.newBatchNumberDb)) valStatesId.push(this.newBatchNumberDb);

// new state for idx
const newValueId = poseidonHash([newValue, tx.fromIdx]);

// new entry according idx and batchNumber
const keyIdBatch = poseidonHash([tx.fromIdx, this.newBatchNumberDb]);

await this.dbState.multiIns([
[newValueId, utils.state2array(newState1)],
[Constants.DB_Idx.add(bigInt(tx.fromIdx)), newValueId],
[keyAxAy, valAxAy],
[keyEthAddr, valEthAddr]
[keyIdBatch, newValueId],
[Constants.DB_Idx.add(bigInt(tx.fromIdx)), valStatesId],
]);

} else if (op1 == "UPDATE") {
const newValue = utils.hashState(newState1);

Expand All @@ -269,12 +342,24 @@ module.exports = class BatchBuilder {
this.input.oldKey1[i]= 0x1234; // It should not matter
this.input.oldValue1[i]= 0x1234; // It should not matter

// get array of states saved by batch
const lastIdStates = await this.dbState.get(Constants.DB_Idx.add(bigInt(tx.fromIdx)));
// add last batch number
let valStatesId;
if (!lastIdStates) valStatesId = [];
else valStatesId = [...lastIdStates];
if (!valStatesId.includes(this.newBatchNumberDb)) valStatesId.push(this.newBatchNumberDb);

// new state for idx
const newValueId = poseidonHash([newValue, tx.fromIdx]);
const oldValueId = poseidonHash([resFind1.foundValue, tx.fromIdx]);
await this.dbState.multiDel([oldValueId]);

// new entry according idx and batchNumber
const keyIdBatch = poseidonHash([tx.fromIdx, this.newBatchNumberDb]);

await this.dbState.multiIns([
[newValueId, utils.state2array(newState1)],
[Constants.DB_Idx.add(bigInt(tx.fromIdx)), newValueId]
[keyIdBatch, newValueId],
[Constants.DB_Idx.add(bigInt(tx.fromIdx)), valStatesId]
]);
}

Expand Down Expand Up @@ -349,12 +434,24 @@ module.exports = class BatchBuilder {
this.input.oldKey2[i]= 0x1234; // It should not matter
this.input.oldValue2[i]= 0x1234; // It should not matter

// get array of states saved by batch
const lastIdStates = await this.dbState.get(Constants.DB_Idx.add(bigInt(tx.toIdx)));
// add last batch number
let valStatesId;
if (!lastIdStates) valStatesId = [];
else valStatesId = [...lastIdStates];
if (!valStatesId.includes(this.newBatchNumberDb)) valStatesId.push(this.newBatchNumberDb);

// new state for idx
const newValueId = poseidonHash([newValue, tx.toIdx]);
const oldValueId = poseidonHash([resFind2.foundValue, tx.toIdx]);
await this.dbState.multiDel([oldValueId]);

// new entry according idx and batchNumber
const keyIdBatch = poseidonHash([tx.toIdx, this.newBatchNumberDb]);

await this.dbState.multiIns([
[newValueId, utils.state2array(newState2)],
[Constants.DB_Idx.add(bigInt(tx.toIdx)), newValueId]
[keyIdBatch, newValueId],
[Constants.DB_Idx.add(bigInt(tx.toIdx)), valStatesId]
]);
}
} else if (op2=="NOP") {
Expand All @@ -372,6 +469,59 @@ module.exports = class BatchBuilder {
this.input.oldKey2[i]= 0;
this.input.oldValue2[i]= 0;
}

// Database numBatch - Idx
const keyNumBatchIdx = Constants.DB_NumBatch_Idx.add(this.newBatchNumberDb);
let lastBatchIdx = await this.dbState.get(keyNumBatchIdx);

// get last state and add last batch number
let newBatchIdx;
if (!lastBatchIdx) lastBatchIdx = [];
newBatchIdx = [...lastBatchIdx];

if (op1 == "INSERT" || op1 == "UPDATE") {
if (!newBatchIdx.includes(tx.fromIdx)) newBatchIdx.push(tx.fromIdx);
}

if (op2 == "UPDATE" && !isExit) {
if (!newBatchIdx.includes(tx.toIdx)) newBatchIdx.push(tx.toIdx);
}
await this.dbState.multiIns([
[keyNumBatchIdx, newBatchIdx],
]);

// Database NumBatch - AxAy
if (op1 == "INSERT") {
const encodeAxAy = this.input.ay[i].add(this.input.ax[i].shl(256));
const keyNumBatchAxAy = Constants.DB_NumBatch_AxAy.add(this.newBatchNumberDb);
let oldStatesAxAy = await this.dbState.get(keyNumBatchAxAy);
let newStatesAxAy;
if (!oldStatesAxAy) oldStatesAxAy = [];
newStatesAxAy = [...oldStatesAxAy];
if (!newStatesAxAy.includes(encodeAxAy)) {
newStatesAxAy.push(encodeAxAy);
await this.dbState.multiIns([
[keyNumBatchAxAy, newStatesAxAy],
]);
}
}
}

async _purgeStates(states){
if (states.length === 0) return;
if (states.slice(-1)[0].lesser(this.newBatchNumberDb)) return;
let indexFound = null;
for (let i = states.length - 1; i >= 0; i--){
if (states[i].lesserOrEquals(this.newBatchNumberDb)){
indexFound = i+1;
if (states[i].equals(this.newBatchNumberDb))
indexFound = i;
break;
}
}
if (indexFound !== null){
states.splice(indexFound);
}
}

_incCounter(coin, step) {
Expand Down Expand Up @@ -463,13 +613,13 @@ module.exports = class BatchBuilder {

if (this.builded) throw new Error("Batch already builded");
for (let i=0; i<this.offChainTxs.length; i++) {
await this._addTx(this.offChainTxs[i]);
await this._addTx(this.offChainTxs[i], i);
}
for (let i=0; i<this.maxNTx - this.offChainTxs.length - this.onChainTxs.length; i++) {
this._addNopTx();
}
for (let i=0; i<this.onChainTxs.length; i++) {
await this._addTx(this.onChainTxs[i]);
await this._addTx(this.onChainTxs[i], i);
}
this.builded=true;
}
Expand Down
3 changes: 3 additions & 0 deletions js/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ module.exports.DB_EthAddr=hash([string2Int("Rollup_DB_EthAddr")]);
module.exports.DB_TxPoolSlotsMap=hash([string2Int("Rollup_DB_TxPoolSlots")]);
module.exports.DB_EthAddr=hash([string2Int("Rollup_DB_EthAddr")]);
module.exports.DB_TxPollTx=hash([string2Int("Rollup_DB_TxPollTx")]);
module.exports.DB_NumBatch_Idx=hash([string2Int("Rollup_DB_NumBatch_Idx")]);
module.exports.DB_NumBatch_AxAy=hash([string2Int("Rollup_DB_NumBatch_AxAy")]);
module.exports.DB_NumBatch_EthAddr=hash([string2Int("Rollup_DB_NumBatch_EthAddr")]);
Loading

0 comments on commit 6f08a40

Please sign in to comment.