从tic.common转化而来,彻底脱离对 Base/*, _Ling.js 的依赖,只保留并提供 Action及其子类。
This commit is contained in:
		
						commit
						89975eea2c
					
				
							
								
								
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					# 以'#'开始的行,被视为注释.                                                                                                                          
 | 
				
			||||||
 | 
					node_modules
 | 
				
			||||||
 | 
					package-lock.json
 | 
				
			||||||
 | 
					.vscode
 | 
				
			||||||
 | 
					.svn
 | 
				
			||||||
 | 
					~*
 | 
				
			||||||
 | 
					.gitattributes
 | 
				
			||||||
							
								
								
									
										6
									
								
								index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								index.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					const Action = require('./ling/Action.js')
 | 
				
			||||||
 | 
					const ActTransfer = require('./ling/ActTransfer.js')
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
						Action,
 | 
				
			||||||
 | 
					    ActTransfer
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										40
									
								
								ling/ActTransfer.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								ling/ActTransfer.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					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) {
 | 
				
			||||||
 | 
					  this._class='ActTransfer'
 | 
				
			||||||
 | 
					  this.setProp(prop) // 没有定义 ActTransfer.prototype._model,因此继承了上级Action.prototype._model,因此通过this.setProp,继承了上级Action定义的实例自有数据。另一个方案是,调用 Action.call(this, prop)
 | 
				
			||||||
 | 
					  this.type='ActTransfer'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					DAD.__proto__= Action
 | 
				
			||||||
 | 
					// DAD._table=DAD.name // 注释掉,从而继承父类Action的数据库表格名
 | 
				
			||||||
 | 
					const MOM=DAD.prototype
 | 
				
			||||||
 | 
					MOM.__proto__=Action.prototype
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******************** Shared by instances ********************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MOM.validate=function(){
 | 
				
			||||||
 | 
					  // return Ticrypto.isAddress(this.toAddress)
 | 
				
			||||||
 | 
					  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(){
 | 
				
			||||||
 | 
					  let sender= await wo.Account.getOne({Account: { address: this.actorAddress }})
 | 
				
			||||||
 | 
					  if (sender && sender.type !== 'multisig' && this.toAddress != this.actorAddress && sender.balance >= this.amount + this.fee){
 | 
				
			||||||
 | 
					    await sender.setMe({Account:{ balance: sender.balance-this.amount-this.fee }, cond:{ address:sender.address}})
 | 
				
			||||||
 | 
					    let getter= await wo.Account.getOne({Account: { address: this.toAddress }}) || await wo.Account.addOne({Account: { address: this.toAddress }})
 | 
				
			||||||
 | 
					    await getter.setMe({Account:{ balance: getter.balance+this.amount }, cond:{ address:getter.address}})
 | 
				
			||||||
 | 
					    // mylog.info('Excecuted action='+JSON.stringify(this))
 | 
				
			||||||
 | 
					    return this
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  // mylog.info('balance('+sender.address+')='+sender.balance+' is less than '+this.amount+', 无法转账')
 | 
				
			||||||
 | 
					  return null
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******************** Public of class ********************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DAD.api={}
 | 
				
			||||||
							
								
								
									
										123
									
								
								ling/Action.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								ling/Action.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,123 @@
 | 
				
			|||||||
 | 
					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 = {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "tic.common",
 | 
				
			||||||
 | 
					  "version": "0.1.5",
 | 
				
			||||||
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "fon.ling": "git+https://git.faronear.org/fon/fon.ling",
 | 
				
			||||||
 | 
					    "tic.crypto": "git+https://git.faronear.org/tic/tic.crypto"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "devDependencies": {},
 | 
				
			||||||
 | 
					  "scripts": {},
 | 
				
			||||||
 | 
					  "author": ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user