mirror of
https://github.com/IT4Change/gradido.git
synced 2026-03-01 12:44:43 +00:00
refactor, finalize export to blockchain file
This commit is contained in:
parent
f09c8e917d
commit
290a6a4f27
@ -24,6 +24,7 @@
|
||||
"jsonrpc-ts-client": "^0.2.3",
|
||||
"log4js": "^6.9.1",
|
||||
"mysql2": "^3.15.3",
|
||||
"sodium-native": "5.0.9",
|
||||
"typescript": "^5.8.3",
|
||||
"uuid": "^8.3.2",
|
||||
"valibot": "1.1.0",
|
||||
@ -342,6 +343,18 @@
|
||||
|
||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"bare-addon-resolve": ["bare-addon-resolve@1.9.5", "", { "dependencies": { "bare-module-resolve": "^1.10.0", "bare-semver": "^1.0.0" }, "peerDependencies": { "bare-url": "*" }, "optionalPeers": ["bare-url"] }, "sha512-XdqrG73zLK9LDfblOJwoAxmJ+7YdfRW4ex46+f4L+wPhk7H7LDrRMAbBw8s8jkxeEFpUenyB7QHnv0ErAWd3Yg=="],
|
||||
|
||||
"bare-module-resolve": ["bare-module-resolve@1.11.2", "", { "dependencies": { "bare-semver": "^1.0.0" }, "peerDependencies": { "bare-url": "*" }, "optionalPeers": ["bare-url"] }, "sha512-HIBu9WacMejg3Dz4X1v6lJjp7ECnwpujvuLub+8I7JJLRwJaGxWMzGYvieOoS9R1n5iRByvTmLtIdPbwjfRgiQ=="],
|
||||
|
||||
"bare-os": ["bare-os@3.6.2", "", {}, "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A=="],
|
||||
|
||||
"bare-path": ["bare-path@3.0.0", "", { "dependencies": { "bare-os": "^3.0.1" } }, "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw=="],
|
||||
|
||||
"bare-semver": ["bare-semver@1.0.2", "", {}, "sha512-ESVaN2nzWhcI5tf3Zzcq9aqCZ676VWzqw07eEZ0qxAcEOAFYBa0pWq8sK34OQeHLY3JsfKXZS9mDyzyxGjeLzA=="],
|
||||
|
||||
"bare-url": ["bare-url@2.3.2", "", { "dependencies": { "bare-path": "^3.0.0" } }, "sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw=="],
|
||||
|
||||
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
||||
|
||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.8.20", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-JMWsdF+O8Orq3EMukbUN1QfbLK9mX2CkUmQBcW2T0s8OmdAUL5LLM/6wFwSrqXzlXB13yhyK9gTKS1rIizOduQ=="],
|
||||
@ -862,6 +875,8 @@
|
||||
|
||||
"regenerator-runtime": ["regenerator-runtime@0.13.11", "", {}, "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="],
|
||||
|
||||
"require-addon": ["require-addon@1.1.0", "", { "dependencies": { "bare-addon-resolve": "^1.3.0", "bare-url": "^2.1.0" } }, "sha512-KbXAD5q2+v1GJnkzd8zzbOxchTkStSyJZ9QwoCq3QwEXAaIlG3wDYRZGzVD357jmwaGY7hr5VaoEAL0BkF0Kvg=="],
|
||||
|
||||
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
|
||||
|
||||
"resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],
|
||||
@ -906,6 +921,8 @@
|
||||
|
||||
"slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
||||
|
||||
"sodium-native": ["sodium-native@5.0.9", "", { "dependencies": { "require-addon": "^1.1.0", "which-runtime": "^1.2.1" } }, "sha512-6fpu3d6zdrRpLhuV3CDIBO5g90KkgaeR+c3xvDDz0ZnDkAlqbbPhFW7zhMJfsskfZ9SuC3SvBbqvxcECkXRyKw=="],
|
||||
|
||||
"sonic-boom": ["sonic-boom@4.2.0", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww=="],
|
||||
|
||||
"source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="],
|
||||
@ -1006,6 +1023,8 @@
|
||||
|
||||
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
|
||||
"which-runtime": ["which-runtime@1.3.2", "", {}, "sha512-5kwCfWml7+b2NO7KrLMhYihjRx0teKkd3yGp1Xk5Vaf2JGdSh+rgVhEALAD9c/59dP+YwJHXoEO7e8QPy7gOkw=="],
|
||||
|
||||
"wide-align": ["wide-align@1.1.5", "", { "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } }, "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg=="],
|
||||
|
||||
"wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||
|
||||
@ -38,6 +38,7 @@
|
||||
"jsonrpc-ts-client": "^0.2.3",
|
||||
"log4js": "^6.9.1",
|
||||
"mysql2": "^3.15.3",
|
||||
"sodium-native": "5.0.9",
|
||||
"typescript": "^5.8.3",
|
||||
"uuid": "^8.3.2",
|
||||
"valibot": "1.1.0",
|
||||
|
||||
@ -1,32 +1,31 @@
|
||||
import { drizzle, MySql2Database } from 'drizzle-orm/mysql2'
|
||||
import mysql from 'mysql2/promise'
|
||||
import { InMemoryBlockchain } from 'gradido-blockchain-js'
|
||||
import { Filter, Profiler, SearchDirection_ASC } from 'gradido-blockchain-js'
|
||||
import { getLogger, Logger } from 'log4js'
|
||||
|
||||
import { HieroId, Uuidv4 } from '../../schemas/typeGuard.schema'
|
||||
import { Uuidv4 } from '../../schemas/typeGuard.schema'
|
||||
|
||||
import { KeyPairCacheManager } from '../../cache/KeyPairCacheManager'
|
||||
import { loadConfig } from '../../bootstrap/init'
|
||||
import { CONFIG } from '../../config'
|
||||
import { LOG4JS_BASE_CATEGORY } from '../../config/const'
|
||||
|
||||
export type CommunityContext = {
|
||||
communityId: string
|
||||
blockchain: InMemoryBlockchain
|
||||
topicId: HieroId
|
||||
}
|
||||
import { heapStats } from 'bun:jsc'
|
||||
import { CommunityContext } from './valibot.schema'
|
||||
import { bytesToMbyte } from './utils'
|
||||
|
||||
export class Context {
|
||||
public logger: Logger
|
||||
public db: MySql2Database
|
||||
public communities: Map<string, CommunityContext>
|
||||
public cache: KeyPairCacheManager
|
||||
private timeUsed: Profiler
|
||||
|
||||
constructor(logger: Logger, db: MySql2Database, cache: KeyPairCacheManager) {
|
||||
this.logger = logger
|
||||
this.db = db
|
||||
this.cache = cache
|
||||
this.communities = new Map<string, CommunityContext>()
|
||||
this.timeUsed = new Profiler()
|
||||
}
|
||||
|
||||
static async create(): Promise<Context> {
|
||||
@ -53,4 +52,29 @@ export class Context {
|
||||
}
|
||||
return community
|
||||
}
|
||||
|
||||
logRuntimeStatistics() {
|
||||
this.logger.info(`${this.timeUsed.string()} for synchronizing to blockchain`)
|
||||
const runtimeStats = heapStats()
|
||||
this.logger.info(
|
||||
`Memory Statistics: heap size: ${bytesToMbyte(runtimeStats.heapSize)} MByte, heap capacity: ${bytesToMbyte(runtimeStats.heapCapacity)} MByte, extra memory: ${bytesToMbyte(runtimeStats.extraMemorySize)} MByte`
|
||||
)
|
||||
}
|
||||
|
||||
logBlogchain(communityUuid: Uuidv4) {
|
||||
const communityContext = this.getCommunityContextByUuid(communityUuid)
|
||||
const f = new Filter()
|
||||
f.pagination.size = 0
|
||||
f.searchDirection = SearchDirection_ASC
|
||||
|
||||
const transactions = communityContext.blockchain.findAll(f)
|
||||
for(let i = 0; i < transactions.size(); i++) {
|
||||
const transaction = transactions.get(i)
|
||||
const confirmedTransaction = transaction?.getConfirmedTransaction()
|
||||
this.logger.info(confirmedTransaction?.toJson(true))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: move into utils
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
export enum TransactionTypeId {
|
||||
CREATION = 1,
|
||||
SEND = 2,
|
||||
RECEIVE = 3,
|
||||
// This is a virtual property, never occurring on the database
|
||||
DECAY = 4,
|
||||
LINK_SUMMARY = 5,
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
import { ConfirmedTransaction, Filter, InteractionSerialize, Profiler, SearchDirection_ASC } from 'gradido-blockchain-js'
|
||||
import path from 'node:path'
|
||||
import { CONFIG } from '../../config'
|
||||
import fs from 'node:fs'
|
||||
import { bytesToKbyte } from './utils'
|
||||
import { calculateOneHashStep } from './utils'
|
||||
import { Context } from './Context'
|
||||
import { CommunityContext } from './valibot.schema'
|
||||
|
||||
export function exportAllCommunities(context: Context, batchSize: number) {
|
||||
const timeUsed = new Profiler()
|
||||
for(const communityContext of context.communities.values()) {
|
||||
exportCommunity(communityContext, context, batchSize)
|
||||
}
|
||||
context.logger.info(`time used for exporting communities to binary file: ${timeUsed.string()}`)
|
||||
}
|
||||
|
||||
export function exportCommunity(communityContext: CommunityContext, context: Context, batchSize: number) {
|
||||
// write as binary file for GradidoNode
|
||||
const f = new Filter()
|
||||
f.pagination.size = batchSize
|
||||
f.pagination.page = 1
|
||||
f.searchDirection = SearchDirection_ASC
|
||||
const binFilePath = prepareFolder(communityContext)
|
||||
|
||||
let lastTransactionCount = 0
|
||||
let hash = Buffer.alloc(32, 0)
|
||||
do {
|
||||
const transactions = communityContext.blockchain.findAll(f)
|
||||
lastTransactionCount = transactions.size()
|
||||
|
||||
for (let i = 0; i < lastTransactionCount; i++) {
|
||||
const confirmedTransaction = transactions.get(i)?.getConfirmedTransaction()
|
||||
const transactionNr = f.pagination.page * batchSize + i
|
||||
if (!confirmedTransaction) {
|
||||
throw new Error(`invalid TransactionEntry at index: ${transactionNr} `)
|
||||
}
|
||||
hash = exportTransaction(confirmedTransaction, hash, binFilePath)
|
||||
}
|
||||
f.pagination.page++
|
||||
} while (lastTransactionCount === batchSize)
|
||||
|
||||
fs.appendFileSync(binFilePath, hash!)
|
||||
context.logger.info(`binary file for community ${communityContext.communityId} written to ${binFilePath}`)
|
||||
context.logger.info(
|
||||
`transactions count: ${(f.pagination.page - 1) * batchSize + lastTransactionCount}, size: ${bytesToKbyte(fs.statSync(binFilePath).size)} KByte`
|
||||
)
|
||||
}
|
||||
|
||||
function exportTransaction(confirmedTransaction: ConfirmedTransaction, hash: Buffer<ArrayBuffer>, binFilePath: string): Buffer<ArrayBuffer> {
|
||||
const sizeBuffer = Buffer.alloc(2)
|
||||
const interactionSerialize = new InteractionSerialize(confirmedTransaction)
|
||||
const binBlock = interactionSerialize.run()
|
||||
if (!binBlock) {
|
||||
throw new Error(`invalid TransactionEntry at index: ${confirmedTransaction.getId()}, serialize into protobuf format failed`)
|
||||
}
|
||||
|
||||
hash = calculateOneHashStep(hash, binBlock.data())
|
||||
sizeBuffer.writeUInt16LE(binBlock.size(), 0)
|
||||
fs.appendFileSync(binFilePath, sizeBuffer)
|
||||
fs.appendFileSync(binFilePath, binBlock.data())
|
||||
return hash
|
||||
}
|
||||
|
||||
function prepareFolder(communityContext: CommunityContext): string {
|
||||
const binFileFolder = path.join(
|
||||
CONFIG.DLT_GRADIDO_NODE_SERVER_HOME_FOLDER,
|
||||
'.gradido',
|
||||
communityContext.folder,
|
||||
)
|
||||
const binFilePath = path.join(binFileFolder, 'blk00000001.dat')
|
||||
// make sure we work with a clean folder, rm beforehand with all content
|
||||
fs.rmSync(binFileFolder, { recursive: true })
|
||||
fs.mkdirSync(binFileFolder, { recursive: true })
|
||||
return binFilePath
|
||||
}
|
||||
@ -28,6 +28,7 @@ function addToBlockchain(builder: GradidoTransactionBuilder, blockchain: InMemor
|
||||
const transaction = builder.build()
|
||||
const transactionId = new HieroTransactionId(createdAtTimestamp, defaultHieroAccount)
|
||||
const interactionSerialize = new InteractionSerialize(transactionId)
|
||||
|
||||
try {
|
||||
const result = blockchain.createAndAddConfirmedTransaction(transaction, interactionSerialize.run(), createdAtTimestamp)
|
||||
return result
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { Context } from './Context'
|
||||
import { CommunityContext } from './Context'
|
||||
import { loadCommunities } from './database'
|
||||
import { HieroId, hieroIdSchema } from '../../schemas/typeGuard.schema'
|
||||
import * as v from 'valibot'
|
||||
@ -7,6 +6,7 @@ import { InMemoryBlockchainProvider } from 'gradido-blockchain-js'
|
||||
import { generateKeyPairCommunity } from './keyPair'
|
||||
import { communityDbToCommunity } from './convert'
|
||||
import { addCommunityRootTransaction } from './blockchain'
|
||||
import { CommunityContext } from './valibot.schema'
|
||||
|
||||
export async function bootstrap(): Promise<Context> {
|
||||
const context = await Context.create()
|
||||
@ -35,7 +35,8 @@ async function bootstrapCommunities(context: Context): Promise<Map<string, Commu
|
||||
communities.set(communityDb.communityUuid, {
|
||||
communityId: communityDb.uniqueAlias,
|
||||
blockchain,
|
||||
topicId
|
||||
topicId,
|
||||
folder: communityDb.uniqueAlias.replace(/[^a-zA-Z0-9]/g, '_'),
|
||||
})
|
||||
|
||||
generateKeyPairCommunity(communityDb, context.cache, topicId)
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { InputTransactionType } from '../../data/InputTransactionType.enum'
|
||||
import { CommunityDb, TransactionDb, TransactionTypeId, CreatedUserDb, TransactionLinkDb } from './database'
|
||||
import { CommunityDb, TransactionDb, CreatedUserDb, TransactionLinkDb } from './valibot.schema'
|
||||
import { Community, communitySchema, transactionSchema, Transaction, TransactionInput } from '../../schemas/transaction.schema'
|
||||
import { AccountType } from '../../data/AccountType.enum'
|
||||
import { gradidoAmountSchema, HieroId, memoSchema, timeoutDurationSchema } from '../../schemas/typeGuard.schema'
|
||||
import * as v from 'valibot'
|
||||
import { TransactionTypeId } from './TransactionTypeId'
|
||||
|
||||
export function getInputTransactionTypeFromTypeId(typeId: TransactionTypeId): InputTransactionType {
|
||||
switch (typeId) {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import { memoSchema, uuidv4Schema, identifierSeedSchema, gradidoAmountSchema } from '../../schemas/typeGuard.schema'
|
||||
import { dateSchema, booleanSchema } from '../../schemas/typeConverter.schema'
|
||||
import * as v from 'valibot'
|
||||
import { LOG4JS_BASE_CATEGORY } from '../../config/const'
|
||||
import { getLogger } from 'log4js'
|
||||
@ -8,61 +6,17 @@ import { communitiesTable, transactionLinksTable, transactionsTable, usersTable
|
||||
import { asc, sql, eq, isNotNull } from 'drizzle-orm'
|
||||
import { alias } from 'drizzle-orm/mysql-core'
|
||||
import { GradidoUnit } from 'gradido-blockchain-js'
|
||||
|
||||
export const createdUserDbSchema = v.object({
|
||||
gradidoId: uuidv4Schema,
|
||||
communityUuid: uuidv4Schema,
|
||||
createdAt: dateSchema,
|
||||
})
|
||||
|
||||
export const userDbSchema = v.object({
|
||||
gradidoId: uuidv4Schema,
|
||||
communityUuid: uuidv4Schema,
|
||||
})
|
||||
|
||||
export enum TransactionTypeId {
|
||||
CREATION = 1,
|
||||
SEND = 2,
|
||||
RECEIVE = 3,
|
||||
// This is a virtual property, never occurring on the database
|
||||
DECAY = 4,
|
||||
LINK_SUMMARY = 5,
|
||||
}
|
||||
|
||||
export const transactionDbSchema = v.object({
|
||||
typeId: v.enum(TransactionTypeId),
|
||||
amount: gradidoAmountSchema,
|
||||
balanceDate: dateSchema,
|
||||
memo: memoSchema,
|
||||
creationDate: v.nullish(dateSchema),
|
||||
user: userDbSchema,
|
||||
linkedUser: userDbSchema,
|
||||
transactionLinkCode: v.nullish(identifierSeedSchema),
|
||||
})
|
||||
|
||||
export const transactionLinkDbSchema = v.object({
|
||||
user: userDbSchema,
|
||||
code: identifierSeedSchema,
|
||||
amount: gradidoAmountSchema,
|
||||
memo: memoSchema,
|
||||
createdAt: dateSchema,
|
||||
validUntil: dateSchema,
|
||||
})
|
||||
|
||||
export const communityDbSchema = v.object({
|
||||
foreign: booleanSchema,
|
||||
communityUuid: uuidv4Schema,
|
||||
name: v.string(),
|
||||
creationDate: dateSchema,
|
||||
userMinCreatedAt: dateSchema,
|
||||
uniqueAlias: v.string(),
|
||||
})
|
||||
|
||||
export type TransactionDb = v.InferOutput<typeof transactionDbSchema>
|
||||
export type UserDb = v.InferOutput<typeof userDbSchema>
|
||||
export type CreatedUserDb = v.InferOutput<typeof createdUserDbSchema>
|
||||
export type TransactionLinkDb = v.InferOutput<typeof transactionLinkDbSchema>
|
||||
export type CommunityDb = v.InferOutput<typeof communityDbSchema>
|
||||
import {
|
||||
CommunityDb,
|
||||
communityDbSchema,
|
||||
CreatedUserDb,
|
||||
createdUserDbSchema,
|
||||
TransactionDb,
|
||||
transactionDbSchema,
|
||||
TransactionLinkDb,
|
||||
transactionLinkDbSchema
|
||||
} from './valibot.schema'
|
||||
import { TransactionTypeId } from './TransactionTypeId'
|
||||
|
||||
const logger = getLogger(`${LOG4JS_BASE_CATEGORY}.migrations.db-v2.7.0_to_blockchain-v3.6.blockchain`)
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
import { mysqlTable, unique, int, varchar, char, datetime, tinyint, decimal, index } from 'drizzle-orm/mysql-core'
|
||||
import { sql } from 'drizzle-orm'
|
||||
|
||||
|
||||
// use only fields needed in the migration, after update the rest of the project, import database instead
|
||||
export const communitiesTable = mysqlTable('communities', {
|
||||
foreign: tinyint().default(1).notNull(),
|
||||
@ -14,7 +13,6 @@ export const communitiesTable = mysqlTable('communities', {
|
||||
unique('uuid_key').on(table.communityUuid),
|
||||
])
|
||||
|
||||
|
||||
export const usersTable = mysqlTable('users', {
|
||||
id: int().autoincrement().notNull(),
|
||||
gradidoId: char('gradido_id', { length: 36 }).notNull(),
|
||||
@ -27,20 +25,19 @@ export const usersTable = mysqlTable('users', {
|
||||
|
||||
export const transactionsTable = mysqlTable('transactions', {
|
||||
id: int().autoincrement().notNull(),
|
||||
typeId: int("type_id").default(sql`NULL`),
|
||||
transactionLinkId: int("transaction_link_id").default(sql`NULL`),
|
||||
typeId: int('type_id').default(sql`NULL`),
|
||||
transactionLinkId: int('transaction_link_id').default(sql`NULL`),
|
||||
amount: decimal({ precision: 40, scale: 20 }).default(sql`NULL`),
|
||||
balanceDate: datetime("balance_date", { mode: 'string', fsp: 3 }).default(sql`current_timestamp(3)`).notNull(),
|
||||
balanceDate: datetime('balance_date', { mode: 'string', fsp: 3 }).default(sql`current_timestamp(3)`).notNull(),
|
||||
memo: varchar({ length: 255 }).notNull(),
|
||||
creationDate: datetime("creation_date", { mode: 'string', fsp: 3 }).default(sql`NULL`),
|
||||
userId: int("user_id").notNull(),
|
||||
linkedUserId: int("linked_user_id").default(sql`NULL`),
|
||||
creationDate: datetime('creation_date', { mode: 'string', fsp: 3 }).default(sql`NULL`),
|
||||
userId: int('user_id').notNull(),
|
||||
linkedUserId: int('linked_user_id').default(sql`NULL`),
|
||||
},
|
||||
(table) => [
|
||||
index("user_id").on(table.userId),
|
||||
index('user_id').on(table.userId),
|
||||
])
|
||||
|
||||
|
||||
export const transactionLinksTable = mysqlTable('transaction_links', {
|
||||
id: int().autoincrement().notNull(),
|
||||
userId: int().notNull(),
|
||||
|
||||
@ -1,18 +1,12 @@
|
||||
import {
|
||||
InMemoryBlockchain,
|
||||
Filter,
|
||||
SearchDirection_ASC,
|
||||
Profiler
|
||||
} from 'gradido-blockchain-js'
|
||||
import { Logger } from 'log4js'
|
||||
import { bootstrap } from './bootstrap'
|
||||
import { heapStats } from 'bun:jsc'
|
||||
import { onShutdown } from '../../../../shared/src/helper/onShutdown'
|
||||
import { syncDbWithBlockchainContext } from './interaction/syncDbWithBlockchain/syncDbWithBlockchain.context'
|
||||
import { exportAllCommunities } from './binaryExport'
|
||||
import { Filter } from 'gradido-blockchain-js'
|
||||
|
||||
const BATCH_SIZE = 100
|
||||
|
||||
async function main() {
|
||||
const timeUsed = new Profiler()
|
||||
// prepare in memory blockchains
|
||||
const context = await bootstrap()
|
||||
onShutdown(async (reason, error) => {
|
||||
@ -22,42 +16,19 @@ async function main() {
|
||||
}
|
||||
})
|
||||
|
||||
// synchronize to blockchain
|
||||
const BATCH_SIZE = 100
|
||||
// synchronize to in memory blockchain
|
||||
await syncDbWithBlockchainContext(context, BATCH_SIZE)
|
||||
|
||||
// write as binary file for GradidoNode
|
||||
exportAllCommunities(context, BATCH_SIZE)
|
||||
|
||||
// log runtime statistics
|
||||
context.logRuntimeStatistics()
|
||||
|
||||
try {
|
||||
await syncDbWithBlockchainContext(context, BATCH_SIZE)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
throw e
|
||||
}
|
||||
context.logger.info(`${timeUsed.string()} for synchronizing to blockchain`)
|
||||
const runtimeStats = heapStats()
|
||||
context.logger.info(
|
||||
`Memory Statistics: heap size: ${bytesToMbyte(runtimeStats.heapSize)} MByte, heap capacity: ${bytesToMbyte(runtimeStats.heapCapacity)} MByte, extra memory: ${bytesToMbyte(runtimeStats.extraMemorySize)} MByte`
|
||||
)
|
||||
// needed because of shutdown handler (TODO: fix shutdown handler)
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
function bytesToMbyte(bytes: number): string {
|
||||
return (bytes / 1024 / 1024).toFixed(4)
|
||||
}
|
||||
|
||||
function logBlogchain(logger: Logger, blockchain: InMemoryBlockchain) {
|
||||
const f = new Filter()
|
||||
f.pagination.size = 0
|
||||
f.searchDirection = SearchDirection_ASC
|
||||
|
||||
const transactions = blockchain.findAll(f)
|
||||
for(let i = 0; i < transactions.size(); i++) {
|
||||
const transaction = transactions.get(i)
|
||||
const confirmedTransaction = transaction?.getConfirmedTransaction()
|
||||
logger.info(confirmedTransaction?.toJson(true))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
main().catch((e) => {
|
||||
// biome-ignore lint/suspicious/noConsole: maybe logger isn't initialized here
|
||||
console.error(e)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { loadDeletedTransactionLinks } from '../../database'
|
||||
import { TransactionsSyncRole } from './TransactionsSync.role'
|
||||
import { TransactionDb } from '../../database'
|
||||
import { TransactionDb } from '../../valibot.schema'
|
||||
|
||||
export class DeletedTransactionLinksSyncRole extends TransactionsSyncRole {
|
||||
itemTypeName(): string {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { TransactionLinkDb, loadTransactionLinks } from '../../database'
|
||||
import { TransactionLinkDb } from '../../valibot.schema'
|
||||
import { loadTransactionLinks } from '../../database'
|
||||
import { transactionLinkDbToTransaction } from '../../convert'
|
||||
import { addTransaction } from '../../blockchain'
|
||||
import { AbstractSyncRole } from './AbstractSync.role'
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { TransactionDb, loadTransactions } from '../../database'
|
||||
import { TransactionDb } from '../../valibot.schema'
|
||||
import { loadTransactions } from '../../database'
|
||||
import { transactionDbToTransaction } from '../../convert'
|
||||
import { addTransaction } from '../../blockchain'
|
||||
import { AbstractSyncRole } from './AbstractSync.role'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { CreatedUserDb } from '../../database'
|
||||
import { CreatedUserDb } from '../../valibot.schema'
|
||||
import { AbstractSyncRole } from './AbstractSync.role'
|
||||
import { loadUsers } from '../../database'
|
||||
import { generateKeyPairUserAccount } from '../../keyPair'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { CommunityDb, UserDb } from './database'
|
||||
import { CommunityDb, UserDb } from './valibot.schema'
|
||||
import { KeyPairCacheManager } from '../../cache/KeyPairCacheManager'
|
||||
import { KeyPairIdentifierLogic } from '../../data/KeyPairIdentifier.logic'
|
||||
import { KeyPairEd25519, MemoryBlock, MemoryBlockPtr } from 'gradido-blockchain-js'
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
import { crypto_generichash_batch, crypto_generichash_KEYBYTES } from 'sodium-native'
|
||||
|
||||
export function bytesToMbyte(bytes: number): string {
|
||||
return (bytes / 1024 / 1024).toFixed(4)
|
||||
}
|
||||
|
||||
export function bytesToKbyte(bytes: number): string {
|
||||
return (bytes / 1024).toFixed(0)
|
||||
}
|
||||
|
||||
export function calculateOneHashStep(hash: Buffer, data: Buffer): Buffer<ArrayBuffer> {
|
||||
const outputHash = Buffer.alloc(crypto_generichash_KEYBYTES, 0)
|
||||
crypto_generichash_batch(outputHash, [hash, data])
|
||||
return outputHash
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
import { memoSchema, uuidv4Schema, identifierSeedSchema, gradidoAmountSchema, hieroIdSchema } from '../../schemas/typeGuard.schema'
|
||||
import { dateSchema, booleanSchema } from '../../schemas/typeConverter.schema'
|
||||
import { TransactionTypeId } from './TransactionTypeId'
|
||||
import { InMemoryBlockchain } from 'gradido-blockchain-js'
|
||||
import * as v from 'valibot'
|
||||
|
||||
export const createdUserDbSchema = v.object({
|
||||
gradidoId: uuidv4Schema,
|
||||
communityUuid: uuidv4Schema,
|
||||
createdAt: dateSchema,
|
||||
})
|
||||
|
||||
export const userDbSchema = v.object({
|
||||
gradidoId: uuidv4Schema,
|
||||
communityUuid: uuidv4Schema,
|
||||
})
|
||||
|
||||
|
||||
export const transactionDbSchema = v.object({
|
||||
typeId: v.enum(TransactionTypeId),
|
||||
amount: gradidoAmountSchema,
|
||||
balanceDate: dateSchema,
|
||||
memo: memoSchema,
|
||||
creationDate: v.nullish(dateSchema),
|
||||
user: userDbSchema,
|
||||
linkedUser: userDbSchema,
|
||||
transactionLinkCode: v.nullish(identifierSeedSchema),
|
||||
})
|
||||
|
||||
export const transactionLinkDbSchema = v.object({
|
||||
user: userDbSchema,
|
||||
code: identifierSeedSchema,
|
||||
amount: gradidoAmountSchema,
|
||||
memo: memoSchema,
|
||||
createdAt: dateSchema,
|
||||
validUntil: dateSchema,
|
||||
})
|
||||
|
||||
export const communityDbSchema = v.object({
|
||||
foreign: booleanSchema,
|
||||
communityUuid: uuidv4Schema,
|
||||
name: v.string(),
|
||||
creationDate: dateSchema,
|
||||
userMinCreatedAt: dateSchema,
|
||||
uniqueAlias: v.string(),
|
||||
})
|
||||
|
||||
export const communityContextSchema = v.object({
|
||||
communityId: v.string(),
|
||||
blockchain: v.instance(InMemoryBlockchain, 'expect InMemoryBlockchain type'),
|
||||
topicId: hieroIdSchema,
|
||||
folder: v.pipe(
|
||||
v.string(),
|
||||
v.minLength(1, 'expect string length >= 1'),
|
||||
v.maxLength(255, 'expect string length <= 255'),
|
||||
v.regex(/^[a-zA-Z0-9-_]+$/,
|
||||
'expect string to be a valid (alphanumeric, _, -) folder name'),
|
||||
),
|
||||
})
|
||||
|
||||
export type TransactionDb = v.InferOutput<typeof transactionDbSchema>
|
||||
export type UserDb = v.InferOutput<typeof userDbSchema>
|
||||
export type CreatedUserDb = v.InferOutput<typeof createdUserDbSchema>
|
||||
export type TransactionLinkDb = v.InferOutput<typeof transactionLinkDbSchema>
|
||||
export type CommunityDb = v.InferOutput<typeof communityDbSchema>
|
||||
export type CommunityContext = v.InferOutput<typeof communityContextSchema>
|
||||
Loading…
x
Reference in New Issue
Block a user