meta-contract-debug
Version:
Meta Contract SDK
274 lines (273 loc) • 11 kB
JavaScript
"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;