UNPKG

wowok

Version:

Create, collaborate, and transact on your own terms with the AI-driven web3 collaboration protocol.

1,059 lines 50 kB
var _a; import { Inputs } from '@mysten/sui/transactions'; import { Protocol, ContextType, OperatorType, ValueType, SER_VALUE, IsContextWitness, MODULES, WitnessObjectModule, WitnessForModule } from './protocol.js'; import { parse_object_type, array_unique, Bcs, ulebDecode, IsValidAddress, IsValidArray, readOption, readOptionString, deepCopy } from './utils.js'; import { ERROR, Errors } from './exception.js'; import { CMD_CHECK_GUARD, Guard, GUARD_QUERIES, GuardMaker } from './guard.js'; import { bcs } from '@mysten/sui/bcs'; import { Service } from './service.js'; import { Arbitration } from './arbitration.js'; import { Progress } from './progress.js'; export class GuardParser { constructor(guards) { this.guard_list = []; this.guardlist = () => { return this.guard_list; }; this.future_fills = () => { const ret = []; this.guard_list.forEach((g) => { // cmd already in query_list, so filter it out. //console.log(g.constant); console.log(g.input) g.constant.filter((i) => i.bWitness).forEach((v) => { let cited = 0; g.input.forEach((k) => { if (k.identifier === v.identifier) cited++; }); ret.push({ guard: g.id, witness: undefined, identifier: v.identifier, ..._a.ConstantWitnessModule(v), type: v.type, cmd: v.cmd, witnessTypes: v.witness, cited: cited }); // module 很重要,需要得到 }); }); return ret; }; this.fetch_witness = async (fill) => { if (!fill || fill.length === 0) return; // 所有需要查询的witness, 根据module字段获得 const witness = array_unique(fill.filter(v => v.witness_module !== undefined).map(v => v.witness)); if (witness.length === 0) return; const res = await Protocol.Instance().query_raw(witness, { showType: true, showContent: true }); //console.log(res); const witnessObjectInfo = new Map(); // 报错witness 类型信息等 // 查询并填充cmd的witness for (let i = 0; i < res.length; ++i) { const v = res[i]; const type_raw = v?.data?.type ?? undefined; const objectid = v?.data?.objectId ?? undefined; if (!type_raw || !objectid) return; const t = Protocol.Instance().object_name_from_type_repr(type_raw); switch (t) { case 'Progress': { const machine = v?.data?.content?.fields?.machine; fill.filter(v => v.witness === objectid && v.witness_module === MODULES.progress).forEach(v => { v.cmd.forEach(i => { switch (i.witness) { case ContextType.TYPE_PROGRESS_MACHINE: i.witness_object = machine; break; } }); }); witnessObjectInfo.set(objectid, { module: MODULES.progress }); break; } case 'Order': { const service = v?.data?.content?.fields?.service; const machine = v?.data?.content?.fields?.machine; const progress = v?.data?.content?.fields?.progress; fill.filter(v => v.witness === objectid && v.witness_module === MODULES.order).forEach(v => { v.cmd.forEach(i => { switch (i.witness) { case ContextType.TYPE_ORDER_MACHINE: i.witness_object = machine; break; case ContextType.TYPE_ORDER_PROGRESS: i.witness_object = progress; break; case ContextType.TYPE_ORDER_SERVICE: i.witness_object = service; break; } }); }); witnessObjectInfo.set(objectid, { module: MODULES.order, type: Service.parseOrderObjectType(type_raw) }); break; } case 'Arb': { const arbitration = v?.data?.content?.fields?.arbitration; const order = v?.data?.content?.fields?.order; const order_res = await Protocol.Instance().query_raw([order], { showType: true, showContent: true }); const service = order_res[0]?.data?.content?.fields?.service; const machine = order_res[0]?.data?.content?.fields?.machine; const progress = order_res[0]?.data?.content?.fields?.progress; const order_type = order_res[0]?.data?.type ?? undefined; fill.filter(v => v.witness === objectid && v.witness_module === MODULES.arb).forEach(v => { v.cmd.forEach(i => { switch (i.witness) { case ContextType.TYPE_ARB_MACHINE: i.witness_object = machine; break; case ContextType.TYPE_ARB_PROGRESS: i.witness_object = progress; break; case ContextType.TYPE_ARB_SERVICE: i.witness_object = service; break; case ContextType.TYPE_ARB_ORDER: i.witness_object = order; break; case ContextType.TYPE_ARB_ARBITRATION: i.witness_object = arbitration; break; } }); }); witnessObjectInfo.set(objectid, { module: MODULES.arb, type: Arbitration.parseArbObjectType(type_raw), order: order, order_type: order_type }); break; } } } ; // 检查结果的完整性 fill.filter(v => v.witness_module !== undefined).forEach(v => { v.cmd.forEach(i => { if (i.witness && !i.witness_object) { ERROR(Errors.Fail, `fetch_witness : ${i}`); } }); }); return witnessObjectInfo; }; this.done = async (fill, onPassportQueryReady) => { let objects = []; // 填充所有的witness object const witnessObjectInfo = await this.fetch_witness(fill); // check all witness and get all objects to query. this.guard_list.forEach((g) => { g.constant.forEach((v) => { if (v.bWitness) { const value = fill?.find((i) => i.identifier === v.identifier && i.guard === g.id); if (!value) { ERROR(Errors.Fail, 'done: invalid witness ' + v.identifier); } else { v.value = value.witness; // 写witness } } }); g.input.filter((v) => v.cmd !== undefined).forEach((i) => { if (i.identifier !== undefined) { if (IsContextWitness(i.value)) { //是否是 type witness const value = fill?.find(c => c.guard === g.id && c.identifier === i.identifier); const cmd = value?.cmd.find(c => c.cmd === i.cmd); if (!value || !cmd || !IsValidAddress(cmd.witness_object)) ERROR(Errors.Fail, `witness invalid or not found: ${i}`); objects.push(cmd.witness_object); // 将witness查询对象地址加入 } else { // self witness const value = g.constant.find((c) => c.identifier === i.identifier && c.type === ValueType.TYPE_ADDRESS); if (!value || !IsValidAddress(value.value)) ERROR(Errors.Fail, 'done: invalid identifier ' + i.identifier); objects.push(value.value); // const address(witness or not) } } else { objects.push(i.value); //@ address } }); }); if (onPassportQueryReady) { if (objects.length === 0) { onPassportQueryReady(this.done_helper([], fill, witnessObjectInfo)); return; } Protocol.Instance().query_raw(array_unique(objects), { showType: true }).then((res) => { onPassportQueryReady(this.done_helper(res, fill, witnessObjectInfo)); }).catch(e => { console.log(e); onPassportQueryReady(undefined); }); return; } else { let res = []; if (objects.length > 0) { res = await Protocol.Instance().query_raw(array_unique(objects), { showType: true }); } return this.done_helper(res, fill, witnessObjectInfo); } }; // create onchain query for objects : object, movecall-types, id this.object_query = (data, method = 'guard_query') => { for (let k = 0; k < Protocol.Instance().WOWOK_OBJECTS_TYPE().length; k++) { if (data.type.includes(Protocol.Instance().WOWOK_OBJECTS_TYPE()[k])) { // type: pack::m::Object<...> return { target: Protocol.Instance().WOWOK_OBJECTS_PREFIX_TYPE()[k] + method, object: Inputs.SharedObjectRef({ objectId: data.objectId, mutable: false, initialSharedVersion: data.version, }), types: parse_object_type(data.type), id: data.objectId, }; } } }; this.guards = guards; } // ============================================ static Parse_Guard_Helper(guards, res) { const protocol = Protocol.Instance(); const me = new _a(guards); res.forEach((r) => { const c = r.data?.content; if (!c) ERROR(Errors.Fail, 'Parse_Guard_Helper invalid content'); const index = protocol.WOWOK_OBJECTS_TYPE().findIndex(v => { return v.includes('guard::Guard') && v == c.type; }); if (index === -1) ERROR(Errors.Fail, 'Parse_Guard_Helper invalid type: ' + c.type); if (c.fields.input.type === (protocol.package('base') + '::bcs::BCS')) { const constants = _a.parse_constant(c.fields.constants); // MUST first const inputs = _a.parse_bcs(constants, Uint8Array.from(c.fields.input.fields.bytes)); me.guard_list.push({ id: c.fields.id.id, input: [...inputs], constant: [...constants], digest: r.data?.digest ?? '', version: r.data?.version ?? '' }); } else { ERROR(Errors.Fail, 'Parse_Guard_Helper invalid package: ' + c.fields.input.type); } }); return me; } // 检查cmd(含非witness)和witness的模块一致性,并返回模块 static ConstantWitnessModule(constant) { let module; let witness_module; for (let i = 0; i < constant.cmd.length; ++i) { if (constant.cmd[i].witness !== undefined) { // witness cmd if (!IsContextWitness(constant.cmd[i].witness)) { ERROR(Errors.Fail, `ConstantWitnessModule witness type invalid on identifier ${constant}`); } const m = WitnessObjectModule(constant.cmd[i].witness); if (!witness_module) { witness_module = m; } else { if (witness_module !== m) { ERROR(Errors.Fail, `ConstantWitnessModule wintesses modules are different on identifier ${constant}`); } } } else { const q = GUARD_QUERIES.find((q) => q.query_id == constant.cmd[i].cmd); if (q) { if (!module) { module = q.module; } else { if (module !== q.module) { ERROR(Errors.Fail, `ConstantWitnessModule modules are different on identifier ${constant}`); } } } else { ERROR(Errors.Fail, `ConstantWitnessModule. cmd not found on identifier ${constant}`); } } } for (let i = 0; i < constant.witness.length; ++i) { const m = WitnessObjectModule(constant.witness[i]); if (!witness_module) { witness_module = m; } else { if (witness_module !== m) { ERROR(Errors.Fail, `ConstantWitnessModule modules are different on identifier ${constant}`); } } } return { module: module, witness_module: witness_module }; } static AddConstantWitness(constants, identifier, type) { const c = constants.find(i => i.bWitness && i.identifier === identifier); if (!c) ERROR(Errors.Fail, `AddConstantWitness identifier ${identifier} with witness not found`); const module = _a.ConstantWitnessModule(c); const m = WitnessObjectModule(type); if (module.witness_module && m !== module.witness_module) { ERROR(Errors.Fail, `AddConstantWitness.type module not matach ${type}`); } const n = c.witness.find(v => v === type); c.info = { module: m }; if (!n) c.witness.push(type); } static AddConstantCmd(constants, identifier, cmd) { let c; if (cmd.witness !== undefined) { c = constants.find(i => i.bWitness && i.identifier === identifier); if (!c) ERROR(Errors.Fail, `AddConstantCmd identifier ${identifier} with witness not found`); const module = _a.ConstantWitnessModule(c); GuardMaker.checkCmdWitness(cmd.cmd, cmd.witness); const m = WitnessForModule(cmd.witness); if (module.witness_module && m !== module.witness_module) { // 使用module_witness字段 ERROR(Errors.WitnessTypeInvalid, `AddConstantCmd module not match ${identifier}`); } c.info = { module: m }; } else { c = constants.find(i => i.identifier === identifier); if (!c) ERROR(Errors.Fail, `AddConstantCmd identifier ${identifier} with witness not found`); const module = _a.ConstantWitnessModule(c); const m = GUARD_QUERIES.find(v => v.query_id === cmd.cmd); if (!m) { ERROR(Errors.Fail, `AddConstantCmd.cmd not found ${cmd}`); } if (module.module && m?.module !== module.module) { // 使用module字段 ERROR(Errors.Fail, `AddConstantCmd module not match ${identifier}`); } } c.cmd.push(cmd); //@ 每个命令都添加进去,不考虑重复 } done_helper(res, fill, info) { let query = []; let guards = []; this.guard_list.forEach(g => { guards.push(g.id); let object_id; g.input.filter((v) => v.cmd !== undefined).forEach(q => { if (q.identifier !== undefined) { if (IsContextWitness(q.value)) { //是否是 type witness const value = fill?.find(c => c.guard === g.id && c.identifier === q.identifier); object_id = value?.cmd.find(c => c.cmd === q.cmd)?.witness_object; } else { // self witness const value = g.constant.find((c) => c.identifier === q.identifier && c.type === ValueType.TYPE_ADDRESS); if (!value || !IsValidAddress(value.value)) { ERROR(Errors.Fail, `done_helper: invalid identifier ${q.identifier}`); } object_id = value?.value; } } else { object_id = q.value; //@ address } let r = res.find(r => r.data?.objectId == object_id); if (!r) { ERROR(Errors.Fail, 'query object not match'); } let object = this.object_query(r.data); // build passport query objects if (!object) { ERROR(Errors.Fail, 'query object fail'); } query.push(object); }); }); return { query: query, info: this.guard_list, witnessObjectInfo: info }; } } _a = GuardParser; // 解析一个Guard的数据,生成树结构和表结构 GuardParser.DeGuardObject_FromData = (guard_constants, guard_input_bytes) => { let constants = _a.parse_constant(guard_constants); // console.log(constants) let inputs = _a.parse_bcs(constants, guard_input_bytes); if (!inputs || inputs.length == 0) ERROR(Errors.Fail, 'GuardObject: data parsed error'); let stack = []; inputs.forEach((d) => { _a.ResolveData(constants, stack, { ...d, child: [] }); }); if (stack.length != 1) { ERROR(Errors.Fail, 'GuardObject: parse error'); } return { object: stack.pop(), constant: constants }; }; /// 解析一个Guard地址,生成树结构(通过ResolveData)和表结构。 用于UI对单个guard作图 GuardParser.DeGuardObject = async (protocol, guard) => { if (!IsValidAddress(guard)) { ERROR(Errors.IsValidAddress, 'GuardObject guard'); } let res = await protocol.query_raw([guard]); if (res.length == 0 || !res[0].data || res[0].data?.objectId != guard) { ERROR(Errors.Fail, 'GuardObject query error'); } // console.log(res[0].data?.content); let content = res[0].data.content; if (content?.type != protocol.package('base') + '::guard::Guard') { ERROR(Errors.Fail, 'GuardObject object invalid'); } return _a.DeGuardObject_FromData(content.fields.constants, content.fields.input.fields.bytes); }; GuardParser.ResolveData = (constants, stack, current) => { switch (current.type) { case OperatorType.TYPE_LOGIC_NOT: current.ret_type = ValueType.TYPE_BOOL; if (stack.length < 1) ERROR(Errors.Fail, `ResolveData: TYPE_LOGIC_NOT`); var param = stack.pop(); if (!param.ret_type || param.ret_type != ValueType.TYPE_BOOL) { ERROR(Errors.Fail, 'ResolveData: TYPE_LOGIC_NOT type invalid'); } current.child.push(param); stack.push(current); return; case OperatorType.TYPE_NUMBER_ADDRESS: current.ret_type = ValueType.TYPE_ADDRESS; if (stack.length < 1) ERROR(Errors.Fail, 'ResolveData: TYPE_NUMBER_ADDRESS'); var param = stack.pop(); if (!param.ret_type || !GuardMaker.match_u256(param.ret_type)) { ERROR(Errors.Fail, 'ResolveData: TYPE_NUMBER_ADDRESS type invalid'); } current.child.push(param); stack.push(current); return; case OperatorType.TYPE_SAFE_U8: current.ret_type = ValueType.TYPE_U8; if (stack.length < 1) ERROR(Errors.Fail, 'ResolveData: TYPE_SAFE_U8'); var param = stack.pop(); if (!param.ret_type || !GuardMaker.match_u256(param.ret_type)) { ERROR(Errors.Fail, 'ResolveData: TYPE_SAFE_U8 type invalid'); } current.child.push(param); stack.push(current); return; case OperatorType.TYPE_SAFE_U64: current.ret_type = ValueType.TYPE_U64; if (stack.length < 1) ERROR(Errors.Fail, 'ResolveData: TYPE_SAFE_U64'); var param = stack.pop(); if (!param.ret_type || !GuardMaker.match_u256(param.ret_type)) { ERROR(Errors.Fail, 'ResolveData: TYPE_SAFE_U64 type invalid'); } current.child.push(param); stack.push(current); return; case OperatorType.TYPE_STRING_LOWERCASE: current.ret_type = ValueType.TYPE_STRING; if (stack.length < 1) ERROR(Errors.Fail, 'ResolveData: TYPE_STRING_LOWERCASE'); var param = stack.pop(); if (!param.ret_type || param.ret_type !== ValueType.TYPE_STRING) { ERROR(Errors.Fail, 'ResolveData: TYPE_STRING_LOWERCASE type invalid'); } current.child.push(param); stack.push(current); return; case OperatorType.TYPE_LOGIC_AS_U256_GREATER: case OperatorType.TYPE_LOGIC_AS_U256_GREATER_EQUAL: case OperatorType.TYPE_LOGIC_AS_U256_LESSER: case OperatorType.TYPE_LOGIC_AS_U256_LESSER_EQUAL: case OperatorType.TYPE_LOGIC_AS_U256_EQUAL: case OperatorType.TYPE_NUMBER_ADD: case OperatorType.TYPE_NUMBER_DEVIDE: case OperatorType.TYPE_NUMBER_MOD: case OperatorType.TYPE_NUMBER_MULTIPLY: case OperatorType.TYPE_NUMBER_SUBTRACT: if (current.type === OperatorType.TYPE_LOGIC_AS_U256_GREATER || current.type === OperatorType.TYPE_LOGIC_AS_U256_GREATER_EQUAL || current.type === OperatorType.TYPE_LOGIC_AS_U256_LESSER || current.type === OperatorType.TYPE_LOGIC_AS_U256_LESSER_EQUAL || current.type === OperatorType.TYPE_LOGIC_AS_U256_EQUAL) { current.ret_type = ValueType.TYPE_BOOL; } else { current.ret_type = ValueType.TYPE_U256; } if (stack.length < current.value || current.value < 2) ERROR(Errors.Fail, 'ResolveData: ' + current.type); for (let i = 0; i < current.value; ++i) { var p = stack.pop(); if (!p.ret_type || !GuardMaker.match_u256(p.ret_type)) ERROR(Errors.Fail, 'ResolveData: ' + current.type + ' INVALID param type'); current.child.push(p); } stack.push(current); return; case OperatorType.TYPE_LOGIC_EQUAL: current.ret_type = ValueType.TYPE_BOOL; if (stack.length < current.value || current.value < 2) ERROR(Errors.Fail, 'ResolveData: ' + current.type); var p0 = stack.pop(); current.child.push(p0); for (let i = 1; i < current.value; ++i) { var p = stack.pop(); if (!p.ret_type || (p.ret_type != p0.ret_type)) ERROR(Errors.Fail, 'ResolveData: ' + current.type + ' INVALID param type'); current.child.push(p); } stack.push(current); return; case OperatorType.TYPE_LOGIC_HAS_SUBSTRING: current.ret_type = ValueType.TYPE_BOOL; if (stack.length < current.value || current.value < 2) ERROR(Errors.Fail, 'ResolveData: ' + current.type); for (let i = 0; i < current.value; ++i) { var p = stack.pop(); if (!p.ret_type || (p.ret_type != ValueType.TYPE_STRING)) ERROR(Errors.Fail, 'ResolveData: ' + current.type + ' INVALID param type'); current.child.push(p); } stack.push(current); return; case OperatorType.TYPE_LOGIC_AND: case OperatorType.TYPE_LOGIC_OR: current.ret_type = ValueType.TYPE_BOOL; if (stack.length < current.value || current.value < 2) ERROR(Errors.Fail, 'ResolveData: ' + current.type); for (let i = 0; i < current.value; ++i) { var p = stack.pop(); if (!p.ret_type || (p.ret_type != ValueType.TYPE_BOOL)) ERROR(Errors.Fail, 'ResolveData: ' + current.type + ' INVALID param type'); current.child.push(p); } stack.push(current); return; case OperatorType.TYPE_QUERY: if (!current?.cmd) ERROR(Errors.Fail, 'ResolveData: cmd invalid ' + current.type); let r = Guard.GetCmd(current.cmd); if (!r) ERROR(Errors.Fail, 'ResolveData: cmd not supported ' + current.type); current.ret_type = r?.return; if (stack.length < r.parameters.length) ERROR(Errors.Fail, 'ResolveData: cmd param lost ' + current.type); r.parameters.forEach((e) => { let d = stack.pop(); if (!d?.ret_type || d.ret_type != e) { ERROR(Errors.Fail, 'ResolveData: cmd param not match ' + current.type); } current.child.push(d); }); stack.push(current); return; case ValueType.TYPE_ADDRESS: case ValueType.TYPE_BOOL: case ValueType.TYPE_U128: case ValueType.TYPE_U256: case ValueType.TYPE_U64: case ValueType.TYPE_U8: case ValueType.TYPE_VEC_ADDRESS: case ValueType.TYPE_VEC_BOOL: case ValueType.TYPE_VEC_U128: case ValueType.TYPE_VEC_U256: case ValueType.TYPE_VEC_U64: case ValueType.TYPE_VEC_U8: case ValueType.TYPE_VEC_VEC_U8: case ValueType.TYPE_OPTION_ADDRESS: case ValueType.TYPE_OPTION_BOOL: case ValueType.TYPE_OPTION_U128: case ValueType.TYPE_OPTION_U256: case ValueType.TYPE_OPTION_U64: case ValueType.TYPE_OPTION_U8: case ValueType.TYPE_STRING: current.ret_type = current.type; stack.push(current); return; case ContextType.TYPE_CLOCK: current.ret_type = ValueType.TYPE_U64; stack.push(current); return; case ContextType.TYPE_SIGNER: current.ret_type = ValueType.TYPE_ADDRESS; stack.push(current); return; case ContextType.TYPE_GUARD: current.ret_type = ValueType.TYPE_ADDRESS; stack.push(current); return; case ContextType.TYPE_CONSTANT: let v = constants.find((e) => e.identifier == current?.identifier); if (!v) ERROR(Errors.Fail, 'ResolveData: identifier invalid ' + current.type); current.ret_type = v?.type; stack.push(current); return; case ContextType.TYPE_ARB_ARBITRATION: case ContextType.TYPE_ARB_MACHINE: case ContextType.TYPE_ARB_ORDER: case ContextType.TYPE_ARB_PROGRESS: case ContextType.TYPE_ARB_SERVICE: case ContextType.TYPE_ORDER_MACHINE: case ContextType.TYPE_ORDER_PROGRESS: case ContextType.TYPE_ORDER_SERVICE: case ContextType.TYPE_PROGRESS_MACHINE: { current.ret_type = ValueType.TYPE_ADDRESS; stack.push(current); return; } } ERROR(Errors.Fail, 'ResolveData: type invalid ' + current.type); }; // 解析一些Guards,生成parser结构。用于生成fill数据或进行passport验证。 GuardParser.Create = async (guards) => { if (!IsValidArray(guards, IsValidAddress)) { ERROR(Errors.InvalidParam, 'GuardParser.Create: guards invalid'); } let guard_list = array_unique(guards); let check_guards = [...guard_list]; let i = 0; const parsers = []; for (; i < _a.MAX_REPOSITORY_DEPTH; ++i) { const res = await Protocol.Instance().query_raw(check_guards); const p = _a.Parse_Guard_Helper(guards, res); const repositories = []; p.guardlist().forEach((g) => { g.input.forEach((i) => { if (i.cmd !== undefined && CMD_CHECK_GUARD.includes(i.cmd)) { if (i.identifier !== undefined) { const id = g.constant.find((c) => c.identifier === i.identifier); if (id && id.value) { repositories.push(id.value); } } else if (i.value) { repositories.push(i.value); } } }); }); parsers.push(p); if (repositories.length === 0) { break; } check_guards = await _a.RepositoryGuards(repositories); if (check_guards.length === 0) { break; } } if (i >= _a.MAX_REPOSITORY_DEPTH) { ERROR(Errors.Fail, `GuardParser.Create: Retrieve guards from the Repository with a maximum depth of more than ${_a.MAX_REPOSITORY_DEPTH} levels.`); } // concatenate all parsers for (let i = 1; i < parsers.length; ++i) { parsers[0].guard_list = parsers[0].guard_list.concat(deepCopy(parsers[i].guard_list)); parsers[0].guards = parsers[0].guards.concat(parsers[i].guards); } if (parsers.length > 0) { return parsers[0]; } }; // fetch repository guards GuardParser.RepositoryGuards = async (repositories) => { const res = await Protocol.Instance().query_raw(repositories); const guards = []; for (let i = 0; i < res.length; ++i) { if (res[i].data?.content?.fields?.guard) { guards.push((res[i].data?.content).fields.guard); } } return guards; }; GuardParser.parse_constant = (constants) => { let ret = []; constants.forEach((c) => { let v = c?.fields ?? c; // graphql dosnot 'fields', but rpcall has. const data = Uint8Array.from(v.value); const type = data.slice(0, 1)[0]; if (v.bWitness) { //@ witness ret.push({ identifier: v.identifier, type: type, bWitness: v.bWitness, value: undefined, cmd: [], witness: [] }); return; } var value = data.slice(1); switch (type) { case ValueType.TYPE_ADDRESS: value = Bcs.getInstance().de(ValueType.TYPE_ADDRESS, Uint8Array.from(value)).toString(); break; case ValueType.TYPE_BOOL: case ValueType.TYPE_U8: case ValueType.TYPE_U64: case ValueType.TYPE_U128: case ValueType.TYPE_U256: case ValueType.TYPE_VEC_U8: case ValueType.TYPE_VEC_U64: case ValueType.TYPE_VEC_U128: case ValueType.TYPE_VEC_ADDRESS: case ValueType.TYPE_VEC_BOOL: case ValueType.TYPE_VEC_VEC_U8: case ValueType.TYPE_OPTION_ADDRESS: case ValueType.TYPE_OPTION_BOOL: case ValueType.TYPE_OPTION_U128: case ValueType.TYPE_OPTION_U8: case ValueType.TYPE_OPTION_U64: case ValueType.TYPE_OPTION_U256: case ValueType.TYPE_VEC_U256: case ValueType.TYPE_STRING: case ValueType.TYPE_OPTION_STRING: case ValueType.TYPE_OPTION_VEC_U8: case ValueType.TYPE_VEC_STRING: let de = SER_VALUE.find(s => s.type == type); if (!de) ERROR(Errors.Fail, 'GuardObject de error'); value = Bcs.getInstance().de(type, Uint8Array.from(value)); break; default: ERROR(Errors.Fail, 'GuardObject constant type invalid:' + type); } ret.push({ identifier: v.identifier, type: type, bWitness: v.bWitness, value: value, witness: [], cmd: [] }); }); return ret; }; GuardParser.parse_bcs = (constants, chain_bytes) => { let bytes = Uint8Array.from(chain_bytes); let arr = [].slice.call(bytes.reverse()); let data = []; while (arr.length > 0) { let type = arr.shift(); let value; let cmd; let identifier; switch (type) { case ContextType.TYPE_SIGNER: case ContextType.TYPE_CLOCK: case ContextType.TYPE_GUARD: case OperatorType.TYPE_LOGIC_NOT: case OperatorType.TYPE_NUMBER_ADDRESS: case OperatorType.TYPE_STRING_LOWERCASE: case OperatorType.TYPE_SAFE_U64: case OperatorType.TYPE_SAFE_U8: break; case OperatorType.TYPE_LOGIC_AS_U256_GREATER: case OperatorType.TYPE_LOGIC_AS_U256_GREATER_EQUAL: case OperatorType.TYPE_LOGIC_AS_U256_LESSER: case OperatorType.TYPE_LOGIC_AS_U256_LESSER_EQUAL: case OperatorType.TYPE_LOGIC_AS_U256_EQUAL: case OperatorType.TYPE_LOGIC_EQUAL: case OperatorType.TYPE_LOGIC_HAS_SUBSTRING: case OperatorType.TYPE_NUMBER_ADD: case OperatorType.TYPE_NUMBER_DEVIDE: case OperatorType.TYPE_NUMBER_MOD: case OperatorType.TYPE_NUMBER_MULTIPLY: case OperatorType.TYPE_NUMBER_SUBTRACT: case OperatorType.TYPE_LOGIC_AND: //@ with logics count case OperatorType.TYPE_LOGIC_OR: value = arr.shift(); break; case ContextType.TYPE_ARB_ARBITRATION: case ContextType.TYPE_ARB_MACHINE: case ContextType.TYPE_ARB_ORDER: case ContextType.TYPE_ARB_PROGRESS: case ContextType.TYPE_ARB_SERVICE: case ContextType.TYPE_ORDER_MACHINE: case ContextType.TYPE_ORDER_PROGRESS: case ContextType.TYPE_ORDER_SERVICE: case ContextType.TYPE_PROGRESS_MACHINE: identifier = arr.shift(); // identifier let v = constants.find((v) => (v.identifier == identifier) && ((v.type == ValueType.TYPE_ADDRESS))); if (!v) { ERROR(Errors.Fail, `GuardParser.parse_bcs: indentifier ${identifier} with type ${ValueType.TYPE_ADDRESS} not in constant`); } value = type; //@ type used //@ 将witness数据加入到常量中 _a.AddConstantWitness(constants, identifier, type); break; case ContextType.TYPE_CONSTANT: identifier = arr.shift(); // identifier break; case ValueType.TYPE_ADDRESS: value = Bcs.getInstance().de(ValueType.TYPE_ADDRESS, Uint8Array.from(arr)).toString(); arr.splice(0, 32); // address break; case ValueType.TYPE_BOOL: case ValueType.TYPE_U8: value = Bcs.getInstance().de(type, Uint8Array.from(arr)); arr.shift(); break; case ValueType.TYPE_U64: value = Bcs.getInstance().de(type, Uint8Array.from(arr)); arr.splice(0, 8); break; case ValueType.TYPE_U128: value = Bcs.getInstance().de(type, Uint8Array.from(arr)); arr.splice(0, 16); break; case ValueType.TYPE_U256: value = Bcs.getInstance().de(type, Uint8Array.from(arr)); arr.splice(0, 32); break; case ValueType.TYPE_VEC_U8: case ValueType.TYPE_VEC_BOOL: case ValueType.TYPE_STRING: let r = ulebDecode(Uint8Array.from(arr)); value = Bcs.getInstance().de(type, Uint8Array.from(arr)); arr.splice(0, r.value + r.length); break; case ValueType.TYPE_VEC_ADDRESS: r = ulebDecode(Uint8Array.from(arr)); value = Bcs.getInstance().de(type, Uint8Array.from(arr)); arr.splice(0, r.value * 32 + r.length); break; case ValueType.TYPE_VEC_U128: r = ulebDecode(Uint8Array.from(arr)); value = Bcs.getInstance().de(type, Uint8Array.from(arr)); arr.splice(0, r.value * 16 + r.length); break; case ValueType.TYPE_VEC_U256: r = ulebDecode(Uint8Array.from(arr)); value = Bcs.getInstance().de(type, Uint8Array.from(arr)); arr.splice(0, r.value * 32 + r.length); break; case ValueType.TYPE_VEC_U64: r = ulebDecode(Uint8Array.from(arr)); value = Bcs.getInstance().de(type, Uint8Array.from(arr)); arr.splice(0, r.value * 8 + r.length); break; case ValueType.TYPE_VEC_VEC_U8: case ValueType.TYPE_VEC_STRING: r = ulebDecode(Uint8Array.from(arr)); arr.splice(0, r.length); let res = []; for (let i = 0; i < r.value; i++) { let r2 = ulebDecode(Uint8Array.from(arr)); res.push(Bcs.getInstance().de(ValueType.TYPE_VEC_U8, Uint8Array.from(arr))); arr.splice(0, r2.length + r2.value); } value = res; break; case OperatorType.TYPE_QUERY: let t = arr.splice(0, 1); // data-type switch (t[0]) { case ValueType.TYPE_ADDRESS: { let addr = Bcs.getInstance().de(ValueType.TYPE_ADDRESS, Uint8Array.from(arr)).toString(); arr.splice(0, 32); // address value = addr; cmd = bcs.u16().parse(Uint8Array.from(arr.splice(0, 2))); // cmd(u16) break; } case ContextType.TYPE_CONSTANT: { let id = arr.splice(0, 1); // key let v = constants.find((v) => (v.identifier == id[0]) && ((v.type == ValueType.TYPE_ADDRESS))); if (!v) { ERROR(Errors.Fail, `GuardParser.parse_bcs: indentifier ${id[0]} with type ${ValueType.TYPE_ADDRESS} not in constant`); } identifier = id[0]; cmd = bcs.u16().parse(Uint8Array.from(arr.splice(0, 2))); // cmd(u16) _a.AddConstantCmd(constants, identifier, { cmd: cmd }); //@ witness的cmd都添加(Self类型) break; } case ContextType.TYPE_ARB_ARBITRATION: case ContextType.TYPE_ARB_MACHINE: case ContextType.TYPE_ARB_ORDER: case ContextType.TYPE_ARB_PROGRESS: case ContextType.TYPE_ARB_SERVICE: case ContextType.TYPE_ORDER_MACHINE: case ContextType.TYPE_ORDER_PROGRESS: case ContextType.TYPE_ORDER_SERVICE: case ContextType.TYPE_PROGRESS_MACHINE: { let id = arr.splice(0, 1); // key let v = constants.find((v) => (v.identifier == id[0]) && v.bWitness && ((v.type == ValueType.TYPE_ADDRESS))); // witness, address type if (!v) { ERROR(Errors.Fail, `GuardParser.parse_bcs: indentifier ${id[0]} with type ${ValueType.TYPE_ADDRESS} not in constant`); } identifier = id[0]; cmd = bcs.u16().parse(Uint8Array.from(arr.splice(0, 2))); // cmd(u16) value = t[0]; //@ value used // 添加witness cmd(witness类型) _a.AddConstantCmd(constants, identifier, { witness: t[0], cmd: cmd }); break; } default: ERROR(Errors.Fail, 'GuardObject: type invalid'); } break; case ValueType.TYPE_OPTION_ADDRESS: let read = readOption(arr, ValueType.TYPE_ADDRESS); value = read.value; if (!read.bNone) arr.splice(0, 32); break; case ValueType.TYPE_OPTION_BOOL: read = readOption(arr, ValueType.TYPE_BOOL); value = read.value; if (!read.bNone) arr.splice(0, 1); break; case ValueType.TYPE_OPTION_U8: read = readOption(arr, ValueType.TYPE_U8); value = read.value; if (!read.bNone) arr.splice(0, 1); break; case ValueType.TYPE_OPTION_U128: read = readOption(arr, ValueType.TYPE_U128); value = read.value; if (!read.bNone) arr.splice(0, 16); break; case ValueType.TYPE_OPTION_U256: read = readOption(arr, ValueType.TYPE_U256); value = read.value; if (!read.bNone) arr.splice(0, 32); break; case ValueType.TYPE_OPTION_U64: read = readOption(arr, ValueType.TYPE_U64); value = read.value; if (!read.bNone) arr.splice(0, 8); break; case ValueType.TYPE_OPTION_STRING: read = readOptionString(arr); // splice in it value = read.value; break; default: ERROR(Errors.Fail, 'GuardObject: parse_bcs types ' + type); } data.push({ type: type, value: value, cmd: cmd, identifier: identifier }); } return data; }; GuardParser.MAX_REPOSITORY_DEPTH = 3; export class Passport { get_object() { return this.passport; } // return passport object used // bObject(true) in cmd env; (false) in service env constructor(txb, query) { this.query_result_async = async (sender) => { this.txb.moveCall({ target: Protocol.Instance().passportFn('query_result'), arguments: [this.passport] }); const res = await Protocol.Client().devInspectTransactionBlock({ sender: sender, transactionBlock: this.txb }); return Passport.ResolveQueryRes(this.txb, res); }; if (query.info.length > Passport.MAX_GUARD_COUNT) { ERROR(Errors.InvalidParam, `Passport: guards count max ${Passport.MAX_GUARD_COUNT}`); } this.txb = txb; //console.log(query) this.passport = this.txb.moveCall({ target: Protocol.Instance().passportFn('new'), arguments: [] }); // add others guards, if any query.info.forEach((g, guard_index) => { const ids = g.constant.filter((i) => i.bWitness).map((v) => v.identifier); const values = g.constant.filter((i) => i.bWitness).map((v) => { const bcs = Bcs.getInstance().ser(v.type, v.value); let r = new Uint8Array(bcs.length + 1); r.set([v.type], 0); r.set(bcs, 1); return [].slice.call(r); }); const guard = g.version !== undefined && g.digest !== undefined ? txb.objectRef({ objectId: g.id, version: g.version, digest: g.digest }) : txb.object(g.id); //console.log(ids); console.log(values) this.txb.moveCall({ target: Protocol.Instance().passportFn('guard_add'), arguments: [this.passport, guard, this.txb.pure.vector('u8', [].slice.call(ids)), this.txb.pure(bcs.vector(bcs.vector(bcs.u8())).serialize([...values]).toBytes())] }); // 对每个witness object处理所有的witness类型请求 const witness_objects = new Map(); g.constant.forEach(v => { const types = []; v.cmd.forEach(i => { if (i.witness && IsContextWitness(i.witness) && !types.includes(i.witness)) { types.push(i.witness); } }); v.witness.forEach(i => { if (i && IsContextWitness(i) && !types.includes(i)) { types.push(i); } }); if (types.length > 0) { let obj = witness_objects.get(v.value); // 用户提供的witness地址 if (obj) { obj.types = array_unique(types.concat(obj.types)); obj.identifier.push(v.identifier); // identifier加入 } else { witness_objects.set(v.value, { types: types, identifier: [v.identifier] }); } } }); // 调用witness object的witness witness_objects.forEach((v, k) => { const r = query.witnessObjectInfo?.get(k); if (!r) { ERROR(Errors.Fail, `Passport: witness not found ${k}`); } switch (r?.module) { case MODULES.progress: Progress.witness(txb, k, guard_index, v.identifier, this.passport); break; case MODULES.order: Service.witness(txb, k, r.type, guard_index, v.identifier, v.types, this.passport); break; case MODULES.arb: Arbitration.witness(txb, k, r.type, guard_index, v.identifier, v.types, r.order, r.order_type, this.passport); break; default: ERROR(Errors.Fail, `Passport: witness type invalid ${r?.module}`); } }); }); const clock = this.txb.sharedObjectRef(Protocol.CLOCK_OBJECT); // rules: 'verify' & 'query' in turns; 'verify' at final end. query?.query.forEach((q) => { this.txb.moveCall({ target: Protocol.Instance().passportFn('passport_verify'), arguments: [this.passport, this.txb.object(clock)] }); this.txb.moveCall({ target: q.target, arguments: [this.txb.object(q.id), this.passport], typeArguments: q.types, }); }); this.txb.moveCall({ target: Protocol.Instance().passportFn('passport_verify'), arguments: [this.passport, this.txb.object(clock)] }); } destroy() { this.txb.moveCall({ target: Protocol.Instance().passportFn('destroy'), arguments: [this.passport] }); } freeze() { this.txb.moveCall({ target: Protocol.Instance().passportFn('freezen'), arguments: [this.passport] }); } query_result(sender, handleResult) { this.txb.moveCall({ target: Protocol.Instance().passportFn('query_result'), arguments: [this.passport] }); Protocol.Client().devInspectTransactionBlock({ sender: sender, transactionBlock: this.txb }).then((res) => { const r = Passport.ResolveQueryRes(this.txb, res); if (r) handleResult(r); }).catch(e => { console.log(e); }); } static ResolveQueryRes(txb, res) { for (let i = 0; i < res.results?.length; ++i) { const v = res.results[i]; if (v?.returnValues && v.returnValues.length === 2 && v.returnValues[0][1] === 'bool' && v.returnValues[1][1] === 'vector<address>') { // (bool, vector<address>) const result = bcs.bool().parse(Uint8Array.from(v.returnValues[0][0])); const guards = bcs.vector(bcs.Address).parse(Uint8Array.from(v.returnValues[1][0])).map((v) => '0x' + v); return { txb: txb, result: result, guards: guards }; } } return undefined; } } Passport.MAX_GUARD_COUNT = 8; //# sourceMappingURL=passport.js.map