Skip to content

Commit

Permalink
🔨 WIP dposv2
Browse files Browse the repository at this point in the history
 - fixed sql for prevblockidsignature
 - rewritten round logic for land and backwardLand + removed all mem_rounds related logic and queries
 - fixed and added all the tests to properly work with dposv2.
 - update SQL for calculating votes and votesWeight
  • Loading branch information
bullbearnetwork committed Nov 9, 2018
1 parent dece637 commit e697e62
Show file tree
Hide file tree
Showing 29 changed files with 504 additions and 600 deletions.
1 change: 0 additions & 1 deletion etc/devnet/genesisBlock.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
"payloadLength": 37262,
"reward": 0,
"previousBlock": null,
"previousBlockIDSignature": "01",
"generatorPublicKey": "b181c550a298e7ca762ed70f02b31e2a4b35de95697ebce2b0c38701fab0c40b",
"transactions": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ UPDATE "mem_accounts" AS m SET "votesWeight" = vote_weight FROM (
ON ma_group."accountId"=ma2."address"
WHERE ma_group.divider>0
) ma3
ON ma2d."accountId"=ma3."address" WHERE ma."isDelegate"=1 GROUP BY ma."address"
ON ma2d."accountId"=ma3."address"
WHERE ma."isDelegate"=1 GROUP BY ma."address"
) as vv
WHERE vv."address"=m."address" AND m."isDelegate"=1;

Expand Down
6 changes: 0 additions & 6 deletions sql/migrations/20181102185300_addPrevBlockSignature.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,4 @@ BEGIN;

ALTER TABLE "blocks" ADD COLUMN IF NOT EXISTS "previousBlockIDSignature" bytea;

-- Set dummy value
UPDATE blocks SET "previousBlockIDSignature" = '\001'::bytea;

ALTER TABLE blocks ALTER COLUMN "previousBlockIDSignature" SET NOT NULL;


