SHA256
Переделать remote AddBlock на сборку блока на homeserver
This commit is contained in:
@@ -751,6 +751,16 @@ function buildBlockPreimage({ prevBlockHashHex, blockNumber, msgType, msgSubType
|
||||
);
|
||||
}
|
||||
|
||||
function buildRemoteBlockBodyBytes({ msgType, msgSubType, msgVersion = 1, bodyBytes }) {
|
||||
const body = bodyBytes || new Uint8Array(0);
|
||||
return concatBytes(
|
||||
int16Bytes(msgType),
|
||||
int16Bytes(msgSubType),
|
||||
int16Bytes(msgVersion),
|
||||
body,
|
||||
);
|
||||
}
|
||||
|
||||
export class AuthService {
|
||||
constructor(serverUrl) {
|
||||
this.serverUrl = normalizeServerUrl(serverUrl);
|
||||
@@ -1437,6 +1447,65 @@ export class AuthService {
|
||||
};
|
||||
}
|
||||
|
||||
async submitRemoteAddBlockBody({ login, storagePwd, blockchainName, blockBodyBytes }) {
|
||||
const cleanLogin = String(login || '').trim();
|
||||
const cleanBlockchainName = String(blockchainName || '').trim();
|
||||
if (!cleanLogin || !cleanBlockchainName) throw new Error('submitRemoteAddBlockBody: missing login/blockchainName');
|
||||
if (!(blockBodyBytes instanceof Uint8Array) || blockBodyBytes.length < 6) {
|
||||
throw new Error('submitRemoteAddBlockBody: bad blockBodyBytes');
|
||||
}
|
||||
|
||||
const remoteSessionId = String(this.remoteAddBlockSessionId || '').trim();
|
||||
if (!remoteSessionId) {
|
||||
throw new Error('На устройстве нет blockchain key и не выбрана homeserver-сессия для remote AddBlock');
|
||||
}
|
||||
|
||||
const signalRequestId = createSignalRequestId('remote-addblock');
|
||||
const responseWait = this.waitForSignal({
|
||||
signalType: SIGNAL_TYPE_REMOTE_ADDBLOCK_RESULT,
|
||||
signalRequestId,
|
||||
timeoutMs: 20000,
|
||||
});
|
||||
|
||||
const signalData = {
|
||||
operation: SIGNAL_TYPE_REMOTE_ADDBLOCK_REQUEST,
|
||||
signalRequestId,
|
||||
blockchainName: cleanBlockchainName,
|
||||
blockBodyB64: bytesToBase64(blockBodyBytes),
|
||||
};
|
||||
|
||||
await this.sendSignal({
|
||||
toLogin: cleanLogin,
|
||||
targetMode: SIGNAL_TARGET_SINGLE,
|
||||
targetSessionId: remoteSessionId,
|
||||
signalType: SIGNAL_TYPE_REMOTE_ADDBLOCK_REQUEST,
|
||||
signalRequestId,
|
||||
data: JSON.stringify(signalData),
|
||||
storagePwd,
|
||||
includeClientSignature: true,
|
||||
});
|
||||
|
||||
const signalPayload = await responseWait;
|
||||
let result = {};
|
||||
try {
|
||||
result = JSON.parse(String(signalPayload?.data || '{}'));
|
||||
} catch {
|
||||
throw new Error('Некорректный ответ remote AddBlock от homeserver');
|
||||
}
|
||||
if (!result?.ok) {
|
||||
throw new Error(String(result?.errorMessage || result?.error || 'remote_addblock_failed'));
|
||||
}
|
||||
|
||||
return {
|
||||
status: 200,
|
||||
payload: {
|
||||
serverLastGlobalNumber: Number(result?.serverLastGlobalNumber ?? -1),
|
||||
serverLastGlobalHash: String(result?.serverLastGlobalHash || ZERO_HASH_HEX),
|
||||
remote: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async runAddBlockWithRetry({ login, storagePwd, resolveFreshState, buildPreimage }) {
|
||||
let freshState = await resolveFreshState();
|
||||
let blockchainName = String(freshState?.blockchainName || '').trim();
|
||||
@@ -1484,6 +1553,21 @@ export class AuthService {
|
||||
if (!cleanLogin) throw new Error('Missing login for AddBlock');
|
||||
if (!storagePwd) throw new Error('Missing storagePwd for AddBlock signing');
|
||||
|
||||
const keyBundle = await loadEncryptedUserSecrets(cleanLogin, storagePwd);
|
||||
const blockchainPrivatePkcs8 = String(keyBundle?.blockchainKey || '').trim();
|
||||
if (!blockchainPrivatePkcs8) {
|
||||
const user = await this.getUser(cleanLogin);
|
||||
const blockchainName = String(user?.blockchainName || `${cleanLogin}-${BCH_SUFFIX}`).trim();
|
||||
if (!blockchainName) throw new Error('Не удалось определить blockchainName для remote AddBlock');
|
||||
const response = await this.submitRemoteAddBlockBody({
|
||||
login: cleanLogin,
|
||||
storagePwd,
|
||||
blockchainName,
|
||||
blockBodyBytes: buildRemoteBlockBodyBytes({ msgType, msgSubType, msgVersion, bodyBytes }),
|
||||
});
|
||||
return response.payload || {};
|
||||
}
|
||||
|
||||
const { response, blockchainName } = await this.runAddBlockWithRetry({
|
||||
login: cleanLogin,
|
||||
storagePwd,
|
||||
@@ -2458,33 +2542,22 @@ export class AuthService {
|
||||
if (!cleanLogin || !cleanParam) throw new Error('Не переданы login/param.');
|
||||
if (!cleanValue) throw new Error('Значение параметра не может быть пустым.');
|
||||
if (!storagePwd) throw new Error('Не передан storagePwd для подписи AddBlock.');
|
||||
const { response } = await this.runAddBlockWithRetry({
|
||||
const bodyBytes = makeUserParamBodyBytes({
|
||||
lineCode: 0,
|
||||
prevLineNumber: -1,
|
||||
prevLineHashHex: ZERO_HASH_HEX,
|
||||
thisLineNumber: -1,
|
||||
key: cleanParam,
|
||||
value: cleanValue,
|
||||
});
|
||||
return this.addBlockSigned({
|
||||
login: cleanLogin,
|
||||
storagePwd,
|
||||
resolveFreshState: () => this.resolveFreshBlockchainCursor(cleanLogin),
|
||||
buildPreimage: async ({ blockNumber, prevBlockHash }) => {
|
||||
const bodyBytes = makeUserParamBodyBytes({
|
||||
lineCode: 0,
|
||||
prevLineNumber: -1,
|
||||
prevLineHashHex: ZERO_HASH_HEX,
|
||||
thisLineNumber: -1,
|
||||
key: cleanParam,
|
||||
value: cleanValue,
|
||||
});
|
||||
return concatBytes(
|
||||
int16Bytes(0),
|
||||
hexToBytes(prevBlockHash),
|
||||
int32Bytes(2 + 32 + 4 + 4 + 8 + 2 + 2 + 2 + bodyBytes.length),
|
||||
int32Bytes(blockNumber),
|
||||
int64Bytes(Math.floor(Date.now() / 1000)),
|
||||
int16Bytes(4),
|
||||
int16Bytes(1),
|
||||
int16Bytes(1),
|
||||
bodyBytes,
|
||||
);
|
||||
},
|
||||
msgType: 4,
|
||||
msgSubType: 1,
|
||||
msgVersion: 1,
|
||||
bodyBytes,
|
||||
});
|
||||
return response.payload || {};
|
||||
}
|
||||
|
||||
async addBlockConnection({ login, toLogin, subType, storagePwd }) {
|
||||
@@ -2504,34 +2577,23 @@ export class AuthService {
|
||||
const targetUser = await this.getUser(cleanToLogin);
|
||||
if (!targetUser?.exists) throw new Error('Пользователь цели не найден.');
|
||||
const toBlockchainName = String(targetUser?.blockchainName || `${cleanToLogin}-${BCH_SUFFIX}`).trim();
|
||||
const { response } = await this.runAddBlockWithRetry({
|
||||
const bodyBytes = makeConnectionBodyBytes({
|
||||
lineCode: 0,
|
||||
prevLineNumber: -1,
|
||||
prevLineHashHex: ZERO_HASH_HEX,
|
||||
thisLineNumber: -1,
|
||||
toBlockchainName,
|
||||
toBlockNumber: 0,
|
||||
toBlockHashHex: ZERO_HASH_HEX,
|
||||
});
|
||||
return this.addBlockSigned({
|
||||
login: cleanLogin,
|
||||
storagePwd,
|
||||
resolveFreshState: () => this.resolveFreshBlockchainCursor(cleanLogin),
|
||||
buildPreimage: async ({ blockNumber, prevBlockHash }) => {
|
||||
const bodyBytes = makeConnectionBodyBytes({
|
||||
lineCode: 0,
|
||||
prevLineNumber: -1,
|
||||
prevLineHashHex: ZERO_HASH_HEX,
|
||||
thisLineNumber: -1,
|
||||
toBlockchainName,
|
||||
toBlockNumber: 0,
|
||||
toBlockHashHex: ZERO_HASH_HEX,
|
||||
});
|
||||
return concatBytes(
|
||||
int16Bytes(0),
|
||||
hexToBytes(prevBlockHash),
|
||||
int32Bytes(2 + 32 + 4 + 4 + 8 + 2 + 2 + 2 + bodyBytes.length),
|
||||
int32Bytes(blockNumber),
|
||||
int64Bytes(Math.floor(Date.now() / 1000)),
|
||||
int16Bytes(3),
|
||||
int16Bytes(cleanSubType),
|
||||
int16Bytes(1),
|
||||
bodyBytes,
|
||||
);
|
||||
},
|
||||
msgType: 3,
|
||||
msgSubType: cleanSubType,
|
||||
msgVersion: 1,
|
||||
bodyBytes,
|
||||
});
|
||||
return response.payload || {};
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user