Skip to content

Commit

Permalink
Merge pull request #81 from hive-engine/addTicks
Browse files Browse the repository at this point in the history
Add tick registration mechanism
  • Loading branch information
bt-cryptomancer authored Jul 21, 2021
2 parents 19d3f51 + 1a982ff commit f3c328d
Show file tree
Hide file tree
Showing 7 changed files with 402 additions and 52 deletions.
32 changes: 32 additions & 0 deletions contracts/testing/dummyTicks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* eslint-disable no-await-in-loop */
/* eslint-disable quote-props */
/* eslint-disable max-len */
/* global actions, api */

actions.createSSC = () => {
// Initialize the smart contract via the create action
};
actions.checkPendingUnstakes = () => {
api.emit('checkPendingUnstakes', {});
};
actions.checkPendingUndelegations = () => {
api.emit('checkPendingUndelegations', {});
};
actions.tick = () => {
api.emit('tick', {});
};
actions.checkPendingLotteries = () => {
api.emit('checkPendingLotteries', {});
};
actions.checkPendingAirdrops = () => {
api.emit('checkPendingAirdrops', {});
};
actions.updateAuctions = () => {
api.emit('updateAuctions', {});
};
actions.scheduleWitnesses = () => {
api.emit('scheduleWitnesses', {});
};
actions.checkPendingDtfs = () => {
api.emit('checkPendingDtfs', {});
};
78 changes: 27 additions & 51 deletions libs/Block.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,31 +127,14 @@ class Block {
// handle virtual transactions
const virtualTransactions = [];

virtualTransactions.push(new Transaction(0, '', 'null', 'tokens', 'checkPendingUnstakes', ''));
virtualTransactions.push(new Transaction(0, '', 'null', 'tokens', 'checkPendingUndelegations', ''));
virtualTransactions.push(new Transaction(0, '', 'null', 'nft', 'checkPendingUndelegations', ''));
// use contracts_config contractTicks to trigger ticking contract actions.
const contractsConfig = await database.getContractsConfig();

if (this.refHiveBlockNumber >= 45251626) {
virtualTransactions.push(new Transaction(0, '', 'null', 'botcontroller', 'tick', ''));
}
if (this.refHiveBlockNumber >= 47746850) {
virtualTransactions.push(new Transaction(0, '', 'null', 'mining', 'checkPendingLotteries', ''));
}
if (this.refHiveBlockNumber >= 48664773) {
virtualTransactions.push(new Transaction(0, '', 'null', 'airdrops', 'checkPendingAirdrops', ''));
}
if (this.refHiveBlockNumber >= 54560500) {
virtualTransactions.push(new Transaction(0, '', 'null', 'nftauction', 'updateAuctions', ''));
}

if (this.refHiveBlockNumber >= 51022551) {
virtualTransactions
.push(new Transaction(0, '', 'null', 'witnesses', 'scheduleWitnesses', ''));
}

if (this.refHiveBlockNumber >= 53610300) {
virtualTransactions
.push(new Transaction(0, '', 'null', 'tokenfunds', 'checkPendingDtfs', ''));
for (let i = 0; i < contractsConfig.contractTicks.length; i += 1) {
const contractTick = contractsConfig.contractTicks[i];
if (this.refHiveBlockNumber >= contractTick.startRefBlock) {
virtualTransactions.push(new Transaction(0, '', 'null', contractTick.contract, contractTick.action, ''));
}
}

if (this.refHiveBlockNumber % 1200 === 0) {
Expand All @@ -170,37 +153,22 @@ class Block {
// the "unknown error" errors are removed as they are related to a non existing action
if (transaction.logs !== '{}'
&& transaction.logs !== '{"errors":["unknown error"]}') {
if (transaction.contract === 'witnesses'
&& transaction.action === 'scheduleWitnesses'
let tickingAction = false;
for (let j = 0; j < contractsConfig.contractTicks.length; j += 1) {
const contractTick = contractsConfig.contractTicks[j];
if (transaction.contract === contractTick.contract
&& transaction.action === contractTick.action
&& transaction.logs === '{"errors":["contract doesn\'t exist"]}') {
// don't save logs
} else if (transaction.contract === 'inflation'
tickingAction = true;
}
}


if (transaction.contract === 'inflation'
&& transaction.action === 'issueNewTokens'
&& transaction.logs === '{"errors":["contract doesn\'t exist"]}') {
// don't save logs
} else if (transaction.contract === 'nft'
&& transaction.action === 'checkPendingUndelegations'
&& transaction.logs === '{"errors":["contract doesn\'t exist"]}') {
// don't save logs
} else if (transaction.contract === 'botcontroller'
&& transaction.action === 'tick'
&& transaction.logs === '{"errors":["contract doesn\'t exist"]}') {
// don't save logs
} else if (transaction.contract === 'mining'
&& transaction.action === 'checkPendingLotteries'
&& transaction.logs === '{"errors":["contract doesn\'t exist"]}') {
// don't save logs
} else if (transaction.contract === 'airdrops'
&& transaction.action === 'checkPendingAirdrops'
&& transaction.logs === '{"errors":["contract doesn\'t exist"]}') {
// don't save logs
} else if (transaction.contract === 'nftauction'
&& transaction.action === 'updateAuctions'
&& transaction.logs === '{"errors":["contract doesn\'t exist"]}') {
// don't save logs
} else if (transaction.contract === 'tokenfunds'
&& transaction.action === 'checkPendingDtfs'
&& transaction.logs === '{"errors":["contract doesn\'t exist"]}') {
} else if (tickingAction) {
// don't save logs
} else {
this.virtualTransactions.push(transaction);
Expand Down Expand Up @@ -254,6 +222,14 @@ class Block {
} else {
results = { logs: { errors: ['the contract deployment is currently unavailable'] } };
}
} else if (contract === 'contract' && action === 'registerTick' && payload) {
const authorizedAccountTickRegister = [
CONSTANTS.HIVE_ENGINE_ACCOUNT, CONSTANTS.HIVE_PEGGED_ACCOUNT];
if (authorizedAccountTickRegister.includes(sender)) {
results = await SmartContracts.registerTick(database, transaction);
} else {
results = { logs: { errors: ['registerTick unauthorized'] } };
}
} else {
results = await SmartContracts.executeSmartContract(// eslint-disable-line
database, transaction, this.blockNumber, this.timestamp,
Expand Down
49 changes: 49 additions & 0 deletions libs/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,55 @@ const CONSTANTS = {
// default values
ACCOUNT_RECEIVING_FEES: 'hive-engine',
SSC_STORE_PRICE: '0.001',
// WARNING: Do not add any more entries to this initial configuration.
// Future contracts must use the contract action 'registerTick'.
INITIAL_CONTRACT_TICKS: [
{
contract: 'tokens',
action: 'checkPendingUnstakes',
startRefBlock: 0,
},
{
contract: 'tokens',
action: 'checkPendingUndelegations',
startRefBlock: 0,
},
{
contract: 'nft',
action: 'checkPendingUndelegations',
startRefBlock: 0,
},
{
contract: 'botcontroller',
action: 'tick',
startRefBlock: 45251626,
},
{
contract: 'mining',
action: 'checkPendingLotteries',
startRefBlock: 47746850,
},
{
contract: 'airdrops',
action: 'checkPendingAirdrops',
startRefBlock: 48664773,
},
{
contract: 'nftauction',
action: 'updateAuctions',
startRefBlock: 54560500,
},
{
contract: 'witnesses',
action: 'scheduleWitnesses',
startRefBlock: 51022551,
},
{
contract: 'tokenfunds',
action: 'checkPendingDtfs',
startRefBlock: 53610300,
},
],
};

module.exports.CONSTANTS = CONSTANTS;
28 changes: 28 additions & 0 deletions libs/Database.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const enchex = require('crypto-js/enc-hex');
const validator = require('validator');
const { MongoClient } = require('mongodb');
const { EJSON } = require('bson');
const { CONSTANTS } = require('../libs/Constants');

// Change this to turn on hash logging.
const enableHashLogging = false;
Expand Down Expand Up @@ -149,6 +150,16 @@ class Database {
} else {
this.chain = coll;
}

const contractsConfigColl = await this.getCollection('contracts_config');
if (contractsConfigColl === null) {
const newContractsConfigColl = await this.database.createCollection('contracts_config', { session: this.session });
// WARNING: Do not add any more entries to this initial configuration.
// Future contracts must use the contract action 'registerTick'.
await newContractsConfigColl.insertOne({
contractTicks: CONSTANTS.INITIAL_CONTRACT_TICKS,
}, { session: this.session });
}
}

close() {
Expand Down Expand Up @@ -408,6 +419,23 @@ class Database {
}
}

/**
* Get contracts configuration data.
*/
async getContractsConfig() {
const contractsConfig = await this.getCollection('contracts_config');
return contractsConfig.findOne({}, { session: this.session });
}

/**
* Update contracts configuration data.
* @param {Object} config data.
*/
async updateContractsConfig(config) {
const contractsConfig = await this.getCollection('contracts_config');
await contractsConfig.updateOne({}, { $set: config }, { session: this.session });
}

/**
* Add a table to the database
* @param {String} contractName name of the contract
Expand Down
40 changes: 40 additions & 0 deletions libs/SmartContracts.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,46 @@ class SmartContracts {
}
}

// register tick action
static async registerTick(database, transaction) {
try {
const { refHiveBlockNumber } = transaction;
const payload = JSON.parse(transaction.payload);
const { contractName, tickAction } = payload;

const existingContract = await database.findContract({ name: contractName });
if (!existingContract) {
return { logs: { errors: ['contract does not exist'] } };
}
const contractsConfig = await database.getContractsConfig();
const { contractTicks } = contractsConfig;
if (contractTicks.find(t => t.contract === contractName && t.action === tickAction)) {
return { logs: { errors: ['contract tick already registered'] } };
}
const newContractTick = {
contract: contractName,
action: tickAction,
startRefBlock: refHiveBlockNumber + 1,
};
contractTicks.push(newContractTick);
await database.updateContractsConfig(contractsConfig);
return {
logs: {
errors: [],
events: [
{
contract: 'contract',
event: 'registerTick',
data: newContractTick,
},
],
},
};
} catch (e) {
return { logs: { errors: [`${e.name}: ${e.message}`] } };
}
}

// execute the smart contract and perform actions on the database if needed
static async executeSmartContract(
database, transaction, blockNumber, timestamp, refHiveBlockId, prevRefHiveBlockId, jsVMTimeout,
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"test14": "./node_modules/mocha/bin/mocha ./test/marketpools.js",
"test15": "./node_modules/mocha/bin/mocha ./test/tokenfunds.js",
"test16": "./node_modules/mocha/bin/mocha ./test/nftauction.js",
"test17": "./node_modules/mocha/bin/mocha ./test/comments.js"
"test17": "./node_modules/mocha/bin/mocha ./test/comments.js",
"test18": "./node_modules/mocha/bin/mocha ./test/ticks.js"
},
"engines": {
"node": ">=13.7.0",
Expand Down
Loading

0 comments on commit f3c328d

Please sign in to comment.