Аввив 2.0 - работает, заливка!!

This commit is contained in:
AidarKC
2026-09-21 12:49:33 +03:00
parent 23969121e5
commit be696d116b
90 changed files with 2411 additions and 14938 deletions
+41 -22
View File
@@ -37,6 +37,7 @@ import {
saveEncryptedUserSecrets,
saveSessionMaterial,
} from './key-vault.js';
import { createAns104DataItem } from './ans104-data-item.js';
import { defaultServerWs } from '../deploy-config.js';
const BCH_SUFFIX = '001';
@@ -973,7 +974,7 @@ function buildBlockPreimage({ prevBlockHashHex, blockNumber, msgType, msgSubType
const blockSize = 2 + 32 + 4 + 4 + 8 + 2 + 2 + 2 + body.length;
return concatBytes(
int16Bytes(0),
int16Bytes(1),
prevHashBytes,
int32Bytes(blockSize),
int32Bytes(blockNumber),
@@ -1077,14 +1078,6 @@ export class AuthService {
return response.payload || {};
}
async getArchiveBlockchainLocation(blockchainName) {
const cleanBlockchainName = String(blockchainName || '').trim();
if (!cleanBlockchainName) throw new Error('Не указано имя блокчейна');
const response = await this.ws.request('GetArchiveBlockchainLocation', { blockchainName: cleanBlockchainName });
if (response.status !== 200) throw opError('GetArchiveBlockchainLocation', response);
return response.payload || response || {};
}
async resolveLoginForAuth(login) {
const cleanLogin = String(login || '').trim();
if (!cleanLogin) throw new Error('Введите логин');
@@ -1645,7 +1638,7 @@ export class AuthService {
};
}
async submitPreparedAddBlock({ login, storagePwd, blockchainName, blockNumber, prevBlockHash, preimage }) {
async submitPreparedAddBlock({ login, storagePwd, blockchainName, blockNumber, prevBlockHash, preimage, ansTags }) {
const cleanLogin = String(login || '').trim();
const cleanBlockchainName = String(blockchainName || '').trim();
const cleanPrevBlockHash = normalizeHex32(prevBlockHash, ZERO_HASH_HEX);
@@ -1658,17 +1651,22 @@ export class AuthService {
const blockchainPrivatePkcs8 = String(savedKeys?.blockchainKey || '').trim();
if (blockchainPrivatePkcs8) {
const privateKey = await importPkcs8Ed25519(blockchainPrivatePkcs8);
const hash32 = await sha256Bytes(preimage);
const signatureBytes = await signBytes(privateKey, hash32);
const fullBlock = concatBytes(preimage, int16Bytes(0x0100), signatureBytes);
const owner32 = base64ToBytes(await publicKeyB64FromPkcs8Ed25519(blockchainPrivatePkcs8));
const dataItemBytes = await createAns104DataItem({
owner32,
privateKey,
data: preimage,
tags: Array.isArray(ansTags) && ansTags.length ? ansTags : [{ name: 'App', value: 'test5590' }],
});
return this.ws.request('AddBlock', {
blockchainName: cleanBlockchainName,
blockNumber: Number(blockNumber),
prevBlockHash: cleanPrevBlockHash,
blockBytesB64: bytesToBase64(fullBlock),
blockBytesB64: bytesToBase64(dataItemBytes),
});
}
const remoteSessionId = String(this.remoteAddBlockSessionId || '').trim();
if (!remoteSessionId) {
throw new Error('На устройстве нет blockchain key и не выбрана homeserver-сессия для remote AddBlock');
@@ -1782,7 +1780,7 @@ export class AuthService {
};
}
async runAddBlockWithRetry({ login, storagePwd, resolveFreshState, buildPreimage }) {
async runAddBlockWithRetry({ login, storagePwd, resolveFreshState, buildPreimage, ansTags }) {
let freshState = await resolveFreshState();
let blockchainName = String(freshState?.blockchainName || '').trim();
if (!blockchainName) throw new Error('runAddBlockWithRetry: blockchainName is empty');
@@ -1798,6 +1796,7 @@ export class AuthService {
blockNumber,
prevBlockHash,
preimage,
ansTags,
});
};
@@ -1824,7 +1823,7 @@ export class AuthService {
};
}
async addBlockSigned({ login, storagePwd, msgType, msgSubType, msgVersion = 1, bodyBytes }) {
async addBlockSigned({ login, storagePwd, msgType, msgSubType, msgVersion = 1, bodyBytes, channelSlug = '' }) {
const cleanLogin = (login || '').trim();
if (!cleanLogin) throw new Error('Missing login for AddBlock');
if (!storagePwd) throw new Error('Missing storagePwd for AddBlock signing');
@@ -1844,10 +1843,15 @@ export class AuthService {
return response.payload || {};
}
const ansTags = [{ name: 'App', value: 'test5590' }];
const cleanChannelSlug = String(channelSlug || '').trim();
if (cleanChannelSlug) ansTags.push({ name: 'c', value: cleanChannelSlug });
const { response, blockchainName } = await this.runAddBlockWithRetry({
login: cleanLogin,
storagePwd,
resolveFreshState: () => this.resolveFreshBlockchainCursor(cleanLogin),
ansTags,
buildPreimage: async ({ blockNumber, prevBlockHash }) => buildBlockPreimage({
prevBlockHashHex: prevBlockHash,
blockNumber,
@@ -2039,12 +2043,14 @@ export class AuthService {
if (!owner || !Number.isFinite(root) || root < 0) throw new Error('Invalid channel selector');
if (owner !== blockchainName) throw new Error('Repost is allowed only to your own channels');
let channelSlug = toCanonicalChannelSlug(String(selector?.channelName || selector?.slug || ''));
let rootHashHex = normalizeHex32(selector?.channelRootBlockHash, ZERO64);
if (rootHashHex === ZERO64) {
if (rootHashHex === ZERO64 || !channelSlug) {
const ownChannels = await this.listOwnChannelsForBlockchain(cleanLogin, blockchainName);
const rootChannel = ownChannels.find((item) => item.rootBlockNumber === root);
if (!rootChannel) throw new Error('Channel root not found');
rootHashHex = normalizeHex32(rootChannel.rootBlockHash, ZERO64);
if (rootHashHex === ZERO64) rootHashHex = normalizeHex32(rootChannel.rootBlockHash, ZERO64);
if (!channelSlug) channelSlug = toCanonicalChannelSlug(rootChannel.channelName);
}
let prevLineNumber = root;
@@ -2089,6 +2095,7 @@ export class AuthService {
msgSubType: MSG_SUBTYPE_TEXT_REPOST,
msgVersion: 1,
bodyBytes,
channelSlug,
});
});
}
@@ -2115,11 +2122,15 @@ export class AuthService {
throw new Error('Invalid channel selector for edit');
}
let channelSlug = toCanonicalChannelSlug(String(selector?.channelName || selector?.slug || ''));
let rootHashHex = normalizeHex32(selector?.channelRootBlockHash, ZERO64);
if (rootHashHex === ZERO64) {
if (rootHashHex === ZERO64 || !channelSlug) {
const ownChannels = await this.listOwnChannelsForBlockchain(cleanLogin, ownerBlockchainName);
const rootChannel = ownChannels.find((item) => item.rootBlockNumber === lineCode);
if (rootChannel) rootHashHex = normalizeHex32(rootChannel.rootBlockHash, ZERO64);
if (rootChannel) {
if (rootHashHex === ZERO64) rootHashHex = normalizeHex32(rootChannel.rootBlockHash, ZERO64);
if (!channelSlug) channelSlug = toCanonicalChannelSlug(rootChannel.channelName);
}
}
let prevLineNumber = lineCode;
@@ -2165,6 +2176,7 @@ export class AuthService {
msgSubType: MSG_SUBTYPE_TEXT_EDIT_POST,
msgVersion: 1,
bodyBytes,
channelSlug,
});
}
@@ -2375,6 +2387,7 @@ export class AuthService {
msgType: MSG_TYPE_TECH,
msgSubType: MSG_SUBTYPE_TECH_CREATE_CHANNEL,
msgVersion: CREATE_CHANNEL_BODY_VERSION,
channelSlug,
bodyBytes: makeCreateChannelBodyBytes({
lineCode: 0,
prevLineNumber,
@@ -2413,13 +2426,16 @@ export class AuthService {
throw new Error('Posting is allowed only to your own channels');
}
let channelSlug = toCanonicalChannelSlug(String(selector?.channelName || selector?.slug || ''));
let rootHashHex = normalizeHex32(selector?.channelRootBlockHash, ZERO64);
if (rootHashHex === ZERO64) {
if (rootHashHex === ZERO64 || !channelSlug) {
const ownChannels = await this.listOwnChannelsForBlockchain(login, blockchainName);
const rootChannel = ownChannels.find((item) => item.rootBlockNumber === lineCode);
if (!rootChannel) throw new Error('Channel root not found');
rootHashHex = normalizeHex32(rootChannel.rootBlockHash, ZERO64);
if (rootHashHex === ZERO64) rootHashHex = normalizeHex32(rootChannel.rootBlockHash, ZERO64);
if (!channelSlug) channelSlug = toCanonicalChannelSlug(rootChannel.channelName);
}
if (!channelSlug) throw new Error('Cannot resolve canonical channel slug');
let prevLineNumber = lineCode;
let prevLineHashHex = rootHashHex;
@@ -2462,6 +2478,7 @@ export class AuthService {
prevLineNumber,
prevLineHashHex,
thisLineNumber,
channelSlug,
};
}
@@ -2506,6 +2523,7 @@ export class AuthService {
msgSubType: cleanSubType,
msgVersion: 1,
bodyBytes,
channelSlug: tail.channelSlug,
});
return {
@@ -2547,6 +2565,7 @@ export class AuthService {
msgSubType: MSG_SUBTYPE_TEXT_CHANNEL_META,
msgVersion: 1,
bodyBytes,
channelSlug: tail.channelSlug,
});
return {