Skip to content

Commit

Permalink
hotfix: proper handling of duplicates in DB
Browse files Browse the repository at this point in the history
  • Loading branch information
FilipHarald committed Oct 9, 2024
1 parent d9a0f7e commit c5d2e67
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 236 deletions.
329 changes: 133 additions & 196 deletions services/explorer-api/src/database/controllers/l2block/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,198 +49,147 @@ export const store = async (block: ChicmozL2Block): Promise<void> => {
const gasFeesId = uuidv4();

// Insert archive
await tx
.insert(archive)
.values({
id: archiveId,
root: block.archive.root,
nextAvailableLeafIndex: block.archive.nextAvailableLeafIndex,
})
.onConflictDoNothing();
await tx.insert(archive).values({
id: archiveId,
root: block.archive.root,
nextAvailableLeafIndex: block.archive.nextAvailableLeafIndex,
});

// Insert last archive
await tx
.insert(lastArchive)
.values({
id: lastArchiveId,
root: block.header.lastArchive.root,
nextAvailableLeafIndex: block.header.lastArchive.nextAvailableLeafIndex,
})
.onConflictDoNothing();
await tx.insert(lastArchive).values({
id: lastArchiveId,
root: block.header.lastArchive.root,
nextAvailableLeafIndex: block.header.lastArchive.nextAvailableLeafIndex,
});

// Insert content commitment
await tx
.insert(contentCommitment)
.values({
id: contentCommitmentId,
numTxs: block.header.contentCommitment.numTxs,
txsEffectsHash: block.header.contentCommitment.txsEffectsHash,
inHash: block.header.contentCommitment.inHash,
outHash: block.header.contentCommitment.outHash,
})
.onConflictDoNothing();
await tx.insert(contentCommitment).values({
id: contentCommitmentId,
numTxs: block.header.contentCommitment.numTxs,
txsEffectsHash: block.header.contentCommitment.txsEffectsHash,
inHash: block.header.contentCommitment.inHash,
outHash: block.header.contentCommitment.outHash,
});

// Insert l1ToL2MessageTree
await tx
.insert(l1ToL2MessageTree)
.values({
id: l1ToL2MessageTreeId,
root: block.header.state.l1ToL2MessageTree.root,
nextAvailableLeafIndex:
block.header.state.l1ToL2MessageTree.nextAvailableLeafIndex,
})
.onConflictDoNothing();
await tx.insert(l1ToL2MessageTree).values({
id: l1ToL2MessageTreeId,
root: block.header.state.l1ToL2MessageTree.root,
nextAvailableLeafIndex:
block.header.state.l1ToL2MessageTree.nextAvailableLeafIndex,
});

// Insert partial state trees
await tx
.insert(noteHashTree)
.values({
id: noteHashTreeId,
root: block.header.state.partial.noteHashTree.root,
nextAvailableLeafIndex:
block.header.state.partial.noteHashTree.nextAvailableLeafIndex,
})
.onConflictDoNothing();

await tx
.insert(nullifierTree)
.values({
id: nullifierTreeId,
root: block.header.state.partial.nullifierTree.root,
nextAvailableLeafIndex:
block.header.state.partial.nullifierTree.nextAvailableLeafIndex,
})
.onConflictDoNothing();

await tx
.insert(publicDataTree)
.values({
id: publicDataTreeId,
root: block.header.state.partial.publicDataTree.root,
nextAvailableLeafIndex:
block.header.state.partial.publicDataTree.nextAvailableLeafIndex,
})
.onConflictDoNothing();
await tx.insert(noteHashTree).values({
id: noteHashTreeId,
root: block.header.state.partial.noteHashTree.root,
nextAvailableLeafIndex:
block.header.state.partial.noteHashTree.nextAvailableLeafIndex,
});

await tx.insert(nullifierTree).values({
id: nullifierTreeId,
root: block.header.state.partial.nullifierTree.root,
nextAvailableLeafIndex:
block.header.state.partial.nullifierTree.nextAvailableLeafIndex,
});

await tx.insert(publicDataTree).values({
id: publicDataTreeId,
root: block.header.state.partial.publicDataTree.root,
nextAvailableLeafIndex:
block.header.state.partial.publicDataTree.nextAvailableLeafIndex,
});

// Insert partial
await tx
.insert(partial)
.values({
id: partialId,
noteHashTreeId,
nullifierTreeId,
publicDataTreeId,
})
.onConflictDoNothing();
await tx.insert(partial).values({
id: partialId,
noteHashTreeId,
nullifierTreeId,
publicDataTreeId,
});

// Insert state
await tx
.insert(state)
.values({
id: stateId,
l1ToL2MessageTreeId,
partialId,
})
.onConflictDoNothing();
await tx.insert(state).values({
id: stateId,
l1ToL2MessageTreeId,
partialId,
});

// Insert gas fees
await tx
.insert(gasFees)
.values({
id: gasFeesId,
feePerDaGas: block.header.globalVariables.gasFees.feePerDaGas,
feePerL2Gas: block.header.globalVariables.gasFees.feePerL2Gas,
})
.onConflictDoNothing();
await tx.insert(gasFees).values({
id: gasFeesId,
feePerDaGas: block.header.globalVariables.gasFees.feePerDaGas,
feePerL2Gas: block.header.globalVariables.gasFees.feePerL2Gas,
});

// Insert global variables
await tx
.insert(globalVariables)
.values({
id: globalVariablesId,
chainId: block.header.globalVariables.chainId,
version: block.header.globalVariables.version,
blockNumber: block.header.globalVariables.blockNumber,
slotNumber: block.header.globalVariables.slotNumber,
timestamp: block.header.globalVariables.timestamp,
coinbase: block.header.globalVariables.coinbase,
feeRecipient: block.header.globalVariables.feeRecipient,
gasFeesId,
})
.onConflictDoNothing();
await tx.insert(globalVariables).values({
id: globalVariablesId,
chainId: block.header.globalVariables.chainId,
version: block.header.globalVariables.version,
blockNumber: block.header.globalVariables.blockNumber,
slotNumber: block.header.globalVariables.slotNumber,
timestamp: block.header.globalVariables.timestamp,
coinbase: block.header.globalVariables.coinbase,
feeRecipient: block.header.globalVariables.feeRecipient,
gasFeesId,
});

// Insert header
await tx
.insert(header)
.values({
id: headerId,
lastArchiveId,
contentCommitmentId,
stateId,
globalVariablesId,
totalFees: block.header.totalFees,
})
.onConflictDoNothing();
await tx.insert(header).values({
id: headerId,
lastArchiveId,
contentCommitmentId,
stateId,
globalVariablesId,
totalFees: block.header.totalFees,
});

// Insert body
await tx
.insert(body)
.values({
id: bodyId,
})
.onConflictDoNothing();
await tx.insert(body).values({
id: bodyId,
});

// Insert txEffects and create junction entries
for (const [i, txEff] of Object.entries(block.body.txEffects)) {
if (isNaN(Number(i))) throw new Error("Invalid txEffect index");
const txEffectId = uuidv4();
await tx
.insert(txEffect)
.values({
id: txEffectId,
hash: txEff.hash,
index: Number(i),
revertCode: txEff.revertCode.code,
transactionFee: txEff.transactionFee,
noteHashes: txEff.noteHashes as HexString[],
nullifiers: txEff.nullifiers as HexString[],
l2ToL1Msgs: txEff.l2ToL1Msgs as HexString[],
noteEncryptedLogsLength: txEff.noteEncryptedLogsLength,
encryptedLogsLength: txEff.encryptedLogsLength,
unencryptedLogsLength: txEff.unencryptedLogsLength,
})
.onConflictDoNothing();
await tx.insert(txEffect).values({
id: txEffectId,
hash: txEff.hash,
index: Number(i),
revertCode: txEff.revertCode.code,
transactionFee: txEff.transactionFee,
noteHashes: txEff.noteHashes as HexString[],
nullifiers: txEff.nullifiers as HexString[],
l2ToL1Msgs: txEff.l2ToL1Msgs as HexString[],
noteEncryptedLogsLength: txEff.noteEncryptedLogsLength,
encryptedLogsLength: txEff.encryptedLogsLength,
unencryptedLogsLength: txEff.unencryptedLogsLength,
});

// Create junction entry for bodyToTxEffects
await tx
.insert(bodyToTxEffects)
.values({
bodyId: bodyId,
txEffectId: txEffectId,
})
.onConflictDoNothing();
await tx.insert(bodyToTxEffects).values({
bodyId: bodyId,
txEffectId: txEffectId,
});

// Insert public data writes
for (const [pdwIndex, pdw] of Object.entries(txEff.publicDataWrites)) {
const publicDataWriteId = uuidv4();
await tx
.insert(publicDataWrite)
.values({
id: publicDataWriteId,
leafIndex: pdw.leafIndex,
newValue: pdw.newValue,
})
.onConflictDoNothing();
await tx.insert(publicDataWrite).values({
id: publicDataWriteId,
leafIndex: pdw.leafIndex,
newValue: pdw.newValue,
});

// Create junction entry for txEffectToPublicDataWrite
await tx
.insert(txEffectToPublicDataWrite)
.values({
txEffectId: txEffectId,
index: Number(pdwIndex),
publicDataWriteId: publicDataWriteId,
})
.onConflictDoNothing();
await tx.insert(txEffectToPublicDataWrite).values({
txEffectId: txEffectId,
index: Number(pdwIndex),
publicDataWriteId: publicDataWriteId,
});
}

for (const [logType, fLogs] of Object.entries({
Expand All @@ -251,57 +200,45 @@ export const store = async (block: ChicmozL2Block): Promise<void> => {
for (const [functionLogIndex, functionLog] of Object.entries(fLogs)) {
// Insert logs
const functionLogId = uuidv4();
await tx
.insert(functionLogs)
.values({
id: functionLogId,
index: Number(functionLogIndex),
})
.onConflictDoNothing();
await tx.insert(functionLogs).values({
id: functionLogId,
index: Number(functionLogIndex),
});
for (const [index, log] of Object.entries(
functionLog.logs as Array<
NoteEncryptedLogEntry | EncryptedLogEntry | UnencryptedLogEntry
>
)) {
const logId = uuidv4();

await tx
.insert(logs)
.values({
id: logId,
index: Number(index),
type: logType,
data: log.data,
maskedContractAddress: (log as EncryptedLogEntry)
.maskedContractAddress,
contractAddress: (log as UnencryptedLogEntry).contractAddress,
})
.onConflictDoNothing();
await tx.insert(logs).values({
id: logId,
index: Number(index),
type: logType,
data: log.data,
maskedContractAddress: (log as EncryptedLogEntry)
.maskedContractAddress,
contractAddress: (log as UnencryptedLogEntry).contractAddress,
});

// Create junction entry for txEffectToLogs
await tx
.insert(txEffectToLogs)
.values({
txEffectId: txEffectId,
logId: logId,
functionLogId: functionLogId,
})
.onConflictDoNothing();
await tx.insert(txEffectToLogs).values({
txEffectId: txEffectId,
logId: logId,
functionLogId: functionLogId,
});
}
}
}
}

// Insert l2Block
await tx
.insert(l2Block)
.values({
hash: block.hash ,
height: block.header.globalVariables.blockNumber,
archiveId,
headerId,
bodyId,
})
.onConflictDoNothing();
await tx.insert(l2Block).values({
hash: block.hash,
height: block.header.globalVariables.blockNumber,
archiveId,
headerId,
bodyId,
});
});
};
Loading

0 comments on commit c5d2e67

Please sign in to comment.