Merge branch 'master' into mixin-for-creation-labels

This commit is contained in:
Moriz Wahl 2022-02-03 13:50:38 +01:00 committed by GitHub
commit 2d3f04c305
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 127 additions and 227 deletions

View File

@ -60,7 +60,7 @@ docker-compose -f docker-compose.yml up
- [frontend](./frontend) Wallet frontend
- [backend](./backend) GraphQL & Business logic backend
- [mariadb](./mariadb) Database backend
- [community_server](./community_server/) Business logic backend
- [community_server](./community_server/) Business logic backend (will be removed)
We are currently restructuring the service to reduce dependencies and unify business logic into one place. Furthermore the databases defined for each service will be unified into one.

View File

@ -4,7 +4,7 @@ import dotenv from 'dotenv'
dotenv.config()
const constants = {
DB_VERSION: '0015-admin_pending_creations',
DB_VERSION: '0016-transaction_signatures',
}
const server = {

View File

@ -195,7 +195,6 @@ export class AdminResolver {
transaction.transactionTypeId = 1
transaction.memo = pendingCreation.memo
transaction.received = receivedCallDate
transaction.blockchainTypeId = 1
transaction = await transactionRepository.save(transaction)
if (!transaction) throw new Error('Could not create transaction')

View File

@ -36,172 +36,6 @@ import { hasUserAmount, isHexPublicKey } from '../../util/validate'
import { LoginUserRepository } from '../../typeorm/repository/LoginUser'
import { RIGHTS } from '../../auth/RIGHTS'
/*
# Test
## Prepare
> sudo systemctl start docker
> docker-compose up mariadb
> DROP all databases
> docker-compose down
> docker compose up mariadb database
> verify there is exactly one database `gradido_community`
TODO:
INSERT INTO `login_groups` (`id`, `alias`, `name`, `url`, `host`, `home`, `description`) VALUES
(1, 'docker', 'docker gradido group', 'localhost', 'nginx', '/', 'gradido test group for docker and stage2 with blockchain db');
>> Database is cool
### Start login server
> docker-compose up login-server community-server nginx
>> Login & community servers and nginx proxy are up and running
## Build database
> cd database
> yarn
> yarn build
> cd ..
>> Database has been built successful
### Start backend (no docker for debugging)
> cd backend
> yarn
> yarn dev
>> Backend is up and running
### Create users
> chromium http://localhost:4000/graphql
> mutation{createUser(email: "receiver@user.net", firstName: "Receiver", lastName: "user", password: "123!AAAb", language: "de")}
> mutation{createUser(email: "sender@user.net", firstName: "Sender", lastName: "user", password: "123!AAAb", language: "de")}
> mutation{createUser(email: "creator@user.net", firstName: "Creator", lastName: "user", password: "123!AAAb", language: "de")}
>> Verify you have 3 entries in `login_users`, `login_user_backups` and `state_users`
### make creator an admin
> INSERT INTO login_user_roles (id, user_id, role_id) VALUES (NULL, '3', '1');
> UPDATE login_users SET email_checked = 1 WHERE id = 3;
> uncomment line: 19 in community_server/src/Controller/ServerUsersController.php
> chromium http://localhost/server-users/add
> create user `creator` `123` `creator@different.net`
>> verify you have 1 entry in `server_users`
> login with user on http://localhost/server-users
> activate server user by changing the corresponding flag in the interface
> navigate to http://localhost/transaction-creations/create-multi
> create 1000GDD for user sender@user.net
> navigate to http://localhost
> login with `creator@user.net` `123!AAAb`
> confirm transaction (top right corner - click the thingy, click the green button `Transaktion abschließen`)
### the test:
> chromium http://localhost:4000/graphql
> query{login(email: "sender@user.net", password: "123!AAAb"){pubkey}}
>> copy token from network tab (inspect)
> mutation{sendCoins(email: "receiver@user.net", amount: 10.0, memo: "Hier!")}
> mutation{sendCoins(email: "receiver@user.net", amount: 10.0, memo: "Hier!")}
> Headers: {"Authorization": "Bearer ${token}"}
>> Verify via Database that stuff is as it should see `state_balance` & `transaction_send_coins`
### create decay block
> chromium http://localhost/transactions/add
> login with `creator` `123`
> select `decay start`
> press submit
> wait for at least 0.02 display of decay on user sender@user.net on old frontend, this should be aprox 10min
> chromium http://localhost:4000/graphql
> query{login(email: "sender@user.net", password: "123!AAAb"){pubkey}}
>> copy token from network tab (inspect)
> mutation{sendCoins(email: "receiver@user.net", amount: 10.0, memo: "Hier!")}
>> verify in `transaction_send_coins` that a decay was taken into account
>> same in `state_balances`
>> now check the old frontend
>>> sender@user.net should have a decay of 0.02
>>> while receiver@user.net should have zero decay on anything (old frontend)
### Export data
> docker-compose up phpmyadmin
> chromium http://localhost:8074/
> select gradido_community
> export
> select custom
> untick structure
> ok
## Results
NOTE: We decided not to write the `transaction_signatures` since its unused. This is the main difference.
NOTE: We fixed a bug in the `state_user_transactions code` with the new implementation of apollo
Master:
--
-- Dumping data for table `state_user_transactions`
--
INSERT INTO `state_user_transactions` (`id`, `state_user_id`, `transaction_id`, `transaction_type_id`, `balance`, `balance_date`) VALUES
(1, 2, 1, 1, 10000000, '2021-11-05 12:45:18'),
(2, 2, 2, 2, 9900000, '2021-11-05 12:48:35'),
(3, 1, 2, 2, 100000, '2021-11-05 12:48:35'),
(4, 2, 3, 2, 9800000, '2021-11-05 12:49:07'),
(5, 1, 3, 2, 200000, '2021-11-05 12:49:07'),
(6, 2, 5, 2, 9699845, '2021-11-05 13:03:50'),
(7, 1, 5, 2, 99996, '2021-11-05 13:03:50');
--
-- Dumping data for table `transactions`
--
INSERT INTO `transactions` (`id`, `state_group_id`, `transaction_type_id`, `tx_hash`, `memo`, `received`, `blockchain_type_id`) VALUES
(1, NULL, 1, 0x9ccdcd01ccb6320c09c2d1da2f0bf735a95ece0e7c1df6bbff51918fbaec061700000000000000000000000000000000, '', '2021-11-05 12:45:18', 1),
(2, NULL, 2, 0x58d7706a67fa4ff4b8038168c6be39a2963d7e28e9d3872759ad09c519fe093700000000000000000000000000000000, 'Hier!', '2021-11-05 12:48:35', 1),
(3, NULL, 2, 0x427cd214f92ef35af671129d50edc5a478c53d1e464f285b7615d9794a69f69b00000000000000000000000000000000, 'Hier!', '2021-11-05 12:49:07', 1),
(4, NULL, 9, 0x32807368f0906a21b94c072599795bc9eeab88fb565df82e85cc62a4fdcde48500000000000000000000000000000000, '', '2021-11-05 12:51:51', 1),
(5, NULL, 2, 0x75eb729e0f60a1c8cead1342955853d2440d7a2ea57dfef6d4a18bff0d94491e00000000000000000000000000000000, 'Hier!', '2021-11-05 13:03:50', 1);
--
-- Dumping data for table `transaction_signatures`
--
INSERT INTO `transaction_signatures` (`id`, `transaction_id`, `signature`, `pubkey`) VALUES
(1, 1, 0x5888edcdcf77aaadad6d321882903bc831d7416f17213fd5020a764365b5fcb336e4c7917385a1278ea44ccdb31eac4a09e448053b5e3f8f1fe5da3baf53c008, 0xd5b20f8dee415038bfa2b6b0e1b40ff54850351109444863b04d6d28825b7b7d),
(2, 2, 0xf6fef428f8f22faf7090f7d740e6088d1d90c58ae92d757117d7d91d799e659f3a3a0c65a3fd97cbde798e761f9d23eff13e8810779a184c97c411f28e7c4608, 0xdc74a589004377ab14836dce68ce2ca34e5b17147cd78ad4b3afe8137524ae8a),
(3, 3, 0x8ebe9730c6cf61f56ef401d6f2bd229f3c298ca3c2791ee9137e4827b7af6c6d6566fca616eb1fe7adc2e4d56b5c7350ae3990c9905580630fa75ecffca8e001, 0xdc74a589004377ab14836dce68ce2ca34e5b17147cd78ad4b3afe8137524ae8a),
(4, 5, 0x50cf418f7e217391e89ab9c2879ae68d7c7c597d846b4fe1c082b5b16e5d0c85c328fbf48ad3490bcfe94f446700ae0a4b0190e76d26cc752abced58f480c80f, 0xdc74a589004377ab14836dce68ce2ca34e5b17147cd78ad4b3afe8137524ae8a);
This Feature Branch:
--
-- Dumping data for table `state_user_transactions`
--
INSERT INTO `state_user_transactions` (`id`, `state_user_id`, `transaction_id`, `transaction_type_id`, `balance`, `balance_date`) VALUES
(1, 2, 1, 1, 10000000, '2021-11-05 00:25:46'),
(12, 2, 7, 2, 9900000, '2021-11-05 00:55:37'),
(13, 1, 7, 2, 100000, '2021-11-05 00:55:37'),
(14, 2, 8, 2, 9800000, '2021-11-05 01:00:04'),
(15, 1, 8, 2, 200000, '2021-11-05 01:00:04'),
(16, 2, 10, 2, 9699772, '2021-11-05 01:17:41'),
(17, 1, 10, 2, 299995, '2021-11-05 01:17:41');
--
-- Dumping data for table `transactions`
--
INSERT INTO `transactions` (`id`, `state_group_id`, `transaction_type_id`, `tx_hash`, `memo`, `received`, `blockchain_type_id`) VALUES
(1, NULL, 1, 0xdd030d475479877587d927ed9024784ba62266cf1f3d87862fc98ad68f7b26e400000000000000000000000000000000, '', '2021-11-05 00:25:46', 1),
(7, NULL, 2, NULL, 'Hier!', '2021-11-05 00:55:37', 1),
(8, NULL, 2, NULL, 'Hier!', '2021-11-05 01:00:04', 1),
(9, NULL, 9, 0xb1cbedbf126aa35f5edbf06e181c415361d05228ab4da9d19a4595285a673dfa00000000000000000000000000000000, '', '2021-11-05 01:05:34', 1),
(10, NULL, 2, NULL, 'Hier!', '2021-11-05 01:17:41', 1);
--
-- Dumping data for table `transaction_signatures`
--
INSERT INTO `transaction_signatures` (`id`, `transaction_id`, `signature`, `pubkey`) VALUES
(1, 1, 0x60d632479707e5d01cdc32c3326b5a5bae11173a0c06b719ee7b552f9fd644de1a0cd4afc207253329081d39dac1a63421f51571d836995c649fc39afac7480a, 0x48c45cb4fea925e83850f68f2fa8f27a1a4ed1bcba68cdb59fcd86adef3f52ee);
*/
// Helper function
async function calculateAndAddDecayTransactions(
userTransactions: dbUserTransaction[],

View File

@ -1,25 +1,34 @@
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne } from 'typeorm'
import { TransactionCreation } from './TransactionCreation'
import { TransactionSendCoin } from './TransactionSendCoin'
import { TransactionCreation } from '../TransactionCreation'
import { TransactionSendCoin } from '../TransactionSendCoin'
@Entity('transactions')
export class Transaction extends BaseEntity {
@PrimaryGeneratedColumn()
id: number
@Column({ name: 'transaction_type_id' })
@Column({ name: 'state_group_id', unsigned: true, default: null })
stateGroupId: number
@Column({ name: 'transaction_type_id', unsigned: true, nullable: false })
transactionTypeId: number
@Column({ name: 'tx_hash', type: 'binary', length: 48 })
@Column({ name: 'tx_hash', type: 'binary', length: 48, default: null })
txHash: Buffer
@Column()
@Column({ length: 255, nullable: false, collation: 'utf8mb4_unicode_ci' })
memo: string
@Column({ type: 'timestamp' })
@Column({ type: 'timestamp', nullable: false, default: () => 'CURRENT_TIMESTAMP' })
received: Date
@Column({ name: 'blockchain_type_id' })
@Column({
name: 'blockchain_type_id',
type: 'bigint',
unsigned: true,
nullable: false,
default: 1,
})
blockchainTypeId: number
@OneToOne(() => TransactionSendCoin, (transactionSendCoin) => transactionSendCoin.transaction)

View File

@ -1,5 +1,5 @@
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm'
import { Transaction } from './Transaction'
import { Transaction } from '../Transaction'
@Entity('transaction_creations')
export class TransactionCreation extends BaseEntity {

View File

@ -1,5 +1,5 @@
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm'
import { Transaction } from './Transaction'
import { Transaction } from '../Transaction'
@Entity('transaction_send_coins')
export class TransactionSendCoin extends BaseEntity {

View File

@ -1,21 +1,21 @@
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm'
import { Transaction } from './Transaction'
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm'
import { Transaction } from '../Transaction'
@Entity('transaction_signatures')
export class TransactionSignature extends BaseEntity {
@PrimaryGeneratedColumn()
@PrimaryGeneratedColumn('increment', { unsigned: true })
id: number
@Column({ name: 'transaction_id' })
transactionId: number
@Column({ type: 'binary', length: 64 })
@Column({ type: 'binary', length: 64, nullable: false })
signature: Buffer
@Column({ type: 'binary', length: 32 })
@Column({ type: 'binary', length: 32, nullable: false })
pubkey: Buffer
@ManyToOne(() => Transaction)
@OneToOne(() => Transaction)
@JoinColumn({ name: 'transaction_id' })
transaction: Transaction
}

View File

@ -1,5 +1,5 @@
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm'
import { UserSetting } from './UserSetting'
import { UserSetting } from '../UserSetting'
// Moriz: I do not like the idea of having two user tables
@Entity('state_users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' })

View File

@ -1,5 +1,5 @@
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm'
import { User } from './User'
import { User } from '../User'
@Entity()
export class UserSetting extends BaseEntity {

View File

@ -0,0 +1,34 @@
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne } from 'typeorm'
import { TransactionCreation } from '../TransactionCreation'
import { TransactionSendCoin } from '../TransactionSendCoin'
@Entity('transactions')
export class Transaction extends BaseEntity {
// TODO the id is defined as bigint(20) - there might be problems with that: https://github.com/typeorm/typeorm/issues/2400
@PrimaryGeneratedColumn('increment', { unsigned: true })
id: number
@Column({ name: 'transaction_type_id', unsigned: true, nullable: false })
transactionTypeId: number
@Column({ name: 'tx_hash', type: 'binary', length: 48, default: null })
txHash: Buffer
@Column({ length: 255, nullable: false, collation: 'utf8mb4_unicode_ci' })
memo: string
@Column({ type: 'timestamp', nullable: false, default: () => 'CURRENT_TIMESTAMP' })
received: Date
@Column({ type: 'binary', length: 64, nullable: true, default: null })
signature: Buffer
@Column({ type: 'binary', length: 32, nullable: true, default: null })
pubkey: Buffer
@OneToOne(() => TransactionSendCoin, (transactionSendCoin) => transactionSendCoin.transaction)
transactionSendCoin: TransactionSendCoin
@OneToOne(() => TransactionCreation, (transactionCreation) => transactionCreation.transaction)
transactionCreation: TransactionCreation
}

View File

@ -1 +1 @@
export { Transaction } from './0001-init_db/Transaction'
export { Transaction } from './0016-transaction_signatures/Transaction'

View File

@ -1 +0,0 @@
export { TransactionSignature } from './0001-init_db/TransactionSignature'

View File

@ -7,7 +7,6 @@ import { Migration } from './Migration'
import { ServerUser } from './ServerUser'
import { Transaction } from './Transaction'
import { TransactionCreation } from './TransactionCreation'
import { TransactionSignature } from './TransactionSignature'
import { TransactionSendCoin } from './TransactionSendCoin'
import { User } from './User'
import { UserSetting } from './UserSetting'
@ -25,7 +24,6 @@ export const entities = [
ServerUser,
Transaction,
TransactionCreation,
TransactionSignature,
TransactionSendCoin,
User,
UserSetting,

View File

@ -0,0 +1,60 @@
/* MIGRATION TO CLEANUP TRANSACTIONS TABLE
*
* This migration cleans up the transactions table and
* combines its data with transaction_signatures.
*/
export async function upgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
// Drop column `state_group_id` since it only contains "0" as value, no variation.
// Furthermore it was not present in our model itself (meaning that newly created )
await queryFn('ALTER TABLE `transactions` DROP COLUMN `state_group_id`;')
// Drop column `blockchain_type_id` since it only contains "1" as value, no variation.
await queryFn('ALTER TABLE `transactions` DROP COLUMN `blockchain_type_id`;')
// Create `signature` column - for data from `transaction_signatures` table.
await queryFn(
'ALTER TABLE `transactions` ADD COLUMN `signature` binary(64) DEFAULT NULL AFTER `received`;',
)
// Create `pubkey` column - for data from `transaction_signatures` table.
await queryFn(
'ALTER TABLE `transactions` ADD COLUMN `pubkey` binary(32) DEFAULT NULL AFTER `signature`;',
)
// Transfer data from `transaction_signatures` table to `transactions` table
await queryFn(`
UPDATE transactions
INNER JOIN transaction_signatures ON transactions.id = transaction_signatures.transaction_id
SET transactions.signature = transaction_signatures.signature, transactions.pubkey = transaction_signatures.pubkey;
`)
// Drop `transaction_signatures` table
await queryFn('DROP TABLE `transaction_signatures`;')
}
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
await queryFn(`
CREATE TABLE \`transaction_signatures\` (
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
\`transaction_id\` int(10) unsigned NOT NULL,
\`signature\` binary(64) NOT NULL,
\`pubkey\` binary(32) NOT NULL,
PRIMARY KEY (\`id\`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
`)
await queryFn(`
INSERT INTO transaction_signatures (transaction_id, signature, pubkey)
(SELECT id as transaction_id, signature, pubkey FROM transactions WHERE signature IS NOT NULL and pubkey IS NOT NULL);
`)
await queryFn('ALTER TABLE `transactions` DROP COLUMN `pubkey`;')
await queryFn('ALTER TABLE `transactions` DROP COLUMN `signature`;')
await queryFn(
'ALTER TABLE `transactions` ADD COLUMN `blockchain_type_id` bigint(20) unsigned NOT NULL DEFAULT 1 AFTER `received` ;',
)
await queryFn(
'ALTER TABLE `transactions` ADD COLUMN `state_group_id` int(10) unsigned DEFAULT NULL AFTER `id`;',
)
// We have to set the correct values previously in the table , since its not the same as the column's default
await queryFn('UPDATE `transactions` SET `state_group_id` = 0;')
}

View File

@ -1,18 +0,0 @@
import Faker from 'faker'
import { define } from 'typeorm-seeding'
import { TransactionSignature } from '../../entity/TransactionSignature'
import { TransactionSignatureContext } from '../interface/TransactionContext'
import { randomBytes } from 'crypto'
define(TransactionSignature, (faker: typeof Faker, context?: TransactionSignatureContext) => {
if (!context || !context.transaction) {
throw new Error('TransactionSignature: No transaction present!')
}
const transactionSignature = new TransactionSignature()
transactionSignature.signature = context.signature ? context.signature : randomBytes(64)
transactionSignature.pubkey = context.pubkey ? context.pubkey : randomBytes(32)
transactionSignature.transaction = context.transaction
return transactionSignature
})

View File

@ -12,7 +12,8 @@ define(Transaction, (faker: typeof Faker, context?: TransactionContext) => {
transaction.txHash = context.txHash ? context.txHash : randomBytes(48)
transaction.memo = context.memo || context.memo === '' ? context.memo : faker.lorem.sentence()
transaction.received = context.received ? context.received : new Date()
transaction.blockchainTypeId = context.blockchainTypeId ? context.blockchainTypeId : 1
transaction.signature = context.signature ? context.signature : randomBytes(64)
transaction.pubkey = context.signaturePubkey ? context.signaturePubkey : randomBytes(32)
if (context.transactionSendCoin) transaction.transactionSendCoin = context.transactionSendCoin
if (context.transactionCreation) transaction.transactionCreation = context.transactionCreation

View File

@ -9,6 +9,8 @@ export interface TransactionContext {
memo?: string
received?: Date
blockchainTypeId?: number
signature?: Buffer
signaturePubkey?: Buffer
transactionSendCoin?: TransactionSendCoin
transactionCreation?: TransactionCreation
}
@ -43,10 +45,6 @@ export interface UserTransactionContext {
transactionTypeId?: number
balance?: number
balanceDate?: Date
}
export interface TransactionSignatureContext {
signature?: Buffer
pubkey?: Buffer
transaction?: Transaction
}

View File

@ -10,7 +10,6 @@ import {
TransactionContext,
TransactionCreationContext,
UserTransactionContext,
TransactionSignatureContext,
} from '../../interface/TransactionContext'
import { UserInterface } from '../../interface/UserInterface'
import { User } from '../../../entity/User'
@ -19,7 +18,6 @@ import { LoginUserBackup } from '../../../entity/LoginUserBackup'
import { ServerUser } from '../../../entity/ServerUser'
import { Balance } from '../../../entity/Balance'
import { Transaction } from '../../../entity/Transaction'
import { TransactionSignature } from '../../../entity/TransactionSignature'
import { UserTransaction } from '../../../entity/UserTransaction'
import { TransactionCreation } from '../../../entity/TransactionCreation'
import { Factory } from 'typeorm-seeding'
@ -46,9 +44,6 @@ export const userSeeder = async (factory: Factory, userData: UserInterface): Pro
await factory(UserTransaction)(
createUserTransactionContext(userData, user, transaction),
).create()
await factory(TransactionSignature)(
createTransactionSignatureContext(userData, transaction),
).create()
}
}
@ -161,16 +156,7 @@ const createUserTransactionContext = (
transactionTypeId: transaction.transactionTypeId,
balance: context.amount,
balanceDate: context.recordDate,
}
}
const createTransactionSignatureContext = (
context: UserInterface,
transaction: Transaction,
): TransactionSignatureContext => {
return {
signature: context.signature,
pubkey: context.signaturePubkey,
transaction,
}
}