Skip to content

Commit

Permalink
Copy previous BatchState.dbWrite into the next one
Browse files Browse the repository at this point in the history
  • Loading branch information
fractasy committed Sep 21, 2023
1 parent 4ead23d commit c64dc36
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 13 deletions.
1 change: 1 addition & 0 deletions src/hashdb64/database_64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ zkresult Database64::readKV(const Goldilocks::Element (&root)[4], const Goldiloc

if (dbReadLog != NULL) dbReadLog->add(keyStr, value, true, TimeDiff(t));
rkv = ZKR_SUCCESS;
rout = rkv;

}
// If the key is pending to be stored in database, but already deleted from cache
Expand Down
26 changes: 24 additions & 2 deletions src/hashdb64/state_manager_64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,20 @@ zkresult StateManager64::setStateRoot(const string &batchUUID, uint64_t tx, cons
state[batchUUID] = batchState;
it = state.find(batchUUID);
zkassert(it != state.end());

// Copy the previous batch state dbWrite map
for (int64_t i = stateOrder.size() - 1; i >= 0; i--)
{
unordered_map<string, BatchState64>::iterator previt;
previt = state.find(stateOrder[i]);
zkassert(previt != state.end());
if (previt->second.currentStateRoot == stateRoot)
{
it->second.dbWrite = previt->second.dbWrite;
break;
}
}

stateOrder.emplace_back(batchUUID);
}
BatchState64 &batchState = it->second;
Expand Down Expand Up @@ -872,6 +886,14 @@ zkresult StateManager64::consolidateState(const string &_virtualStateRoot, const
// Return the consolidated state root
consolidatedStateRoot = fea2string(fr, newRoot);

// Copy it to use it when reading a KV that is not in the StateManager,
// and we have to read it from database using a consolidated state root
lastConsolidatedStateRoot[0] = newRoot[0];
lastConsolidatedStateRoot[1] = newRoot[1];
lastConsolidatedStateRoot[2] = newRoot[2];
lastConsolidatedStateRoot[3] = newRoot[3];
lastConsolidatedStateRootString = consolidatedStateRoot;

// Call flush and get the flush ID

zkr = db.flush(flushId, lastSentFlushId);
Expand Down Expand Up @@ -1123,11 +1145,11 @@ zkresult StateManager64::get (const string &batchUUID, Database64 &db, const Gol
}
if (zkr != ZKR_SUCCESS)
{
zkr = db.readKV(root, key, value, level, dbReadLog);
zkr = db.readKV(lastConsolidatedStateRoot, key, value, level, dbReadLog);
}
if (zkr != ZKR_SUCCESS)
{
zklog.error("StateManager64::get() db.read error: " + to_string(zkr) + " (" + zkresult2string(zkr) + ") root:" + fea2string(fr, root));
zklog.error("StateManager64::get() db.read error=" + zkresult2string(zkr) + " root=" + fea2string(fr, lastConsolidatedStateRoot) + " key=" + fea2string(fr, key));
return zkr;
}

Expand Down
6 changes: 6 additions & 0 deletions src/hashdb64/state_manager_64.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,17 @@ class StateManager64
Config config;
pthread_mutex_t mutex; // Mutex to protect the multi write queues
uint64_t lastVirtualStateRoot;
Goldilocks::Element lastConsolidatedStateRoot[4];
string lastConsolidatedStateRootString;
public:
StateManager64(Goldilocks &fr, PoseidonGoldilocks &poseidon) : fr(fr), poseidon(poseidon), lastVirtualStateRoot(0)
{
// Init mutex
pthread_mutex_init(&mutex, NULL);
lastConsolidatedStateRoot[0] = fr.zero();
lastConsolidatedStateRoot[1] = fr.zero();
lastConsolidatedStateRoot[2] = fr.zero();
lastConsolidatedStateRoot[3] = fr.zero();
};
private:
zkresult setStateRoot (const string &batchUUID, uint64_t tx, const string &stateRoot, const bool bIsOldStateRoot, const Persistence persistence);
Expand Down
56 changes: 45 additions & 11 deletions test/service/hashdb/hashdb64_workflow_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ uint64_t HashDB64WorkflowTest (const Config& config)
uint64_t flushId, storedFlushId;


const uint64_t numberOfSetsPerTx = 3;
const uint64_t numberOfTxsPerBatch = 3;
const uint64_t numberOfBatches = 10;
const uint64_t numberOfTxsPerBatch = 3;
const uint64_t numberOfSetsPerTx = 3;

zklog.info("HashDB64WorkflowTest() numberOfBatches=" + to_string(numberOfBatches) + " numberOfTxsPerBatch=" + to_string(numberOfTxsPerBatch) + " numberOfSetsPerTx=" + to_string(numberOfSetsPerTx));

SmtSetResult setResult;
SmtGetResult getResult;
Expand All @@ -36,10 +38,11 @@ uint64_t HashDB64WorkflowTest (const Config& config)
Goldilocks::Element keyfea[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
mpz_class value = 0;
mpz_class keyScalar = 0;
vector<KeyValue> allKeyValues;

for (uint64_t batch=0; batch<numberOfBatches; batch++)
{
zklog.info("STARTING LOOP=" + to_string(batch));
zklog.info("STARTING BATCH=" + to_string(batch));

// Start batch
string batchUUID = getUUID();
Expand Down Expand Up @@ -72,6 +75,7 @@ uint64_t HashDB64WorkflowTest (const Config& config)
// Take note of the key we used
KeyValue keyValue;
for (uint64_t i=0; i<4; i++) keyValue.key[i] = key[i];
keyValue.value = value;
keyValues.emplace_back(keyValue);
}

Expand All @@ -83,6 +87,25 @@ uint64_t HashDB64WorkflowTest (const Config& config)
zkassertpermanent(zkr==ZKR_SUCCESS);
zklog.info("PURGE zkr=" + zkresult2string(zkr) + " root=" + fea2string(fr, root));

for (uint64_t i=0; i<allKeyValues.size(); i++)
{
//zklog.info("allKeyValues[" + to_string(i) + "].key=" + fea2string(fr, allKeyValues[i].key) + " .value=" + allKeyValues[i].value.get_str(10));
mpz_class auxValue;
zkr = pHashDB->get(batchUUID, root, allKeyValues[i].key, auxValue, &getResult, NULL);
zkassertpermanent(zkr==ZKR_SUCCESS);
zkassertpermanent(auxValue==allKeyValues[i].value);
}

// Discard some of the batches, and accumulate the key values in the rest
if (((batch+4) % 5) == 0)
{
for (uint64_t i=0; i<4; i++) root[i] = batchOldStateRoot[i];
}
else
{
allKeyValues.insert(allKeyValues.end(), keyValues.begin(), keyValues.end());
}

// Consolidate state root every 5 batches, at batches 4, 9, 14, 19...
Goldilocks::Element batchNewStateRoot[4];
if (((batch+1) % 5) == 0)
Expand Down Expand Up @@ -120,20 +143,31 @@ uint64_t HashDB64WorkflowTest (const Config& config)

// Call ReadTree with the new state root to get the hashes of the initial values of all read or written keys
vector<HashValueGL> hashValues;
zkr = pHashDB->readTree(batchNewStateRoot, keyValues, hashValues);
vector<KeyValue> auxKeyValues = allKeyValues;
for (uint64_t i=0; i<auxKeyValues.size(); i++)
{
auxKeyValues[i].value = 0;
}
zkr = pHashDB->readTree(batchNewStateRoot, auxKeyValues, hashValues);
zkassertpermanent(zkr==ZKR_SUCCESS);
zklog.info("READ TREE batchNewStateRoot=" + fea2string(fr, batchNewStateRoot) + " keyValues.size=" + to_string(keyValues.size()) + " hashValues.size=" + to_string(hashValues.size()));
zklog.info("READ TREE batchNewStateRoot=" + fea2string(fr, batchNewStateRoot) + " keyValues.size=" + to_string(auxKeyValues.size()) + " hashValues.size=" + to_string(hashValues.size()));

zkassertpermanent(auxKeyValues.size() == allKeyValues.size());
for (uint64_t i=0; i<auxKeyValues.size(); i++)
{
//zklog.info("auxKeyValues[" + to_string(i) + "].key=" + fea2string(fr, auxKeyValues[i].key) + " .value=" + auxKeyValues[i].value.get_str(10));
//zklog.info("allKeyValues[i].key=" + fea2string(fr, allKeyValues[i].key) + " .value=" + allKeyValues[i].value.get_str(10));
zkassertpermanent(auxKeyValues[i].value == allKeyValues[i].value);
zkassertpermanent( fr.equal(auxKeyValues[i].key[0], allKeyValues[i].key[0]) &&
fr.equal(auxKeyValues[i].key[1], allKeyValues[i].key[1]) &&
fr.equal(auxKeyValues[i].key[2], allKeyValues[i].key[2]) &&
fr.equal(auxKeyValues[i].key[3], allKeyValues[i].key[3]) );
}
}
else
{
for (uint64_t i=0; i<4; i++) batchNewStateRoot[i] = root[i];
}

// Discard some of the batches
if (((batch+4) % 5) == 0)
{
for (uint64_t i=0; i<4; i++) root[i] = batchOldStateRoot[i];
}
}

TimerStopAndLog(HASHDB64_WORKFLOW_TEST);
Expand Down

0 comments on commit c64dc36

Please sign in to comment.