Skip to content

Commit d085ac0

Browse files
authored
feat: store block and hash info (#764)
add BlockInfoDAO to store the highest block references: #764 , #707
1 parent 2a0cddb commit d085ac0

File tree

6 files changed

+124
-3
lines changed

6 files changed

+124
-3
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/* tslint:disable:no-relative-imports */
2+
import { describe } from 'riteway'
3+
import { runtimeId, setUpDb } from '../../tests/helpers/utils'
4+
import { BlockInfoDAO } from './BlockInfoDAO'
5+
6+
const prefix = runtimeId()
7+
8+
describe('BlockInfoDAO.insertBlockInfo', async assert => {
9+
const db = await setUpDb(prefix)
10+
const { result, mongoClient } = await db.collection('blockchainInfo')
11+
const blockchainInfoCollection = result
12+
const blockInfoDAO = new BlockInfoDAO(blockchainInfoCollection)
13+
await blockInfoDAO.start()
14+
const expected = { height: 12345, hash: 'this-is-a-hash', previousHash: 'this-is-a-parent-hash' }
15+
await blockInfoDAO.insertBlockInfo(expected)
16+
const actual = await blockchainInfoCollection.find().limit(1).next()
17+
18+
assert({
19+
given: 'a lightBlock',
20+
should: 'store the block in mongodb',
21+
actual,
22+
expected,
23+
})
24+
25+
await mongoClient.close()
26+
await db.teardown()
27+
})
28+
29+
describe('BlockInfoDAO.getHighestBlock', async assert => {
30+
const db = await setUpDb(prefix)
31+
const { result, mongoClient } = await db.collection('blockchainInfo')
32+
const blockchainInfoCollection = result
33+
const blockInfoDAO = new BlockInfoDAO(blockchainInfoCollection)
34+
await blockInfoDAO.start()
35+
await blockInfoDAO.insertBlockInfo({ height: 1234, hash: 'wrong-hash', previousHash: 'wrong-hash-parent' })
36+
const expected = { height: 54321, hash: 'good-hash', previousHash: 'parentHash '}
37+
await blockInfoDAO.insertBlockInfo(expected)
38+
const actual = await blockInfoDAO.getHighestBlock()
39+
40+
assert({
41+
given: 'multiple blocks in mongo',
42+
should: 'retrieve the block with the greatest height',
43+
actual,
44+
expected,
45+
})
46+
47+
await mongoClient.close()
48+
await db.teardown()
49+
})
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { LightBlock } from 'Messaging/Messages'
2+
import { inject, injectable } from 'inversify'
3+
import { Collection } from 'mongodb'
4+
5+
@injectable()
6+
export class BlockInfoDAO {
7+
private readonly blockchainInfo: Collection
8+
9+
constructor(
10+
@inject('BlockchainInfoCollection') blockchainInfo: Collection,
11+
) {
12+
this.blockchainInfo = blockchainInfo
13+
}
14+
15+
readonly start = async () => {
16+
await this.blockchainInfo.createIndex({ height: 1, hash: 1 }, { unique: true })
17+
}
18+
19+
readonly insertBlockInfo = (lightBlock: LightBlock) =>
20+
this.blockchainInfo.insertOne(lightBlock)
21+
22+
readonly getHighestBlock = async (): Promise<LightBlock> => {
23+
const cursor = this.blockchainInfo.find().sort({height: -1}).limit(1)
24+
return await cursor.next()
25+
}
26+
}

src/BlockchainWriter/BlockchainWriter.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,14 @@ export class BlockchainWriter {
4545
const db = await this.mongoClient.db()
4646

4747
const blockchainWriterCollection = db.collection('blockchainWriter')
48+
const blockchainInfoCollection = db.collection('blockchainInfo')
4849

49-
const container = createContainer(this.configuration, this.logger, blockchainWriterCollection)
50+
const container = createContainer(
51+
this.configuration,
52+
this.logger,
53+
blockchainWriterCollection,
54+
blockchainInfoCollection,
55+
)
5056

5157
this.messaging = container.get('Messaging') as Messaging
5258
await this.messaging.start()
@@ -77,6 +83,7 @@ const createContainer = (
7783
configuration: BlockchainWriterConfiguration,
7884
logger: Pino.Logger,
7985
blockchainWriterCollection: Collection,
86+
blockchainInfo: Collection,
8087
) => {
8188
const container = new Container()
8289

@@ -86,7 +93,12 @@ const createContainer = (
8693
container.bind<DAO>('DAO').to(DAO)
8794

8895
container.bind<Pino.Logger>('Logger').toConstantValue(logger)
89-
container.bind<Collection>('BlockchainWriterCollection').toConstantValue(blockchainWriterCollection)
96+
container
97+
.bind<Collection>('BlockchainWriterCollection')
98+
.toConstantValue(blockchainWriterCollection)
99+
container
100+
.bind<Collection>('BlockchainInfoCollection')
101+
.toConstantValue(blockchainInfo)
90102

91103
const exchangesMessaging = pick(['poetAnchorDownloaded', 'claimsDownloaded'], configuration.exchanges)
92104
container.bind<Messaging>('Messaging').toConstantValue(new Messaging(configuration.rabbitmqUrl, exchangesMessaging))

tests/helpers/database.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,35 @@ export const dbHelper = () => {
3535
await mongoClient.close()
3636
}
3737

38+
const dbExecuteWithClient = async (...fns: any) => {
39+
const mongodbUrl = loadConfigurationWithDefaults({
40+
MONGODB_USER: 'root',
41+
MONGODB_PASSWORD: 'rootPass',
42+
MONGODB_DATABASE: tempDbName,
43+
}).mongodbUrl
44+
45+
console.log(`Connecting to temporary DB (${mongodbUrl})...`)
46+
const mongoClient = await MongoClient.connect(
47+
mongodbUrl,
48+
{ authSource: 'admin' },
49+
)
50+
let result
51+
52+
try {
53+
const db = await mongoClient.db()
54+
result = await pipeP(...fns)(db)
55+
} catch (err) {
56+
console.log(err)
57+
}
58+
return { result, mongoClient }
59+
}
60+
3861
return {
62+
collection: async (collection: string = 'poet') => {
63+
if (setupCalled) return await dbExecuteWithClient(async (db: any) => db.collection(collection))
64+
else console.log('ERROR: setup() must be called before collection()')
65+
return
66+
},
3967
setup: async (dbNamePrefix: string = null, dbUser: string = null, dbPassword: string = null) => {
4068
tempDbName = dbNamePrefix || id
4169
const tempDbUser = dbUser || `test-${id}`
@@ -57,7 +85,7 @@ export const dbHelper = () => {
5785
if (setupCalled) {
5886
console.log(`Deleting temporary DB (${tempDbName})...`)
5987
await dbExecute(async (db: any) => db.dropDatabase())
60-
} else console.log('ERROR: setup() must be called vefore teardown()')
88+
} else console.log('ERROR: setup() must be called before teardown()')
6189
},
6290
}
6391
}

tests/helpers/utils.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export const createDatabase = async (prefix: string) => {
1313
return {
1414
teardown: db.teardown,
1515
settings: await db.setup(prefix),
16+
collection: db.collection,
1617
}
1718
}
1819

@@ -24,6 +25,10 @@ const defaultBlockchainSettings = {
2425
UPLOAD_CLAIM_INTERVAL_IN_SECONDS: 5,
2526
}
2627

28+
export const setUpDb = async (prefix: string) => {
29+
return await createDatabase(prefix)
30+
}
31+
2732
export const setUpServerAndDb = async ({
2833
PREFIX,
2934
NODE_PORT,

tests/unit/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import '../../src/API/Middlewares/RequestValidationMiddleware.test'
55
import '../../src/API/Middlewares/RequestValidationMiddleware.test.ts'
66
import '../../src/BlockchainReader/Bitcoin.test'
77
import '../../src/BlockchainWriter/Bitcoin.test'
8+
import '../../src/BlockchainWriter/BlockInfoDAO.test'
89
import '../../src/BlockchainWriter/Exceptions.test'
910
import '../../src/Configuration.test'
1011
import '../../src/Extensions/Array.test.ts'

0 commit comments

Comments
 (0)