Skip to content

Commit

Permalink
Merge pull request #19 from XinFinOrg/copy-at-parent-chain
Browse files Browse the repository at this point in the history
cache the last submitted block in parentchain
  • Loading branch information
wjrjerome authored Aug 6, 2023
2 parents 88effbc + cff0453 commit 7520f18
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 25 deletions.
1 change: 1 addition & 0 deletions backend/src/interfaces/output/blocksResponse.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface BlockResponse extends BaseBlockResponse {
parentHash: string;
committedInSubnet: boolean;
committedInParentChain: boolean;
submittedInParentChain: boolean;
}

export interface BaseBlockResponse {
Expand Down
55 changes: 30 additions & 25 deletions backend/src/services/block.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ export class BlockService {
public async getLastMinedBlocks(): Promise<BaseBlockResponse> {
const allBlocks = await this.blockStorage.getAllBlocks();
const latestMinedBlock =
allBlocks && allBlocks.length
? {
hash: allBlocks[allBlocks.length - 1].hash,
number: allBlocks[allBlocks.length - 1].number,
}
: {
hash: "",
number: 0
};
allBlocks && allBlocks.length
? {
hash: allBlocks[allBlocks.length - 1].hash,
number: allBlocks[allBlocks.length - 1].number,
}
: {
hash: '',
number: 0,
};
return latestMinedBlock;
}

Expand All @@ -79,31 +79,24 @@ export class BlockService {
const allBlocks = await this.blockStorage.getAllBlocks();
const lastCommittedBlockInfo = await this.getLastSubnetCommittedBlock();
const lastCommittedBlock = await this.blockStorage.getMinedBlockByHash(lastCommittedBlockInfo.hash);
const endIndex = blockIndex != -1? allBlocks.findIndex((block) => block.number == blockIndex) : allBlocks.length-1;
const endIndex = blockIndex != -1 ? allBlocks.findIndex(block => block.number == blockIndex) : allBlocks.length - 1;
const startIndex = endIndex - NUM_OF_BLOCKS_RETURN >= 0 ? endIndex - NUM_OF_BLOCKS_RETURN : 0;
const selectedBlocks = allBlocks.slice(startIndex, endIndex)
const selectedBlocks = allBlocks.slice(startIndex, endIndex);

// Short-curcit if the committedBlock is not even recored in the system. The gap between mined and committed is too far
if (!lastCommittedBlock) {
return this.shortCircuitRecentBlocks(selectedBlocks);
}

const sameChainBlocks = this.filterOutForksBeforeStartingBlock(selectedBlocks, lastCommittedBlock);
const { committed } = await this.getLastParentchainSubnetBlock();
const { committed, submitted } = await this.getLastParentchainSubnetBlock();

return sameChainBlocks.map(b => {
let committedInSubnet = false;
let committedInParentChain = false;
if (b.number <= lastCommittedBlockInfo.number) {
committedInSubnet = true;
}
if (b.number <= committed.height) {
committedInParentChain = true;
}
return {
...b,
committedInSubnet,
committedInParentChain,
committedInSubnet: b.number <= lastCommittedBlockInfo.number,
committedInParentChain: b.number <= committed.height,
submittedInParentChain: b.number <= submitted.height,
};
});
}
Expand All @@ -127,7 +120,7 @@ export class BlockService {

public async getLastParentchainSubnetBlock() {
const { smartContractCommittedHash, smartContractCommittedHeight, smartContractHash, smartContractHeight } =
await this.parentChainClient.getLastAudittedBlock();
await this.getAndSetLastSubmittedBlockInfo();
return {
committed: {
height: smartContractCommittedHeight,
Expand Down Expand Up @@ -217,7 +210,7 @@ export class BlockService {
}

private async getSmartContractProcessingInfo(): Promise<{ processedUntil: number; isProcessing: boolean }> {
const { smartContractHeight, smartContractCommittedHash } = await this.parentChainClient.getLastAudittedBlock();
const { smartContractHeight, smartContractCommittedHash } = await this.getAndSetLastSubmittedBlockInfo();
const { timestamp } = await this.parentChainClient.getParentChainBlockBySubnetHash(smartContractCommittedHash);
let isProcessing = true;
const timeDiff = new Date().getTime() / 1000 - parseInt(timestamp.toString());
Expand All @@ -229,6 +222,17 @@ export class BlockService {
};
}

private async getAndSetLastSubmittedBlockInfo() {
const lastSubmittedBlockInfo = await this.blockStorage.getLastSubmittedBlockInfo();
// Not exist, we need to call the parentchain node and set the value
if (!lastSubmittedBlockInfo) {
const result = await this.parentChainClient.getLastAudittedBlock();
await this.blockStorage.setLastSubmittedToParentchainBlockInfo(result);
return result;
}
return lastSubmittedBlockInfo;
}

/**
In order to insert into the queue. we need it satisfy any of the below condition
Expand Down Expand Up @@ -260,7 +264,7 @@ export class BlockService {
}

const lastBLock = chainToFilter[chainToFilter.length - 1];
const startingPointer = startingBlock && startingBlock.number <= lastBLock.number? startingBlock : lastBLock;
const startingPointer = startingBlock && startingBlock.number <= lastBLock.number ? startingBlock : lastBLock;
const onChainHash = [startingPointer.hash];
let parentHashPointer = startingPointer.parentHash;
// Track back through the parentChain hash, if found then mark them as on the same chain
Expand All @@ -287,6 +291,7 @@ export class BlockService {
...b,
committedInSubnet: false,
committedInParentChain: false,
submittedInParentChain: false,
};
});
}
Expand Down
11 changes: 11 additions & 0 deletions backend/src/storage/block.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { SmartContractAuditedBlockInfo } from '../client/parentchain';
import { MAX_NUM_OF_BLOCKS_IN_HISTORY } from '../config';
import { Db } from './base';

const TYPE = 'BLOCK';
// In case of no new blocks in 60s, we declare the block componenet of the system is not operational
const STATUS_KEY = 'BLOCK_STATUS';
const TTL = 60;
const CHECK_PARENTCHAIN_TTL = 2;

const LATEST_COMMITTEDBLOCK_KEY = 'LATEST_COMMITTED_BLOCK';
const LATEST_PARENTCHAIN_SUBMITTED_KEY = 'LATEST_PARENTCHAIN_SUBMITTED_BLOCKINFO';

/**
This class is created so that we can easily swap with real DB without making changes to any other files.
Expand Down Expand Up @@ -58,6 +61,14 @@ export class BlockStorage {
async getStatus(): Promise<boolean> {
return this.db.get(STATUS_KEY) || false;
}

async getLastSubmittedBlockInfo(): Promise<SmartContractAuditedBlockInfo> {
return this.db.get(LATEST_PARENTCHAIN_SUBMITTED_KEY);
}

async setLastSubmittedToParentchainBlockInfo(blockInfo: SmartContractAuditedBlockInfo) {
this.db.set(LATEST_PARENTCHAIN_SUBMITTED_KEY, blockInfo, CHECK_PARENTCHAIN_TTL);
}
}

export interface StoredBlock {
Expand Down
4 changes: 4 additions & 0 deletions backend/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -356,11 +356,15 @@ definitions:
committedInParentChain:
description: This boolean value is to indicate whether this block has been confirmed in the parent chain smart contract
type: boolean
submittedInParentChain:
description: This boolean value is to indicate whether this block has been submitted in the parent chain smart contract and waiting for the confirmation
type: boolean
required:
- hash
- number
- committedInParentChain
- committedInSubnet
- submittedInParentChain

schemes:
- https
Expand Down

0 comments on commit 7520f18

Please sign in to comment.