COMMIT;
22 changes: 0 additions & 22 deletions src/ioc/interfaces/logic/IRoundLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,16 @@ export interface IRoundLogic {
*/
updateMissedBlocks(): DBOp<any>;

/**
* Update votes for the round
*/
updateVotes(): DBCustomOp<any>;

/**
* In case of backwards calls updateBlockId with '0';
*/
markBlockId(): DBOp<any>;

/**
* Calls sql flush, deletes round from mem_round
*/
flushRound(): DBOp<any>;

/**
* REmove blocks higher than this block height
*/
truncateBlocks(): DBOp<any>;

/**
* Performed when rollbacking last block of a round.
* It restores the round snapshot from sql
*/
restoreRoundSnapshot(): DBOp<any>;

/**
* Performed when rollbacking last block of a round.
* It restores the round snapshot from sql
*/
restoreVotesSnapshot(): DBOp<any>;

/**
* For each delegate in round calls mergeAccountAndGet with new Balance
*/
Expand Down
24 changes: 0 additions & 24 deletions src/logic/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,37 +360,13 @@ export class AccountLogic implements IAccountLogic {
}
if (Math.abs(trueValue) === trueValue && trueValue !== 0) {
update[fieldName] = sequelize.literal(`${fieldName} + ${Math.floor(trueValue)}`);
if (fieldName === 'balance') {
dbOps.push({
model: this.RoundsModel,
query: this.RoundsModel.insertMemRoundBalanceSQL({
address,
amount : trueValue,
blockId: diff.blockId,
round : diff.round,
}),
type : 'custom',
});
}
} else if (trueValue < 0) {
update[fieldName] = sequelize.literal(`${fieldName} - ${Math.floor(Math.abs(trueValue))}`);
// If decrementing u_balance on account
if (update.u_balance) {
// Remove virginity and ensure marked columns become immutable
update.virgin = 0;
}
if (fieldName === 'balance') {
dbOps.push({
model: this.RoundsModel,
query: this.RoundsModel.insertMemRoundBalanceSQL({
address,
amount : trueValue,
blockId: diff.blockId,
round : diff.round,
}),
type : 'custom',
});
}
}
break;
}
Expand Down
16 changes: 8 additions & 8 deletions src/logic/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { inject, injectable } from 'inversify';
import * as supersha from 'supersha';
import z_schema from 'z-schema';
import { BigNum, constants, Ed, IKeypair } from '../helpers/';
import {IAccountLogic, IBlockLogic, ITransactionLogic} from '../ioc/interfaces/logic/';
import { IAccountLogic, IBlockLogic, ITransactionLogic } from '../ioc/interfaces/logic/';
import { Symbols } from '../ioc/symbols';
import { BlocksModel } from '../models';
import logicBlockSchema from '../schema/logic/block';
Expand Down Expand Up @@ -78,6 +78,9 @@ export class BlockLogic implements IBlockLogic {
@inject(Symbols.generic.zschema)
public zschema: z_schema;

@inject(Symbols.helpers.constants)
private consts: typeof constants;

@inject(Symbols.logic.account)
private accountLogic: IAccountLogic;
@inject(Symbols.logic.blockReward)
Expand Down Expand Up @@ -154,10 +157,10 @@ export class BlockLogic implements IBlockLogic {
payloadHash : payloadHash.digest(),
payloadLength : size,
previousBlock : data.previousBlock.id,
previousBlockIDSignature: this.ed.sign(
previousBlockIDSignature: this.consts.dposv2.firstBlock <= data.previousBlock.height + 1 ? this.ed.sign(
supersha.sha256(Buffer.from(data.previousBlock.id, 'utf8')),
data.keypair
),
) : null,
reward,
timestamp : data.timestamp,
totalAmount,
Expand All @@ -168,6 +171,7 @@ export class BlockLogic implements IBlockLogic {

block.blockSignature = this.sign(block, data.keypair);
block.id = this.getId(block);

return this.objectNormalize(block);
}

Expand All @@ -189,10 +193,6 @@ export class BlockLogic implements IBlockLogic {
* @param {BlockType} block
*/
public verifySignature(block: SignedBlockType): boolean {
// console.log(block);
// const res = new OldImplementation(this.ed, this.zschema, this.transaction, null)
// .verifySignature(block);
// console.log(res);
return this.ed.verify(
this.getHash(block, false),
block.blockSignature,
Expand Down Expand Up @@ -388,7 +388,7 @@ export class BlockLogic implements IBlockLogic {
const payloadHash = blk.bytes.slice(48, 80);
const generatorPublicKey = blk.bytes.slice(80, 112);
const previousBlockIDSignature = blk.bytes.length === 176 ? null : blk.bytes.slice(112, 176);
const blockSignature = previousBlockIDSignature ? blk.bytes.slice(177, 177 + 64) : blk.bytes.slice(112, 176);
const blockSignature = previousBlockIDSignature ? blk.bytes.slice(176, 176 + 64) : blk.bytes.slice(112, 176);
const id = this.getIdFromBytes(blk.bytes);
const transactions = blk.transactions.map((tx) => {
const baseTx = this.transaction.fromBytes(tx);
Expand Down
81 changes: 14 additions & 67 deletions src/logic/round.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { IRoundLogic } from '../ioc/interfaces/logic/';
import { IAccountsModule } from '../ioc/interfaces/modules';
import { AccountsModel, BlocksModel, RoundsModel } from '../models';
import roundSQL from '../sql/logic/rounds';
import { DBCustomOp, DBOp } from '../types/genericTypes';
import { DBOp } from '../types/genericTypes';
import { address } from '../types/sanityTypes';
import { SignedBlockType } from './block';

Expand Down Expand Up @@ -93,17 +93,6 @@ export class RoundLogic implements IRoundLogic {
};
}

/**
* Update votes for the round
*/
public updateVotes(): DBCustomOp<any> {
return {
model: this.scope.models.AccountsModel,
query: this.scope.models.RoundsModel.updateVotesSQL(this.scope.round),
type : 'custom',
};
}

/**
* In case of backwards calls updateBlockId with '0';
*/
Expand All @@ -125,17 +114,6 @@ export class RoundLogic implements IRoundLogic {
return null;
}

/**
* Calls sql flush, deletes round from mem_round
*/
public flushRound(): DBOp<any> {
return {
model : this.scope.models.RoundsModel,
options: { where: { round: this.scope.round } },
type : 'remove',
};
}

/**
* Recalculates votesWeight
*/
Expand All @@ -160,24 +138,23 @@ export class RoundLogic implements IRoundLogic {

/**
* Performed when rollbacking last block of a round.
* It restores the round snapshot from sql
* It restores the votes snapshot from sql
*/
public restoreRoundSnapshot(): DBOp<RoundsModel> {
public restoreVotesSnapshot(): DBOp<AccountsModel> {
return {
model: this.scope.models.RoundsModel,
query: roundSQL.restoreRoundSnapshot,
model: this.scope.models.AccountsModel,
query: roundSQL.restoreVotesSnapshot,
type: 'custom',
};
}

/**
* Performed when rollbacking last block of a round.
* It restores the votes snapshot from sql
*/
public restoreVotesSnapshot(): DBOp<AccountsModel> {
public performVoteSnapshot(): DBOp<AccountsModel> {
return {
model: this.scope.models.AccountsModel,
query: roundSQL.restoreVotesSnapshot,
query: roundSQL.performVotesSnapshot,
type: 'custom',
};
}
Expand All @@ -194,7 +171,6 @@ export class RoundLogic implements IRoundLogic {
for (let i = 0; i < delegates.length; i++) {
const delegate = delegates[i];
const changes = roundChanges.at(i);
this.scope.library.logger.trace('Delegate changes', { delegate, changes });

// merge Account in the direction.
queries.push(... this.scope.modules.accounts.mergeAccountAndGetOPs({
Expand All @@ -209,18 +185,16 @@ export class RoundLogic implements IRoundLogic {
}

// last delegate will always get the remainder fees.
const remainderIndex = this.scope.backwards ? 0 : delegates.length - 1;
const remainderDelegate = delegates[remainderIndex];
const remainderDelegate = delegates[delegates.length - 1];

const remainderChanges = roundChanges.at(remainderIndex);
const remainderChanges = roundChanges.at(delegates.length - 1);

if (remainderChanges.feesRemaining > 0) {
const feesRemaining = (this.scope.backwards ? -remainderChanges.feesRemaining : remainderChanges.feesRemaining);

this.scope.library.logger.trace('Fees remaining', {
delegate: remainderDelegate,
delegate: remainderDelegate.toString('hex'),
fees : feesRemaining,
index : remainderIndex,
});

queries.push(... this.scope.modules.accounts.mergeAccountAndGetOPs({
Expand Down Expand Up @@ -249,13 +223,8 @@ export class RoundLogic implements IRoundLogic {
}
} else if (this.scope.dposV2 && this.scope.preFinishRound) {
return [
{ type: 'custom', query: roundSQL.clearRoundSnapshot, model: this.scope.models.RoundsModel },
{ type: 'custom', query: roundSQL.clearVotesSnapshot, model: this.scope.models.RoundsModel },
{ type: 'custom', query: roundSQL.performRoundSnapshot, model: this.scope.models.RoundsModel },
{ type: 'custom', query: roundSQL.performVotesSnapshot, model: this.scope.models.RoundsModel },
this.updateVotes(),
this.performVoteSnapshot(),
this.reCalcVotes(),
this.flushRound(),
];
}
return [];
Expand All @@ -271,28 +240,17 @@ export class RoundLogic implements IRoundLogic {
}
return this.backwardCloseRoundV1();
} else if (this.scope.dposV2 && this.scope.preFinishRound) {
return [
this.restoreRoundSnapshot(),
this.restoreVotesSnapshot(),
];
return [ this.restoreVotesSnapshot() ];
}
return [];
}

private closeRoundV1(): Array<DBOp<any>> {
return [
this.updateVotes(),
this.reCalcVotes(),
this.updateMissedBlocks(),
this.flushRound(),
...this.applyRound(),
this.updateVotes(),
this.performVoteSnapshot(),
this.reCalcVotes(),
this.flushRound(),
{ type: 'custom', query: roundSQL.clearRoundSnapshot, model: this.scope.models.RoundsModel },
{ type: 'custom', query: roundSQL.clearVotesSnapshot, model: this.scope.models.RoundsModel },
{ type: 'custom', query: roundSQL.performRoundSnapshot, model: this.scope.models.RoundsModel },
{ type: 'custom', query: roundSQL.performVotesSnapshot, model: this.scope.models.RoundsModel },
];
}

Expand All @@ -302,29 +260,18 @@ export class RoundLogic implements IRoundLogic {
];
}

// tslint:disable-next-line no-identical-functions
private backwardCloseRoundV1() {
return [
this.updateVotes(),
this.reCalcVotes(),
this.updateMissedBlocks(),
this.flushRound(),
...this.applyRound(),
this.updateVotes(),
this.reCalcVotes(),
this.flushRound(),
this.restoreRoundSnapshot(),
this.restoreVotesSnapshot(),
];
}

private backwardCloseRoundV2() {
return [
this.updateMissedBlocks(),
{
model : this.scope.models.RoundsModel,
options: { where: { round: this.scope.round } },
type : 'remove',
} as any,
... this.applyRound(),
];
}
Expand Down
37 changes: 2 additions & 35 deletions src/logic/transactions/vote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,48 +121,15 @@ export class VoteTransaction extends BaseTransactionType<VoteAsset, VotesModel>
public async apply(tx: IConfirmedTransaction<VoteAsset>, block: SignedBlockType, sender: AccountsModel): Promise<Array<DBOp<any>>> {
await this.checkConfirmedDelegates(tx, sender);
sender.applyDiffArray('delegates', tx.asset.votes);
const ops = this.calculateOPs(this.Accounts2DelegatesModel, block.id, tx.asset.votes, sender.address);
ops.push(... tx.asset.votes.map<DBCustomOp<RoundsModel>>((vote) => {
const add = vote[0] === '+';
const delegate = vote.substr(1);
return {
model: this.RoundsModel,
query: this.RoundsModel.insertMemRoundDelegatesSQL({
add,
address: sender.address,
blockId: block.id,
delegate,
round : this.roundsLogic.calcRound(block.height),
}),
type : 'custom',
};
}));
return ops;
return this.calculateOPs(this.Accounts2DelegatesModel, block.id, tx.asset.votes, sender.address);
}

// tslint:disable-next-line max-line-length
public async undo(tx: IConfirmedTransaction<VoteAsset>, block: SignedBlockType, sender: AccountsModel): Promise<Array<DBOp<any>>> {
this.objectNormalize(tx);
const invertedVotes = Diff.reverse(tx.asset.votes);
sender.applyDiffArray('delegates', invertedVotes);
const ops = this.calculateOPs(this.Accounts2DelegatesModel, block.id, invertedVotes, sender.address);
// tslint:disable-next-line
ops.push(... invertedVotes.map<DBCustomOp<RoundsModel>>((vote) => {
const add = vote[0] === '+';
const delegate = vote.substr(1);
return {
model: this.RoundsModel,
query: this.RoundsModel.insertMemRoundDelegatesSQL({
add,
address: sender.address,
blockId: block.id,
delegate,
round : this.roundsLogic.calcRound(block.height),
}),
type : 'custom',
};
}));
return ops;
return this.calculateOPs(this.Accounts2DelegatesModel, block.id, invertedVotes, sender.address);
}

public async applyUnconfirmed(tx: IBaseTransaction<VoteAsset>, sender: AccountsModel): Promise<Array<DBOp<any>>> {
Expand Down

0 comments on commit e697e62

Please sign in to comment.