UNPKG

meta-contract-debug

Version:

Meta Contract SDK

274 lines (273 loc) 11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getQuerySensibleID = exports.getQueryGenesis = exports.getQueryCodehash = exports.updateScript = exports.parseDataPart = exports.newDataPart = exports.genGenesisTxid = exports.getUInt32Buf = exports.getTxIdBuf = exports.getNewTokenScript = exports.getDataPart = exports.getContractCodeHash = exports.getContractCode = exports.getTokenName = exports.getTokenSymbol = exports.getDecimalNum = exports.getTokenAddress = exports.getGenesisHash = exports.getSensibleID = exports.getTokenID = exports.getTokenAmount = exports.getHeaderLen = exports.GENESIS_FLAG = exports.FT_OP_TYPE = exports.OP_UNLOCK_FROM_CONTRACT = exports.OP_TRANSFER = exports.SIGNER_VERIFY_NUM = exports.SIGNER_NUM = exports.PROTO_VERSION = void 0; const BN = require("../../bn.js"); const mvc = require("../../mvc"); const proto = require("../../common/protoheader"); const scryptlib_1 = require("../../scryptlib"); const tokenUtil_1 = require("../../common/tokenUtil"); exports.PROTO_VERSION = 1; exports.SIGNER_NUM = 5; exports.SIGNER_VERIFY_NUM = 3; // <op_pushdata> + <type specific data> + <proto header> + <data_len(4 bytes)> + <version(1 bytes)> // <token type specific data> = <name(40 bytes)> + <symbol(20 bytes)> + <decimal(1 bytes)> + <address(20 bytes)> + <token amount(8 bytes)> + <genesisHash(20 bytes)> + <genesisTxid(36 bytes)> // name 40 // symbol 20 // decimal 1 // address 20 // token amount/token value 8 // genesis hash 20 // genesis txid 36 // token version // 4 // token type // 4 // protp flag // 12 /** * 对应上面10个参数 * */ const TOKEN_NAME_LEN = 40; const TOKEN_SYMBOL_LEN = 20; const DECIMAL_NUM_LEN = 1; const TOKEN_ADDRESS_LEN = 20; const TOKEN_AMOUNT_LEN = 8; const GENESIS_HASH_LEN = 20; const SENSIBLE_ID_LEN = 36; // genesis txid // proto.PROTO_VERSION_LEN // proto.PROTO_TYPE_LEN // proto.PROTO_FLAG_LEN const GENESISTX_ID_OFFSET = SENSIBLE_ID_LEN + proto.getHeaderLen(); const GENESIS_HASH_OFFSET = GENESISTX_ID_OFFSET + GENESIS_HASH_LEN; const TOKEN_AMOUNT_OFFSET = GENESIS_HASH_OFFSET + TOKEN_AMOUNT_LEN; const TOKEN_ADDRESS_OFFSET = TOKEN_AMOUNT_OFFSET + TOKEN_ADDRESS_LEN; const DECIMAL_NUM_OFFSET = TOKEN_ADDRESS_OFFSET + DECIMAL_NUM_LEN; const TOKEN_SYMBOL_OFFSET = DECIMAL_NUM_OFFSET + TOKEN_SYMBOL_LEN; const TOKEN_NAME_OFFSET = TOKEN_SYMBOL_OFFSET + TOKEN_NAME_LEN; const OP_PUSH_LEN = 2; const TOKEN_HEADER_LEN = TOKEN_NAME_OFFSET; const DATA_LEN = TOKEN_HEADER_LEN + OP_PUSH_LEN; exports.OP_TRANSFER = 1; exports.OP_UNLOCK_FROM_CONTRACT = 2; var FT_OP_TYPE; (function (FT_OP_TYPE) { FT_OP_TYPE[FT_OP_TYPE["TRANSFER"] = 1] = "TRANSFER"; FT_OP_TYPE[FT_OP_TYPE["UNLOCK_FROM_CONTRACT"] = 2] = "UNLOCK_FROM_CONTRACT"; })(FT_OP_TYPE = exports.FT_OP_TYPE || (exports.FT_OP_TYPE = {})); var GENESIS_FLAG; (function (GENESIS_FLAG) { GENESIS_FLAG[GENESIS_FLAG["FALSE"] = 0] = "FALSE"; GENESIS_FLAG[GENESIS_FLAG["TRUE"] = 1] = "TRUE"; })(GENESIS_FLAG = exports.GENESIS_FLAG || (exports.GENESIS_FLAG = {})); function getHeaderLen() { return TOKEN_HEADER_LEN; } exports.getHeaderLen = getHeaderLen; function getTokenAmount(script) { if (script.length < TOKEN_AMOUNT_OFFSET) return BN.Zero; return BN.fromBuffer(script.slice(script.length - TOKEN_AMOUNT_OFFSET, script.length - TOKEN_AMOUNT_OFFSET + TOKEN_AMOUNT_LEN), { endian: 'little' }); } exports.getTokenAmount = getTokenAmount; function getTokenID(script) { return mvc.crypto.Hash.sha256ripemd160(script.slice(script.length - GENESIS_HASH_OFFSET, script.length - proto.getHeaderLen())); } exports.getTokenID = getTokenID; function getSensibleID(script0) { if (script0.length < GENESISTX_ID_OFFSET) return { txid: '', index: 0 }; let script = Buffer.from(script0); let sensibleIDBuf = script.slice(script.length - GENESISTX_ID_OFFSET, script.length - GENESISTX_ID_OFFSET + SENSIBLE_ID_LEN); let txid = sensibleIDBuf.slice(0, 32).reverse().toString('hex'); //reverse会改变原对象 let index = sensibleIDBuf.readUIntLE(32, 4); let sensibleID = { txid, index }; return sensibleID; } exports.getSensibleID = getSensibleID; function getGenesisHash(script) { return script .slice(script.length - GENESIS_HASH_OFFSET, // script.length - GENESIS_HASH_OFFSET + GENESISTX_ID_OFFSET script.length - GENESIS_HASH_OFFSET + GENESIS_HASH_LEN) .toString('hex'); } exports.getGenesisHash = getGenesisHash; function getTokenAddress(script) { if (script.length < TOKEN_ADDRESS_OFFSET) return ''; return script .slice(script.length - TOKEN_ADDRESS_OFFSET, script.length - TOKEN_ADDRESS_OFFSET + TOKEN_ADDRESS_LEN) .toString('hex'); } exports.getTokenAddress = getTokenAddress; function getDecimalNum(script) { if (script.length < DECIMAL_NUM_OFFSET) return 0; return script.readUIntLE(script.length - DECIMAL_NUM_OFFSET, DECIMAL_NUM_LEN); } exports.getDecimalNum = getDecimalNum; function getTokenSymbol(script) { if (script.length < TOKEN_SYMBOL_OFFSET) return ''; let buf = script.slice(script.length - TOKEN_SYMBOL_OFFSET, script.length - TOKEN_SYMBOL_OFFSET + TOKEN_SYMBOL_LEN); return buf.toString(); } exports.getTokenSymbol = getTokenSymbol; function getTokenName(script) { if (script.length < TOKEN_NAME_OFFSET) return ''; let buf = script.slice(script.length - TOKEN_NAME_OFFSET, script.length - TOKEN_NAME_OFFSET + TOKEN_NAME_LEN); return buf.toString(); } exports.getTokenName = getTokenName; function getContractCode(script) { return script.slice(0, script.length - DATA_LEN); } exports.getContractCode = getContractCode; function getContractCodeHash(script) { return mvc.crypto.Hash.sha256ripemd160(getContractCode(script)); } exports.getContractCodeHash = getContractCodeHash; function getDataPart(script) { return script.slice(script.length - TOKEN_HEADER_LEN, script.length); } exports.getDataPart = getDataPart; function getNewTokenScript(scriptBuf, address, tokenAmount) { const amountBuf = tokenAmount.toBuffer({ endian: 'little', size: 8 }); const firstBuf = scriptBuf.slice(0, scriptBuf.length - TOKEN_ADDRESS_OFFSET); const newScript = Buffer.concat([ firstBuf, address, amountBuf, scriptBuf.slice(scriptBuf.length - GENESIS_HASH_OFFSET, scriptBuf.length), ]); return newScript; } exports.getNewTokenScript = getNewTokenScript; const getTxIdBuf = function (txid) { const buf = Buffer.from(txid, 'hex').reverse(); return buf; }; exports.getTxIdBuf = getTxIdBuf; const getUInt32Buf = function (index) { const buf = Buffer.alloc(4, 0); buf.writeUInt32LE(index); return buf; }; exports.getUInt32Buf = getUInt32Buf; const genGenesisTxid = function (txid, index) { return Buffer.concat([(0, exports.getTxIdBuf)(txid), (0, exports.getUInt32Buf)(index)]).toString('hex'); }; exports.genGenesisTxid = genGenesisTxid; function newDataPart({ tokenName, tokenSymbol, decimalNum, tokenAddress, tokenAmount, genesisHash, sensibleID, protoVersion, protoType, }) { const tokenNameBuf = Buffer.alloc(TOKEN_NAME_LEN, 0); if (tokenName) { tokenNameBuf.write(tokenName); } const tokenSymbolBuf = Buffer.alloc(TOKEN_SYMBOL_LEN, 0); if (tokenSymbol) { tokenSymbolBuf.write(tokenSymbol); } const decimalBuf = Buffer.alloc(DECIMAL_NUM_LEN, 0); if (decimalNum) { decimalBuf.writeUInt8(decimalNum); } let tokenAmountBuf = Buffer.alloc(TOKEN_AMOUNT_LEN, 0); if (tokenAmount) { tokenAmountBuf = tokenAmount .toBuffer({ endian: 'little', size: TOKEN_AMOUNT_LEN }) .slice(0, TOKEN_AMOUNT_LEN); } const genesisHashBuf = Buffer.alloc(GENESIS_HASH_LEN, 0); if (genesisHash) { genesisHashBuf.write(genesisHash, 'hex'); } // TODO 同样是36位,只是换了个名字叫 genesis txid let sensibleIDBuf = Buffer.alloc(SENSIBLE_ID_LEN, 0); if (sensibleID) { const txidBuf = Buffer.from(sensibleID.txid, 'hex').reverse(); const indexBuf = Buffer.alloc(4, 0); indexBuf.writeUInt32LE(sensibleID.index); sensibleIDBuf = Buffer.concat([txidBuf, indexBuf]); } const protoTypeBuf = Buffer.alloc(proto.PROTO_TYPE_LEN, 0); if (protoType) { protoTypeBuf.writeUInt32LE(protoType); } const protoVersionBuf = Buffer.alloc(proto.PROTO_VERSION_LEN); if (protoVersion) { protoVersionBuf.writeUInt32LE(protoVersion); } let tokenAddressBuf = Buffer.alloc(TOKEN_ADDRESS_LEN, 0); if (tokenAddress) { tokenAddressBuf = Buffer.from(tokenAddress, 'hex'); } const buf = Buffer.concat([ // 新版结构变化 tokenNameBuf, tokenSymbolBuf, decimalBuf, tokenAddressBuf, tokenAmountBuf, genesisHashBuf, sensibleIDBuf, protoVersionBuf, protoTypeBuf, proto.PROTO_FLAG, // 旧版做法 // tokenNameBuf, // tokenSymbolBuf, // genesisFlagBuf, // decimalBuf, // tokenAddressBuf, // tokenAmountBuf, // genesisHashBuf, // rabinPubKeyHashArrayHashBuf, // sensibleIDBuf, // protoVersionBuf, // protoTypeBuf, // proto.PROTO_FLAG, ]); return (0, tokenUtil_1.buildScriptData)(buf); } exports.newDataPart = newDataPart; function parseDataPart(scriptBuf) { let tokenName = getTokenName(scriptBuf); let tokenSymbol = getTokenSymbol(scriptBuf); let decimalNum = getDecimalNum(scriptBuf); let tokenAddress = getTokenAddress(scriptBuf); let tokenAmount = getTokenAmount(scriptBuf); let genesisHash = getGenesisHash(scriptBuf); let sensibleID = getSensibleID(scriptBuf); let protoVersion = proto.getProtoVersion(scriptBuf); let protoType = proto.getProtoType(scriptBuf); return { tokenName, tokenSymbol, decimalNum, tokenAddress, tokenAmount, genesisHash, sensibleID, protoVersion, protoType, }; } exports.parseDataPart = parseDataPart; function updateScript(scriptBuf, dataPartObj) { const firstBuf = scriptBuf.slice(0, scriptBuf.length - TOKEN_HEADER_LEN); const dataPart = newDataPart(dataPartObj); return Buffer.concat([firstBuf, dataPart]); } exports.updateScript = updateScript; function getQueryCodehash(script) { return (0, scryptlib_1.toHex)(getContractCodeHash(script)); } exports.getQueryCodehash = getQueryCodehash; function getQueryGenesis(script) { return (0, scryptlib_1.toHex)(getTokenID(script)); } exports.getQueryGenesis = getQueryGenesis; function getQuerySensibleID(script0) { let script = Buffer.from(script0); let sensibleIDBuf = script.slice(script.length - GENESISTX_ID_OFFSET, script.length - GENESISTX_ID_OFFSET + SENSIBLE_ID_LEN); return (0, scryptlib_1.toHex)(sensibleIDBuf); } exports.getQuerySensibleID = getQuerySensibleID;