tic-traction/ling/Action.js

124 lines
5.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const Ling = wo&&wo.Ling?wo.Ling:require('fon.ling')
const Ticrypto = wo&&wo.Crypto?wo.Crypto:require('tic.crypto')
/******************** Public of instance ********************/
const DAD=module.exports=function Action(prop) {
this._class=this.constructor.name
this.setProp(prop)
}
DAD.__proto__=Ling
DAD._table=DAD.name
const MOM=DAD.prototype
MOM.__proto__=Ling.prototype
/******************** Shared by instances ********************/
MOM._tablekey='hash'
MOM._model= {
hash: { default:undefined, sqlite:'TEXT UNIQUE', mysql:'VARCHAR(64) PRIMARY KEY' }, // 不纳入签名和哈希
version: { default:0, sqlite:'INTEGER' },
type: { default:'Action', sqlite:'TEXT', mysql:'VARCHAR(100)' }, // 是否放在 assets里更好这里该放action自己的version
blockHash: { default:undefined, sqlite:'TEXT', mysql:'VARCHAR(64)' }, // 不纳入签名和哈希。只为了方便查找
timestamp: { default:undefined, sqlite:'TEXT', mysql:'CHAR(24)' },
actorPubkey: { default:undefined, sqlite:'TEXT', mysql:'BINARY(32)' },
actorAddress: { default:undefined, sqlite:'TEXT', mysql:'VARCHAR(50)' },
actorSignature:{ default:undefined, sqlite:'TEXT', mysql:'BINARY(64)' }, // 不纳入签名,纳入哈希
toAddress: { default:undefined, sqlite:'TEXT', mysql:'VARCHAR(50)' },
amount: { 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)' },
dataIndex: { default:undefined, sqlite:'TEXT', mysql:'VARCHAR(50)'}, //用于索引json中存储数据
json: { default:{}, sqlite:'TEXT' } // 开发者自定义字段可以用json格式添加任意数据而不破坏整体结构
}
MOM.packMe = function(keypair){ // 由前端调用,后台不创建
this.actorPubkey=keypair.pubkey
this.actorAddress=Ticrypto.pubkey2address(keypair.pubkey)
this.timestamp=new Date()
this.signMe(keypair.seckey)
this.hashMe()
return this
}
MOM.signMe = function(seckey){ // 由前端调用,后台不该进行签名
let json=this.getJson({exclude:['hash','blockHash','actorSignature']}) // 是前端用户发起事务时签字这时候还不知道进入哪个区块所以不能计入blockHash
this.actorSignature=Ticrypto.sign(json, seckey)
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(){
this.hash=Ticrypto.hash(this.getJson({exclude:['hash', 'blockHash']})) // block.hash 受到所包含的actionList影响所以action不能受blockHash影响否则循环了
return this
}
MOM.verifyHash = function(){
return this.hash===Ticrypto.hash(this.getJson({exclude:['hash', 'blockHash']}))
}
MOM.execute=function(){ // 子类应当覆盖本方法。把action的影响汇总登记到其他表格用于辅助的、索引的表格方便快速索引、处理。每种事务类型都要重定义这个方法。
// save to account or other tables
return this
}
MOM.validate=function(){ // 子类应当覆盖本方法
return true
}
MOM.calculateFee = function(){
return 1000
}
// DAD._init=async function(){
// await DAD.__proto__._init() // create database table at first
// await DAD.actionLoop()
// return this
// }
/*********************** Public of class *******************/
DAD.api={}
DAD.api.getAction=async function(option){
return await DAD.getOne(option)
}
DAD.api.getActionList=async function(option){
return await DAD.getAll(option)
}
DAD.api.prepare=async function(option){ // 前端发来action数据进行初步检查不检查是否可执行--这和事务类型、执行顺序有关,只检查格式是否有效--这是所有事务通用的规范)后放入缓冲池。
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 (action.verifyAddress() && action.verifySig() && action.verifyHash() // 对所有Action类型都通用的验证
&& action.validate()) { // 各子类特有的验证
// mylog.info('Received action='+JSON.stringify(action))
DAD.actionPool[action.hash]=action
wo.Peer.broadcast('/Action/prepare', option)
return action
}
}
return null // 非法的交易数据
}
/********************** Private in class *******************/
DAD.actionPool={} // 随时不断接收新的交易请求
const my = {
}