升级到目前最新的 node.server/modules/Action/*.js,其中重要的是,把 var Ling = wo&&wo.Ling?wo.Ling:require('fon.ling') 改成 var Ling = require('fon.ling')。原来的写法有 bug! 钱包前端引用了 tic.tool4chain 再引用了 tic.action,在浏览器里报错 "wo 不存在"。

This commit is contained in:
luk.lu 2019-01-09 13:57:00 +08:00
parent dd0260c517
commit 1fd50f0294
2 changed files with 128 additions and 119 deletions

View File

@ -1,7 +1,4 @@
const Action = require('./Action.js') const Action = require('./Action.js')
const Ticrypto = wo&&wo.Crypto?wo.Crypto:require('tic.crypto')
/******************** Public of instance ********************/
const DAD = module.exports = function ActTransfer (prop) { const DAD = module.exports = function ActTransfer (prop) {
this._class = 'ActTransfer' this._class = 'ActTransfer'
@ -9,32 +6,23 @@ const DAD=module.exports=function ActTransfer(prop) {
this.type = 'ActTransfer' this.type = 'ActTransfer'
} }
DAD.__proto__ = Action DAD.__proto__ = Action
// DAD._table=DAD.name // 注释掉从而继承父类Action的数据库表格名
const MOM = DAD.prototype const MOM = DAD.prototype
MOM.__proto__ = Action.prototype MOM.__proto__ = Action.prototype
/******************** Shared by instances ********************/ DAD.validate = async function (action) {
// if (sender && sender.type !== 'multisig' && action.toAddress != action.actorAddress && sender.balance >= action.amount + action.fee){
MOM.validate=function(){ let sender = await wo.Store.getBalance(action.actorAddress)
// return Ticrypto.isAddress(this.toAddress) return action.actorAddress && action.toAddress && action.toAddress != action.actorAddress && action.amount && action.amount > 0 && sender >= action.amount + action.fee && action.fee >= wo.Config.MIN_FEE_ActTransfer
return Ticrypto.isAddress(this.toAddress) && this.fee>=wo.Config.MIN_FEE_ActTransfer
// && wo.Account.accountPool[this.actorAddress].balance>this.amount+this.fee //Todo:引入缓存账户
&&this.toAddress != this.actorAddress
} }
MOM.execute=async function(){ DAD.execute = async function (action) {
let sender= await wo.Account.getOne({Account: { address: this.actorAddress }}) let sender = await wo.Store.getBalance(action.actorAddress)
if (sender && sender.type !== 'multisig' && this.toAddress != this.actorAddress && sender.balance >= this.amount + this.fee){ if (sender >= action.amount + action.fee) {
await sender.setMe({Account:{ balance: sender.balance-this.amount-this.fee }, cond:{ address:sender.address}}) await wo.Store.decrease(action.actorAddress, action.amount + action.fee)
let getter= await wo.Account.getOne({Account: { address: this.toAddress }}) || await wo.Account.addOne({Account: { address: this.toAddress }}) await wo.Store.increase(action.toAddress, action.amount)
await getter.setMe({Account:{ balance: getter.balance+this.amount }, cond:{ address:getter.address}}) return true
// mylog.info('Excecuted action='+JSON.stringify(this))
return this
} }
// mylog.info('balance('+sender.address+')='+sender.balance+' is less than '+this.amount+', 无法转账')
return null return null
} }
/******************** Public of class ********************/
DAD.api = {} DAD.api = {}

View File

@ -1,5 +1,5 @@
const Ling = wo&&wo.Ling?wo.Ling:require('fon.ling') var Ling = require('fon.ling')
const Ticrypto = wo&&wo.Crypto?wo.Crypto:require('tic.crypto') var Ticrypto = require('tic.crypto')
/** ****************** Public of instance ********************/ /** ****************** Public of instance ********************/
@ -26,14 +26,10 @@ MOM._model= {
toAddress: { default: undefined, sqlite: 'TEXT', mysql: 'VARCHAR(50)' }, toAddress: { default: undefined, sqlite: 'TEXT', mysql: 'VARCHAR(50)' },
amount: { default: 0, sqlite: 'NUMERIC', mysql: 'BIGINT' }, amount: { default: 0, sqlite: 'NUMERIC', mysql: 'BIGINT' },
fee: { default: 0, sqlite: 'NUMERIC', mysql: 'BIGINT' }, fee: { default: 0, sqlite: 'NUMERIC', mysql: 'BIGINT' },
// signSignature: { default:undefined, sqlite:'TEXT', mysql:'BINARY(64)' }, // 不纳入签名,纳入哈希
// requesterPubkey:{ default:undefined, sqlite:'TEXT', mysql:'BINARY(32)' },
// signatures: { default:undefined, sqlite:'TEXT', mysql:'TEXT' },
// option: { default:undefined, sqlite:'TEXT', mysql:'VARCHAR(4096)' },
// act: { default:null, sqlite:'TEXT' }, // 相当于 asch/lisk里的asset
message: { default: undefined, sqlite: 'TEXT', mysql: 'VARCHAR(256)' }, message: { default: undefined, sqlite: 'TEXT', mysql: 'VARCHAR(256)' },
dataIndex: { default: undefined, sqlite: 'TEXT', mysql: 'VARCHAR(50)' }, // 用于索引json中存储数据 dataIndex: { default: undefined, sqlite: 'TEXT', mysql: 'VARCHAR(50)' }, // 用于索引json中存储数据
json: { default:{}, sqlite:'TEXT' } // 开发者自定义字段可以用json格式添加任意数据而不破坏整体结构 method: { default: undefined, sqlite: 'TEXT' },
data: { default: undefined, sqlite: 'TEXT' }
} }
MOM.packMe = function (keypair) { // 由前端调用,后台不创建 MOM.packMe = function (keypair) { // 由前端调用,后台不创建
@ -52,43 +48,61 @@ MOM.signMe = function(seckey){ // 由前端调用,后台不该进行签名
return this return this
} }
MOM.verifySig = function(){
let json=this.getJson({exclude:['hash','blockHash','actorSignature']})
let res=Ticrypto.verify(json, this.actorSignature, this.actorPubkey)
return res
}
MOM.verifyAddress = function(){
return this.actorAddress===Ticrypto.pubkey2address(this.actorPubkey)
}
MOM.hashMe = function () { MOM.hashMe = function () {
this.hash = Ticrypto.hash(this.getJson({ exclude: ['hash', 'blockHash'] })) // block.hash 受到所包含的actionList影响所以action不能受blockHash影响否则循环了 this.hash = Ticrypto.hash(this.getJson({ exclude: ['hash', 'blockHash'] })) // block.hash 受到所包含的actionList影响所以action不能受blockHash影响否则循环了
return this return this
} }
MOM.verifyHash = function(){ DAD.getJson = function (action, option = {}) {
return this.hash===Ticrypto.hash(this.getJson({exclude:['hash', 'blockHash']})) let data = {}
let sortedKey = Object.keys(DAD.prototype._model).sort()
for (let exkey of option.exclude) { sortedKey.splice(sortedKey.indexOf(exkey), 1) }
for (let key of sortedKey) { // 忽略一些不需要签名的属性
data[key] = action[key]
}
let json = JSON.stringify(data)
return json
} }
MOM.execute=function(){ // 子类应当覆盖本方法。把action的影响汇总登记到其他表格用于辅助的、索引的表格方便快速索引、处理。每种事务类型都要重定义这个方法。 DAD.verifySig = function (action) {
let json = DAD.getJson(action, { exclude: ['hash', 'blockHash', 'actorSignature'] })
let res = Ticrypto.verify(json, action.actorSignature, action.actorPubkey)
return res
}
DAD.verifyAddress = function (action) {
return action.actorAddress === Ticrypto.pubkey2address(action.actorPubkey)
}
DAD.verifyHash = function (action) {
return action.hash === Ticrypto.hash(DAD.getJson(action, { exclude: ['hash', 'blockHash'] }))
}
DAD.execute = function () { // 子类应当覆盖本方法。把action的影响汇总登记到其他表格用于辅助的、索引的表格方便快速索引、处理。每种事务类型都要重定义这个方法。
// save to account or other tables // save to account or other tables
return this return this
} }
MOM.validate=function(){ // 子类应当覆盖本方法 DAD.calculateFee = function () {
return true
}
MOM.calculateFee = function(){
return 1000 return 1000
} }
/**
// DAD._init=async function(){ * 获取一批交易在出块时调用调用actionPool的内容被深拷贝到currentActionPool后自动清空
// await DAD.__proto__._init() // create database table at first * 所以在一次出块期间只能调用一次
// await DAD.actionLoop() */
// return this DAD.getActionBatch = function () {
// } let actionBatch = {
actionPool: JSON.parse(JSON.stringify(DAD.actionPool)), // deep copy
totalAmount: DAD.actionPoolInfo.totalAmount,
totalFee: DAD.actionPoolInfo.totalFee
}
DAD.actionPool = {}
DAD.actionPoolInfo = {
totalAmount: 0,
totalFee: 0
}
return actionBatch
}
/** ********************* Public of class *******************/ /** ********************* Public of class *******************/
DAD.api = {} DAD.api = {}
@ -101,15 +115,20 @@ DAD.api.getActionList=async function(option){
return await DAD.getAll(option) return await DAD.getAll(option)
} }
DAD.api.prepare=async function(option){ // 前端发来action数据进行初步检查不检查是否可执行--这和事务类型、执行顺序有关,只检查格式是否有效--这是所有事务通用的规范)后放入缓冲池。 DAD.api.prepare = async function (option) {
// 前端发来action数据进行初步检查不检查是否可执行--这和事务类型、执行顺序有关,只检查格式是否有效--这是所有事务通用的规范)后放入缓冲池。
if (option && option.Action && option.Action.type && option.Action.hash && !DAD.actionPool[option.Action.hash]) { if (option && option.Action && option.Action.type && option.Action.hash && !DAD.actionPool[option.Action.hash]) {
let action=new wo[option.Action.type](option.Action) // 一次性把option.Action里送来的参数导入新建的action if (DAD.verifyAddress(option.Action) &&
if (action.verifyAddress() && action.verifySig() && action.verifyHash() // 对所有Action类型都通用的验证 DAD.verifySig(option.Action) &&
&& action.validate()) { // 各子类特有的验证 DAD.verifyHash(option.Action) &&
// mylog.info('Received action='+JSON.stringify(action)) !DAD.actionPool[option.Action.hash] &&
DAD.actionPool[action.hash]=action (await wo[option.Action.type].validate(option.Action))
) {
DAD.actionPool[option.Action.hash] = option.Action
DAD.actionPoolInfo.totalAmount += option.Action.amount || 0
DAD.actionPoolInfo.totalFee += option.Action.fee || 0
wo.Peer.broadcast('/Action/prepare', option) wo.Peer.broadcast('/Action/prepare', option)
return action return option.Action
} }
} }
return null // 非法的交易数据 return null // 非法的交易数据
@ -117,7 +136,9 @@ DAD.api.prepare=async function(option){ // 前端发来action数据进行初
/** ******************** Private in class *******************/ /** ******************** Private in class *******************/
DAD.actionPool={} // 随时不断接收新的交易请求 DAD.actionPool = {} // 交易池在执行getActionBatch时被清空
// DAD.currentActionPool = {} // 仅包含0~40秒的交易,40~59秒的交易将被堆积到actionPool。
const my = { DAD.actionPoolInfo = {
totalAmount: 0,
totalFee: 0
} }