From de19bd154fc960ecdcbcbaf76128c3188fb61fac Mon Sep 17 00:00:00 2001 From: Ashis Date: Wed, 23 Oct 2024 11:31:18 +0530 Subject: [PATCH 1/5] fix: updated proto file --- src/generated/block_pb.d.ts | 182 +++- src/generated/block_pb.js | 1831 +++++++++++++++++++++++++++-------- src/proto/block.proto | 59 +- 3 files changed, 1653 insertions(+), 419 deletions(-) diff --git a/src/generated/block_pb.d.ts b/src/generated/block_pb.d.ts index 53b902e..3377519 100644 --- a/src/generated/block_pb.d.ts +++ b/src/generated/block_pb.d.ts @@ -162,7 +162,7 @@ export namespace Block { } } -export class AttestorReply extends jspb.Message { +export class AttestBlockResult extends jspb.Message { clearAttestordataList(): void; getAttestordataList(): Array; setAttestordataList(value: Array): void; @@ -174,41 +174,115 @@ export class AttestorReply extends jspb.Message { setSigner(value?: Signer): void; serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): AttestorReply.AsObject; - static toObject(includeInstance: boolean, msg: AttestorReply): AttestorReply.AsObject; + toObject(includeInstance?: boolean): AttestBlockResult.AsObject; + static toObject(includeInstance: boolean, msg: AttestBlockResult): AttestBlockResult.AsObject; static extensions: {[key: number]: jspb.ExtensionFieldInfo}; static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: AttestorReply, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): AttestorReply; - static deserializeBinaryFromReader(message: AttestorReply, reader: jspb.BinaryReader): AttestorReply; + static serializeBinaryToWriter(message: AttestBlockResult, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): AttestBlockResult; + static deserializeBinaryFromReader(message: AttestBlockResult, reader: jspb.BinaryReader): AttestBlockResult; } -export namespace AttestorReply { +export namespace AttestBlockResult { export type AsObject = { attestordataList: Array, signer?: Signer.AsObject, } } -export class AttestorReplies extends jspb.Message { +export class AttestSignaturesRequest extends jspb.Message { clearAttestationsList(): void; - getAttestationsList(): Array; - setAttestationsList(value: Array): void; - addAttestations(value?: AttestorReply, index?: number): AttestorReply; + getAttestationsList(): Array; + setAttestationsList(value: Array): void; + addAttestations(value?: AttestBlockResult, index?: number): AttestBlockResult; + + getInitialblockhash(): Uint8Array | string; + getInitialblockhash_asU8(): Uint8Array; + getInitialblockhash_asB64(): string; + setInitialblockhash(value: Uint8Array | string): void; + + getFinalblockhash(): Uint8Array | string; + getFinalblockhash_asU8(): Uint8Array; + getFinalblockhash_asB64(): string; + setFinalblockhash(value: Uint8Array | string): void; serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): AttestorReplies.AsObject; - static toObject(includeInstance: boolean, msg: AttestorReplies): AttestorReplies.AsObject; + toObject(includeInstance?: boolean): AttestSignaturesRequest.AsObject; + static toObject(includeInstance: boolean, msg: AttestSignaturesRequest): AttestSignaturesRequest.AsObject; static extensions: {[key: number]: jspb.ExtensionFieldInfo}; static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: AttestorReplies, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): AttestorReplies; - static deserializeBinaryFromReader(message: AttestorReplies, reader: jspb.BinaryReader): AttestorReplies; + static serializeBinaryToWriter(message: AttestSignaturesRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): AttestSignaturesRequest; + static deserializeBinaryFromReader(message: AttestSignaturesRequest, reader: jspb.BinaryReader): AttestSignaturesRequest; } -export namespace AttestorReplies { +export namespace AttestSignaturesRequest { export type AsObject = { - attestationsList: Array, + attestationsList: Array, + initialblockhash: Uint8Array | string, + finalblockhash: Uint8Array | string, + } +} + +export class AttestSignaturesResponse extends jspb.Message { + clearAttestationsList(): void; + getAttestationsList(): Array; + setAttestationsList(value: Array): void; + addAttestations(value?: AttestorReport, index?: number): AttestorReport; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): AttestSignaturesResponse.AsObject; + static toObject(includeInstance: boolean, msg: AttestSignaturesResponse): AttestSignaturesResponse.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: AttestSignaturesResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): AttestSignaturesResponse; + static deserializeBinaryFromReader(message: AttestSignaturesResponse, reader: jspb.BinaryReader): AttestSignaturesResponse; +} + +export namespace AttestSignaturesResponse { + export type AsObject = { + attestationsList: Array, + } +} + +export class AttestorReport extends jspb.Message { + getNodeid(): string; + setNodeid(value: string): void; + + getTransactionhash(): string; + setTransactionhash(value: string): void; + + getVote(): number; + setVote(value: number): void; + + getDataforsc(): Uint8Array | string; + getDataforsc_asU8(): Uint8Array; + getDataforsc_asB64(): string; + setDataforsc(value: Uint8Array | string): void; + + getDatasigforsc(): Uint8Array | string; + getDatasigforsc_asU8(): Uint8Array; + getDatasigforsc_asB64(): string; + setDatasigforsc(value: Uint8Array | string): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): AttestorReport.AsObject; + static toObject(includeInstance: boolean, msg: AttestorReport): AttestorReport.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: AttestorReport, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): AttestorReport; + static deserializeBinaryFromReader(message: AttestorReport, reader: jspb.BinaryReader): AttestorReport; +} + +export namespace AttestorReport { + export type AsObject = { + nodeid: string, + transactionhash: string, + vote: number, + dataforsc: Uint8Array | string, + datasigforsc: Uint8Array | string, } } @@ -274,10 +348,71 @@ export namespace Transaction { } } -export class InitDid extends jspb.Message { - getDid(): string; - setDid(value: string): void; +export class EncryptedText extends jspb.Message { + getCiphertext(): string; + setCiphertext(value: string): void; + + getSalt(): string; + setSalt(value: string): void; + getNonce(): string; + setNonce(value: string): void; + + getVersion(): string; + setVersion(value: string): void; + + getPrekey(): string; + setPrekey(value: string): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): EncryptedText.AsObject; + static toObject(includeInstance: boolean, msg: EncryptedText): EncryptedText.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: EncryptedText, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): EncryptedText; + static deserializeBinaryFromReader(message: EncryptedText, reader: jspb.BinaryReader): EncryptedText; +} + +export namespace EncryptedText { + export type AsObject = { + ciphertext: string, + salt: string, + nonce: string, + version: string, + prekey: string, + } +} + +export class WalletToEncDerivedKey extends jspb.Message { + hasEncderivedprivkey(): boolean; + clearEncderivedprivkey(): void; + getEncderivedprivkey(): EncryptedText | undefined; + setEncderivedprivkey(value?: EncryptedText): void; + + getSignature(): Uint8Array | string; + getSignature_asU8(): Uint8Array; + getSignature_asB64(): string; + setSignature(value: Uint8Array | string): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): WalletToEncDerivedKey.AsObject; + static toObject(includeInstance: boolean, msg: WalletToEncDerivedKey): WalletToEncDerivedKey.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: WalletToEncDerivedKey, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): WalletToEncDerivedKey; + static deserializeBinaryFromReader(message: WalletToEncDerivedKey, reader: jspb.BinaryReader): WalletToEncDerivedKey; +} + +export namespace WalletToEncDerivedKey { + export type AsObject = { + encderivedprivkey?: EncryptedText.AsObject, + signature: Uint8Array | string, + } +} + +export class InitDid extends jspb.Message { getMasterpubkey(): string; setMasterpubkey(value: string): void; @@ -287,7 +422,7 @@ export class InitDid extends jspb.Message { getDerivedpubkey(): string; setDerivedpubkey(value: string): void; - getWallettoencderivedkeyMap(): jspb.Map; + getWallettoencderivedkeyMap(): jspb.Map; clearWallettoencderivedkeyMap(): void; serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): InitDid.AsObject; @@ -301,11 +436,10 @@ export class InitDid extends jspb.Message { export namespace InitDid { export type AsObject = { - did: string, masterpubkey: string, derivedkeyindex: number, derivedpubkey: string, - wallettoencderivedkeyMap: Array<[string, string]>, + wallettoencderivedkeyMap: Array<[string, WalletToEncDerivedKey.AsObject]>, } } diff --git a/src/generated/block_pb.js b/src/generated/block_pb.js index cd4e885..f1be65d 100644 --- a/src/generated/block_pb.js +++ b/src/generated/block_pb.js @@ -13,21 +13,18 @@ var jspb = require('google-protobuf'); var goog = jspb; -var global = - (typeof globalThis !== 'undefined' && globalThis) || - (typeof window !== 'undefined' && window) || - (typeof global !== 'undefined' && global) || - (typeof self !== 'undefined' && self) || - (function () { return this; }).call(null) || - Function('return this')(); +var global = (function() { return this || window || global || self || Function('return this')(); }).call(null); goog.exportSymbol('proto.push.Attachment', null, global); -goog.exportSymbol('proto.push.AttestorReplies', null, global); -goog.exportSymbol('proto.push.AttestorReply', null, global); +goog.exportSymbol('proto.push.AttestBlockResult', null, global); +goog.exportSymbol('proto.push.AttestSignaturesRequest', null, global); +goog.exportSymbol('proto.push.AttestSignaturesResponse', null, global); +goog.exportSymbol('proto.push.AttestorReport', null, global); goog.exportSymbol('proto.push.Block', null, global); goog.exportSymbol('proto.push.DidMapping', null, global); goog.exportSymbol('proto.push.Email', null, global); goog.exportSymbol('proto.push.EncryptedNotif', null, global); +goog.exportSymbol('proto.push.EncryptedText', null, global); goog.exportSymbol('proto.push.EncryptionDetails', null, global); goog.exportSymbol('proto.push.EncryptionType', null, global); goog.exportSymbol('proto.push.InitDid', null, global); @@ -41,6 +38,7 @@ goog.exportSymbol('proto.push.TransactionObj', null, global); goog.exportSymbol('proto.push.TxAttestorData', null, global); goog.exportSymbol('proto.push.TxValidatorData', null, global); goog.exportSymbol('proto.push.Vote', null, global); +goog.exportSymbol('proto.push.WalletToEncDerivedKey', null, global); /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -177,16 +175,16 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.push.AttestorReply = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.push.AttestorReply.repeatedFields_, null); +proto.push.AttestBlockResult = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.push.AttestBlockResult.repeatedFields_, null); }; -goog.inherits(proto.push.AttestorReply, jspb.Message); +goog.inherits(proto.push.AttestBlockResult, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.push.AttestorReply.displayName = 'proto.push.AttestorReply'; + proto.push.AttestBlockResult.displayName = 'proto.push.AttestBlockResult'; } /** * Generated by JsPbCodeGenerator. @@ -198,16 +196,58 @@ if (goog.DEBUG && !COMPILED) { * @extends {jspb.Message} * @constructor */ -proto.push.AttestorReplies = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, proto.push.AttestorReplies.repeatedFields_, null); +proto.push.AttestSignaturesRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.push.AttestSignaturesRequest.repeatedFields_, null); }; -goog.inherits(proto.push.AttestorReplies, jspb.Message); +goog.inherits(proto.push.AttestSignaturesRequest, jspb.Message); if (goog.DEBUG && !COMPILED) { /** * @public * @override */ - proto.push.AttestorReplies.displayName = 'proto.push.AttestorReplies'; + proto.push.AttestSignaturesRequest.displayName = 'proto.push.AttestSignaturesRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.push.AttestSignaturesResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.push.AttestSignaturesResponse.repeatedFields_, null); +}; +goog.inherits(proto.push.AttestSignaturesResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.push.AttestSignaturesResponse.displayName = 'proto.push.AttestSignaturesResponse'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.push.AttestorReport = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.push.AttestorReport, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.push.AttestorReport.displayName = 'proto.push.AttestorReport'; } /** * Generated by JsPbCodeGenerator. @@ -230,6 +270,48 @@ if (goog.DEBUG && !COMPILED) { */ proto.push.Transaction.displayName = 'proto.push.Transaction'; } +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.push.EncryptedText = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.push.EncryptedText, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.push.EncryptedText.displayName = 'proto.push.EncryptedText'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.push.WalletToEncDerivedKey = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.push.WalletToEncDerivedKey, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.push.WalletToEncDerivedKey.displayName = 'proto.push.WalletToEncDerivedKey'; +} /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -507,8 +589,7 @@ proto.push.DidMapping.prototype.getDidmappingMap = function(opt_noLazyCreate) { */ proto.push.DidMapping.prototype.clearDidmappingMap = function() { this.getDidmappingMap().clear(); - return this; -}; + return this;}; @@ -1541,7 +1622,7 @@ proto.push.Block.prototype.clearSignersList = function() { * @private {!Array} * @const */ -proto.push.AttestorReply.repeatedFields_ = [1]; +proto.push.AttestBlockResult.repeatedFields_ = [1]; @@ -1558,8 +1639,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.push.AttestorReply.prototype.toObject = function(opt_includeInstance) { - return proto.push.AttestorReply.toObject(opt_includeInstance, this); +proto.push.AttestBlockResult.prototype.toObject = function(opt_includeInstance) { + return proto.push.AttestBlockResult.toObject(opt_includeInstance, this); }; @@ -1568,11 +1649,11 @@ proto.push.AttestorReply.prototype.toObject = function(opt_includeInstance) { * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.push.AttestorReply} msg The msg instance to transform. + * @param {!proto.push.AttestBlockResult} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.push.AttestorReply.toObject = function(includeInstance, msg) { +proto.push.AttestBlockResult.toObject = function(includeInstance, msg) { var f, obj = { attestordataList: jspb.Message.toObjectList(msg.getAttestordataList(), proto.push.TxAttestorData.toObject, includeInstance), @@ -1590,23 +1671,23 @@ proto.push.AttestorReply.toObject = function(includeInstance, msg) { /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.push.AttestorReply} + * @return {!proto.push.AttestBlockResult} */ -proto.push.AttestorReply.deserializeBinary = function(bytes) { +proto.push.AttestBlockResult.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.push.AttestorReply; - return proto.push.AttestorReply.deserializeBinaryFromReader(msg, reader); + var msg = new proto.push.AttestBlockResult; + return proto.push.AttestBlockResult.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.push.AttestorReply} msg The message object to deserialize into. + * @param {!proto.push.AttestBlockResult} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.push.AttestorReply} + * @return {!proto.push.AttestBlockResult} */ -proto.push.AttestorReply.deserializeBinaryFromReader = function(msg, reader) { +proto.push.AttestBlockResult.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -1636,9 +1717,9 @@ proto.push.AttestorReply.deserializeBinaryFromReader = function(msg, reader) { * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.push.AttestorReply.prototype.serializeBinary = function() { +proto.push.AttestBlockResult.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.push.AttestorReply.serializeBinaryToWriter(this, writer); + proto.push.AttestBlockResult.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -1646,11 +1727,11 @@ proto.push.AttestorReply.prototype.serializeBinary = function() { /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.push.AttestorReply} message + * @param {!proto.push.AttestBlockResult} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.push.AttestorReply.serializeBinaryToWriter = function(message, writer) { +proto.push.AttestBlockResult.serializeBinaryToWriter = function(message, writer) { var f = undefined; f = message.getAttestordataList(); if (f.length > 0) { @@ -1675,7 +1756,7 @@ proto.push.AttestorReply.serializeBinaryToWriter = function(message, writer) { * repeated TxAttestorData attestorData = 1; * @return {!Array} */ -proto.push.AttestorReply.prototype.getAttestordataList = function() { +proto.push.AttestBlockResult.prototype.getAttestordataList = function() { return /** @type{!Array} */ ( jspb.Message.getRepeatedWrapperField(this, proto.push.TxAttestorData, 1)); }; @@ -1683,9 +1764,9 @@ proto.push.AttestorReply.prototype.getAttestordataList = function() { /** * @param {!Array} value - * @return {!proto.push.AttestorReply} returns this + * @return {!proto.push.AttestBlockResult} returns this */ -proto.push.AttestorReply.prototype.setAttestordataList = function(value) { +proto.push.AttestBlockResult.prototype.setAttestordataList = function(value) { return jspb.Message.setRepeatedWrapperField(this, 1, value); }; @@ -1695,16 +1776,16 @@ proto.push.AttestorReply.prototype.setAttestordataList = function(value) { * @param {number=} opt_index * @return {!proto.push.TxAttestorData} */ -proto.push.AttestorReply.prototype.addAttestordata = function(opt_value, opt_index) { +proto.push.AttestBlockResult.prototype.addAttestordata = function(opt_value, opt_index) { return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.push.TxAttestorData, opt_index); }; /** * Clears the list making it empty but non-null. - * @return {!proto.push.AttestorReply} returns this + * @return {!proto.push.AttestBlockResult} returns this */ -proto.push.AttestorReply.prototype.clearAttestordataList = function() { +proto.push.AttestBlockResult.prototype.clearAttestordataList = function() { return this.setAttestordataList([]); }; @@ -1713,7 +1794,7 @@ proto.push.AttestorReply.prototype.clearAttestordataList = function() { * optional Signer signer = 2; * @return {?proto.push.Signer} */ -proto.push.AttestorReply.prototype.getSigner = function() { +proto.push.AttestBlockResult.prototype.getSigner = function() { return /** @type{?proto.push.Signer} */ ( jspb.Message.getWrapperField(this, proto.push.Signer, 2)); }; @@ -1721,18 +1802,18 @@ proto.push.AttestorReply.prototype.getSigner = function() { /** * @param {?proto.push.Signer|undefined} value - * @return {!proto.push.AttestorReply} returns this + * @return {!proto.push.AttestBlockResult} returns this */ -proto.push.AttestorReply.prototype.setSigner = function(value) { +proto.push.AttestBlockResult.prototype.setSigner = function(value) { return jspb.Message.setWrapperField(this, 2, value); }; /** * Clears the message field making it undefined. - * @return {!proto.push.AttestorReply} returns this + * @return {!proto.push.AttestBlockResult} returns this */ -proto.push.AttestorReply.prototype.clearSigner = function() { +proto.push.AttestBlockResult.prototype.clearSigner = function() { return this.setSigner(undefined); }; @@ -1741,7 +1822,7 @@ proto.push.AttestorReply.prototype.clearSigner = function() { * Returns whether this field is set. * @return {boolean} */ -proto.push.AttestorReply.prototype.hasSigner = function() { +proto.push.AttestBlockResult.prototype.hasSigner = function() { return jspb.Message.getField(this, 2) != null; }; @@ -1752,7 +1833,7 @@ proto.push.AttestorReply.prototype.hasSigner = function() { * @private {!Array} * @const */ -proto.push.AttestorReplies.repeatedFields_ = [1]; +proto.push.AttestSignaturesRequest.repeatedFields_ = [1]; @@ -1769,8 +1850,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.push.AttestorReplies.prototype.toObject = function(opt_includeInstance) { - return proto.push.AttestorReplies.toObject(opt_includeInstance, this); +proto.push.AttestSignaturesRequest.prototype.toObject = function(opt_includeInstance) { + return proto.push.AttestSignaturesRequest.toObject(opt_includeInstance, this); }; @@ -1779,14 +1860,16 @@ proto.push.AttestorReplies.prototype.toObject = function(opt_includeInstance) { * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.push.AttestorReplies} msg The msg instance to transform. + * @param {!proto.push.AttestSignaturesRequest} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.push.AttestorReplies.toObject = function(includeInstance, msg) { +proto.push.AttestSignaturesRequest.toObject = function(includeInstance, msg) { var f, obj = { attestationsList: jspb.Message.toObjectList(msg.getAttestationsList(), - proto.push.AttestorReply.toObject, includeInstance) + proto.push.AttestBlockResult.toObject, includeInstance), + initialblockhash: msg.getInitialblockhash_asB64(), + finalblockhash: msg.getFinalblockhash_asB64() }; if (includeInstance) { @@ -1800,23 +1883,23 @@ proto.push.AttestorReplies.toObject = function(includeInstance, msg) { /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.push.AttestorReplies} + * @return {!proto.push.AttestSignaturesRequest} */ -proto.push.AttestorReplies.deserializeBinary = function(bytes) { +proto.push.AttestSignaturesRequest.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.push.AttestorReplies; - return proto.push.AttestorReplies.deserializeBinaryFromReader(msg, reader); + var msg = new proto.push.AttestSignaturesRequest; + return proto.push.AttestSignaturesRequest.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.push.AttestorReplies} msg The message object to deserialize into. + * @param {!proto.push.AttestSignaturesRequest} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.push.AttestorReplies} + * @return {!proto.push.AttestSignaturesRequest} */ -proto.push.AttestorReplies.deserializeBinaryFromReader = function(msg, reader) { +proto.push.AttestSignaturesRequest.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -1824,10 +1907,18 @@ proto.push.AttestorReplies.deserializeBinaryFromReader = function(msg, reader) { var field = reader.getFieldNumber(); switch (field) { case 1: - var value = new proto.push.AttestorReply; - reader.readMessage(value,proto.push.AttestorReply.deserializeBinaryFromReader); + var value = new proto.push.AttestBlockResult; + reader.readMessage(value,proto.push.AttestBlockResult.deserializeBinaryFromReader); msg.addAttestations(value); break; + case 2: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setInitialblockhash(value); + break; + case 3: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setFinalblockhash(value); + break; default: reader.skipField(); break; @@ -1841,9 +1932,9 @@ proto.push.AttestorReplies.deserializeBinaryFromReader = function(msg, reader) { * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.push.AttestorReplies.prototype.serializeBinary = function() { +proto.push.AttestSignaturesRequest.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.push.AttestorReplies.serializeBinaryToWriter(this, writer); + proto.push.AttestSignaturesRequest.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -1851,68 +1942,166 @@ proto.push.AttestorReplies.prototype.serializeBinary = function() { /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.push.AttestorReplies} message + * @param {!proto.push.AttestSignaturesRequest} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.push.AttestorReplies.serializeBinaryToWriter = function(message, writer) { +proto.push.AttestSignaturesRequest.serializeBinaryToWriter = function(message, writer) { var f = undefined; f = message.getAttestationsList(); if (f.length > 0) { writer.writeRepeatedMessage( 1, f, - proto.push.AttestorReply.serializeBinaryToWriter + proto.push.AttestBlockResult.serializeBinaryToWriter + ); + } + f = message.getInitialblockhash_asU8(); + if (f.length > 0) { + writer.writeBytes( + 2, + f + ); + } + f = message.getFinalblockhash_asU8(); + if (f.length > 0) { + writer.writeBytes( + 3, + f ); } }; /** - * repeated AttestorReply attestations = 1; - * @return {!Array} + * repeated AttestBlockResult attestations = 1; + * @return {!Array} */ -proto.push.AttestorReplies.prototype.getAttestationsList = function() { - return /** @type{!Array} */ ( - jspb.Message.getRepeatedWrapperField(this, proto.push.AttestorReply, 1)); +proto.push.AttestSignaturesRequest.prototype.getAttestationsList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.push.AttestBlockResult, 1)); }; /** - * @param {!Array} value - * @return {!proto.push.AttestorReplies} returns this + * @param {!Array} value + * @return {!proto.push.AttestSignaturesRequest} returns this */ -proto.push.AttestorReplies.prototype.setAttestationsList = function(value) { +proto.push.AttestSignaturesRequest.prototype.setAttestationsList = function(value) { return jspb.Message.setRepeatedWrapperField(this, 1, value); }; /** - * @param {!proto.push.AttestorReply=} opt_value + * @param {!proto.push.AttestBlockResult=} opt_value * @param {number=} opt_index - * @return {!proto.push.AttestorReply} + * @return {!proto.push.AttestBlockResult} */ -proto.push.AttestorReplies.prototype.addAttestations = function(opt_value, opt_index) { - return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.push.AttestorReply, opt_index); +proto.push.AttestSignaturesRequest.prototype.addAttestations = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.push.AttestBlockResult, opt_index); }; /** * Clears the list making it empty but non-null. - * @return {!proto.push.AttestorReplies} returns this + * @return {!proto.push.AttestSignaturesRequest} returns this */ -proto.push.AttestorReplies.prototype.clearAttestationsList = function() { +proto.push.AttestSignaturesRequest.prototype.clearAttestationsList = function() { return this.setAttestationsList([]); }; +/** + * optional bytes initialBlockHash = 2; + * @return {!(string|Uint8Array)} + */ +proto.push.AttestSignaturesRequest.prototype.getInitialblockhash = function() { + return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * optional bytes initialBlockHash = 2; + * This is a type-conversion wrapper around `getInitialblockhash()` + * @return {string} + */ +proto.push.AttestSignaturesRequest.prototype.getInitialblockhash_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getInitialblockhash())); +}; + + +/** + * optional bytes initialBlockHash = 2; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getInitialblockhash()` + * @return {!Uint8Array} + */ +proto.push.AttestSignaturesRequest.prototype.getInitialblockhash_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getInitialblockhash())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.push.AttestSignaturesRequest} returns this + */ +proto.push.AttestSignaturesRequest.prototype.setInitialblockhash = function(value) { + return jspb.Message.setProto3BytesField(this, 2, value); +}; + + +/** + * optional bytes finalBlockHash = 3; + * @return {!(string|Uint8Array)} + */ +proto.push.AttestSignaturesRequest.prototype.getFinalblockhash = function() { + return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * optional bytes finalBlockHash = 3; + * This is a type-conversion wrapper around `getFinalblockhash()` + * @return {string} + */ +proto.push.AttestSignaturesRequest.prototype.getFinalblockhash_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getFinalblockhash())); +}; + + +/** + * optional bytes finalBlockHash = 3; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getFinalblockhash()` + * @return {!Uint8Array} + */ +proto.push.AttestSignaturesRequest.prototype.getFinalblockhash_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getFinalblockhash())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.push.AttestSignaturesRequest} returns this + */ +proto.push.AttestSignaturesRequest.prototype.setFinalblockhash = function(value) { + return jspb.Message.setProto3BytesField(this, 3, value); +}; + + /** * List of repeated fields within this message type. * @private {!Array} * @const */ -proto.push.Transaction.repeatedFields_ = [4]; +proto.push.AttestSignaturesResponse.repeatedFields_ = [1]; @@ -1929,8 +2118,8 @@ if (jspb.Message.GENERATE_TO_OBJECT) { * http://goto/soy-param-migration * @return {!Object} */ -proto.push.Transaction.prototype.toObject = function(opt_includeInstance) { - return proto.push.Transaction.toObject(opt_includeInstance, this); +proto.push.AttestSignaturesResponse.prototype.toObject = function(opt_includeInstance) { + return proto.push.AttestSignaturesResponse.toObject(opt_includeInstance, this); }; @@ -1939,21 +2128,14 @@ proto.push.Transaction.prototype.toObject = function(opt_includeInstance) { * @param {boolean|undefined} includeInstance Deprecated. Whether to include * the JSPB instance for transitional soy proto support: * http://goto/soy-param-migration - * @param {!proto.push.Transaction} msg The msg instance to transform. + * @param {!proto.push.AttestSignaturesResponse} msg The msg instance to transform. * @return {!Object} * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.push.Transaction.toObject = function(includeInstance, msg) { +proto.push.AttestSignaturesResponse.toObject = function(includeInstance, msg) { var f, obj = { - type: jspb.Message.getFieldWithDefault(msg, 1, 0), - category: jspb.Message.getFieldWithDefault(msg, 2, ""), - sender: jspb.Message.getFieldWithDefault(msg, 3, ""), - recipientsList: (f = jspb.Message.getRepeatedField(msg, 4)) == null ? undefined : f, - data: msg.getData_asB64(), - salt: msg.getSalt_asB64(), - apitoken: msg.getApitoken_asB64(), - signature: msg.getSignature_asB64(), - fee: jspb.Message.getFieldWithDefault(msg, 9, "") + attestationsList: jspb.Message.toObjectList(msg.getAttestationsList(), + proto.push.AttestorReport.toObject, includeInstance) }; if (includeInstance) { @@ -1967,23 +2149,23 @@ proto.push.Transaction.toObject = function(includeInstance, msg) { /** * Deserializes binary data (in protobuf wire format). * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.push.Transaction} + * @return {!proto.push.AttestSignaturesResponse} */ -proto.push.Transaction.deserializeBinary = function(bytes) { +proto.push.AttestSignaturesResponse.deserializeBinary = function(bytes) { var reader = new jspb.BinaryReader(bytes); - var msg = new proto.push.Transaction; - return proto.push.Transaction.deserializeBinaryFromReader(msg, reader); + var msg = new proto.push.AttestSignaturesResponse; + return proto.push.AttestSignaturesResponse.deserializeBinaryFromReader(msg, reader); }; /** * Deserializes binary data (in protobuf wire format) from the * given reader into the given message object. - * @param {!proto.push.Transaction} msg The message object to deserialize into. + * @param {!proto.push.AttestSignaturesResponse} msg The message object to deserialize into. * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.push.Transaction} + * @return {!proto.push.AttestSignaturesResponse} */ -proto.push.Transaction.deserializeBinaryFromReader = function(msg, reader) { +proto.push.AttestSignaturesResponse.deserializeBinaryFromReader = function(msg, reader) { while (reader.nextField()) { if (reader.isEndGroup()) { break; @@ -1991,40 +2173,9 @@ proto.push.Transaction.deserializeBinaryFromReader = function(msg, reader) { var field = reader.getFieldNumber(); switch (field) { case 1: - var value = /** @type {number} */ (reader.readUint32()); - msg.setType(value); - break; - case 2: - var value = /** @type {string} */ (reader.readString()); - msg.setCategory(value); - break; - case 3: - var value = /** @type {string} */ (reader.readString()); - msg.setSender(value); - break; - case 4: - var value = /** @type {string} */ (reader.readString()); - msg.addRecipients(value); - break; - case 5: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setData(value); - break; - case 6: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setSalt(value); - break; - case 7: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setApitoken(value); - break; - case 8: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setSignature(value); - break; - case 9: - var value = /** @type {string} */ (reader.readString()); - msg.setFee(value); + var value = new proto.push.AttestorReport; + reader.readMessage(value,proto.push.AttestorReport.deserializeBinaryFromReader); + msg.addAttestations(value); break; default: reader.skipField(); @@ -2039,9 +2190,9 @@ proto.push.Transaction.deserializeBinaryFromReader = function(msg, reader) { * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.push.Transaction.prototype.serializeBinary = function() { +proto.push.AttestSignaturesResponse.prototype.serializeBinary = function() { var writer = new jspb.BinaryWriter(); - proto.push.Transaction.serializeBinaryToWriter(this, writer); + proto.push.AttestSignaturesResponse.serializeBinaryToWriter(this, writer); return writer.getResultBuffer(); }; @@ -2049,72 +2200,215 @@ proto.push.Transaction.prototype.serializeBinary = function() { /** * Serializes the given message to binary data (in protobuf wire * format), writing to the given BinaryWriter. - * @param {!proto.push.Transaction} message + * @param {!proto.push.AttestSignaturesResponse} message * @param {!jspb.BinaryWriter} writer * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.push.Transaction.serializeBinaryToWriter = function(message, writer) { +proto.push.AttestSignaturesResponse.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getType(); - if (f !== 0) { - writer.writeUint32( - 1, - f - ); - } - f = message.getCategory(); - if (f.length > 0) { - writer.writeString( - 2, - f - ); - } - f = message.getSender(); - if (f.length > 0) { - writer.writeString( - 3, - f - ); - } - f = message.getRecipientsList(); - if (f.length > 0) { - writer.writeRepeatedString( - 4, - f - ); - } - f = message.getData_asU8(); - if (f.length > 0) { - writer.writeBytes( - 5, - f - ); - } - f = message.getSalt_asU8(); + f = message.getAttestationsList(); if (f.length > 0) { - writer.writeBytes( - 6, - f + writer.writeRepeatedMessage( + 1, + f, + proto.push.AttestorReport.serializeBinaryToWriter ); } - f = message.getApitoken_asU8(); - if (f.length > 0) { - writer.writeBytes( - 7, - f - ); +}; + + +/** + * repeated AttestorReport attestations = 1; + * @return {!Array} + */ +proto.push.AttestSignaturesResponse.prototype.getAttestationsList = function() { + return /** @type{!Array} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.push.AttestorReport, 1)); +}; + + +/** + * @param {!Array} value + * @return {!proto.push.AttestSignaturesResponse} returns this +*/ +proto.push.AttestSignaturesResponse.prototype.setAttestationsList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 1, value); +}; + + +/** + * @param {!proto.push.AttestorReport=} opt_value + * @param {number=} opt_index + * @return {!proto.push.AttestorReport} + */ +proto.push.AttestSignaturesResponse.prototype.addAttestations = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.push.AttestorReport, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.push.AttestSignaturesResponse} returns this + */ +proto.push.AttestSignaturesResponse.prototype.clearAttestationsList = function() { + return this.setAttestationsList([]); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.push.AttestorReport.prototype.toObject = function(opt_includeInstance) { + return proto.push.AttestorReport.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.push.AttestorReport} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.push.AttestorReport.toObject = function(includeInstance, msg) { + var f, obj = { + nodeid: jspb.Message.getFieldWithDefault(msg, 1, ""), + transactionhash: jspb.Message.getFieldWithDefault(msg, 2, ""), + vote: jspb.Message.getFieldWithDefault(msg, 3, 0), + dataforsc: msg.getDataforsc_asB64(), + datasigforsc: msg.getDatasigforsc_asB64() + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; } - f = message.getSignature_asU8(); + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.push.AttestorReport} + */ +proto.push.AttestorReport.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.push.AttestorReport; + return proto.push.AttestorReport.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.push.AttestorReport} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.push.AttestorReport} + */ +proto.push.AttestorReport.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setNodeid(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setTransactionhash(value); + break; + case 3: + var value = /** @type {number} */ (reader.readInt32()); + msg.setVote(value); + break; + case 4: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setDataforsc(value); + break; + case 5: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setDatasigforsc(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.push.AttestorReport.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.push.AttestorReport.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.push.AttestorReport} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.push.AttestorReport.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getNodeid(); if (f.length > 0) { - writer.writeBytes( - 8, + writer.writeString( + 1, f ); } - f = message.getFee(); + f = message.getTransactionhash(); if (f.length > 0) { writer.writeString( - 9, + 2, + f + ); + } + f = message.getVote(); + if (f !== 0) { + writer.writeInt32( + 3, + f + ); + } + f = message.getDataforsc_asU8(); + if (f.length > 0) { + writer.writeBytes( + 4, + f + ); + } + f = message.getDatasigforsc_asU8(); + if (f.length > 0) { + writer.writeBytes( + 5, f ); } @@ -2122,250 +2416,1076 @@ proto.push.Transaction.serializeBinaryToWriter = function(message, writer) { /** - * optional uint32 type = 1; - * @return {number} + * optional string nodeId = 1; + * @return {string} */ -proto.push.Transaction.prototype.getType = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); +proto.push.AttestorReport.prototype.getNodeid = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; /** - * @param {number} value - * @return {!proto.push.Transaction} returns this + * @param {string} value + * @return {!proto.push.AttestorReport} returns this */ -proto.push.Transaction.prototype.setType = function(value) { - return jspb.Message.setProto3IntField(this, 1, value); +proto.push.AttestorReport.prototype.setNodeid = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); }; /** - * optional string category = 2; + * optional string transactionHash = 2; * @return {string} */ -proto.push.Transaction.prototype.getCategory = function() { +proto.push.AttestorReport.prototype.getTransactionhash = function() { return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); }; /** * @param {string} value - * @return {!proto.push.Transaction} returns this + * @return {!proto.push.AttestorReport} returns this */ -proto.push.Transaction.prototype.setCategory = function(value) { +proto.push.AttestorReport.prototype.setTransactionhash = function(value) { return jspb.Message.setProto3StringField(this, 2, value); }; /** - * optional string sender = 3; + * optional int32 vote = 3; + * @return {number} + */ +proto.push.AttestorReport.prototype.getVote = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.push.AttestorReport} returns this + */ +proto.push.AttestorReport.prototype.setVote = function(value) { + return jspb.Message.setProto3IntField(this, 3, value); +}; + + +/** + * optional bytes dataForSc = 4; + * @return {!(string|Uint8Array)} + */ +proto.push.AttestorReport.prototype.getDataforsc = function() { + return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +}; + + +/** + * optional bytes dataForSc = 4; + * This is a type-conversion wrapper around `getDataforsc()` * @return {string} */ -proto.push.Transaction.prototype.getSender = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +proto.push.AttestorReport.prototype.getDataforsc_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getDataforsc())); +}; + + +/** + * optional bytes dataForSc = 4; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getDataforsc()` + * @return {!Uint8Array} + */ +proto.push.AttestorReport.prototype.getDataforsc_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getDataforsc())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.push.AttestorReport} returns this + */ +proto.push.AttestorReport.prototype.setDataforsc = function(value) { + return jspb.Message.setProto3BytesField(this, 4, value); +}; + + +/** + * optional bytes dataSigForSc = 5; + * @return {!(string|Uint8Array)} + */ +proto.push.AttestorReport.prototype.getDatasigforsc = function() { + return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 5, "")); +}; + + +/** + * optional bytes dataSigForSc = 5; + * This is a type-conversion wrapper around `getDatasigforsc()` + * @return {string} + */ +proto.push.AttestorReport.prototype.getDatasigforsc_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getDatasigforsc())); +}; + + +/** + * optional bytes dataSigForSc = 5; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getDatasigforsc()` + * @return {!Uint8Array} + */ +proto.push.AttestorReport.prototype.getDatasigforsc_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getDatasigforsc())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.push.AttestorReport} returns this + */ +proto.push.AttestorReport.prototype.setDatasigforsc = function(value) { + return jspb.Message.setProto3BytesField(this, 5, value); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array} + * @const + */ +proto.push.Transaction.repeatedFields_ = [4]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.push.Transaction.prototype.toObject = function(opt_includeInstance) { + return proto.push.Transaction.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.push.Transaction} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.push.Transaction.toObject = function(includeInstance, msg) { + var f, obj = { + type: jspb.Message.getFieldWithDefault(msg, 1, 0), + category: jspb.Message.getFieldWithDefault(msg, 2, ""), + sender: jspb.Message.getFieldWithDefault(msg, 3, ""), + recipientsList: (f = jspb.Message.getRepeatedField(msg, 4)) == null ? undefined : f, + data: msg.getData_asB64(), + salt: msg.getSalt_asB64(), + apitoken: msg.getApitoken_asB64(), + signature: msg.getSignature_asB64(), + fee: jspb.Message.getFieldWithDefault(msg, 9, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.push.Transaction} + */ +proto.push.Transaction.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.push.Transaction; + return proto.push.Transaction.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.push.Transaction} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.push.Transaction} + */ +proto.push.Transaction.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {number} */ (reader.readUint32()); + msg.setType(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setCategory(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setSender(value); + break; + case 4: + var value = /** @type {string} */ (reader.readString()); + msg.addRecipients(value); + break; + case 5: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setData(value); + break; + case 6: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setSalt(value); + break; + case 7: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setApitoken(value); + break; + case 8: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setSignature(value); + break; + case 9: + var value = /** @type {string} */ (reader.readString()); + msg.setFee(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.push.Transaction.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.push.Transaction.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.push.Transaction} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.push.Transaction.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getType(); + if (f !== 0) { + writer.writeUint32( + 1, + f + ); + } + f = message.getCategory(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = message.getSender(); + if (f.length > 0) { + writer.writeString( + 3, + f + ); + } + f = message.getRecipientsList(); + if (f.length > 0) { + writer.writeRepeatedString( + 4, + f + ); + } + f = message.getData_asU8(); + if (f.length > 0) { + writer.writeBytes( + 5, + f + ); + } + f = message.getSalt_asU8(); + if (f.length > 0) { + writer.writeBytes( + 6, + f + ); + } + f = message.getApitoken_asU8(); + if (f.length > 0) { + writer.writeBytes( + 7, + f + ); + } + f = message.getSignature_asU8(); + if (f.length > 0) { + writer.writeBytes( + 8, + f + ); + } + f = message.getFee(); + if (f.length > 0) { + writer.writeString( + 9, + f + ); + } +}; + + +/** + * optional uint32 type = 1; + * @return {number} + */ +proto.push.Transaction.prototype.getType = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.push.Transaction} returns this + */ +proto.push.Transaction.prototype.setType = function(value) { + return jspb.Message.setProto3IntField(this, 1, value); +}; + + +/** + * optional string category = 2; + * @return {string} + */ +proto.push.Transaction.prototype.getCategory = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.push.Transaction} returns this + */ +proto.push.Transaction.prototype.setCategory = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +/** + * optional string sender = 3; + * @return {string} + */ +proto.push.Transaction.prototype.getSender = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * @param {string} value + * @return {!proto.push.Transaction} returns this + */ +proto.push.Transaction.prototype.setSender = function(value) { + return jspb.Message.setProto3StringField(this, 3, value); +}; + + +/** + * repeated string recipients = 4; + * @return {!Array} + */ +proto.push.Transaction.prototype.getRecipientsList = function() { + return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 4)); +}; + + +/** + * @param {!Array} value + * @return {!proto.push.Transaction} returns this + */ +proto.push.Transaction.prototype.setRecipientsList = function(value) { + return jspb.Message.setField(this, 4, value || []); +}; + + +/** + * @param {string} value + * @param {number=} opt_index + * @return {!proto.push.Transaction} returns this + */ +proto.push.Transaction.prototype.addRecipients = function(value, opt_index) { + return jspb.Message.addToRepeatedField(this, 4, value, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.push.Transaction} returns this + */ +proto.push.Transaction.prototype.clearRecipientsList = function() { + return this.setRecipientsList([]); +}; + + +/** + * optional bytes data = 5; + * @return {!(string|Uint8Array)} + */ +proto.push.Transaction.prototype.getData = function() { + return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 5, "")); +}; + + +/** + * optional bytes data = 5; + * This is a type-conversion wrapper around `getData()` + * @return {string} + */ +proto.push.Transaction.prototype.getData_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getData())); +}; + + +/** + * optional bytes data = 5; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getData()` + * @return {!Uint8Array} + */ +proto.push.Transaction.prototype.getData_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getData())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.push.Transaction} returns this + */ +proto.push.Transaction.prototype.setData = function(value) { + return jspb.Message.setProto3BytesField(this, 5, value); +}; + + +/** + * optional bytes salt = 6; + * @return {!(string|Uint8Array)} + */ +proto.push.Transaction.prototype.getSalt = function() { + return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 6, "")); +}; + + +/** + * optional bytes salt = 6; + * This is a type-conversion wrapper around `getSalt()` + * @return {string} + */ +proto.push.Transaction.prototype.getSalt_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getSalt())); +}; + + +/** + * optional bytes salt = 6; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getSalt()` + * @return {!Uint8Array} + */ +proto.push.Transaction.prototype.getSalt_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getSalt())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.push.Transaction} returns this + */ +proto.push.Transaction.prototype.setSalt = function(value) { + return jspb.Message.setProto3BytesField(this, 6, value); +}; + + +/** + * optional bytes apiToken = 7; + * @return {!(string|Uint8Array)} + */ +proto.push.Transaction.prototype.getApitoken = function() { + return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 7, "")); +}; + + +/** + * optional bytes apiToken = 7; + * This is a type-conversion wrapper around `getApitoken()` + * @return {string} + */ +proto.push.Transaction.prototype.getApitoken_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getApitoken())); +}; + + +/** + * optional bytes apiToken = 7; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getApitoken()` + * @return {!Uint8Array} + */ +proto.push.Transaction.prototype.getApitoken_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getApitoken())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.push.Transaction} returns this + */ +proto.push.Transaction.prototype.setApitoken = function(value) { + return jspb.Message.setProto3BytesField(this, 7, value); +}; + + +/** + * optional bytes signature = 8; + * @return {!(string|Uint8Array)} + */ +proto.push.Transaction.prototype.getSignature = function() { + return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 8, "")); +}; + + +/** + * optional bytes signature = 8; + * This is a type-conversion wrapper around `getSignature()` + * @return {string} + */ +proto.push.Transaction.prototype.getSignature_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getSignature())); +}; + + +/** + * optional bytes signature = 8; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getSignature()` + * @return {!Uint8Array} + */ +proto.push.Transaction.prototype.getSignature_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getSignature())); +}; + + +/** + * @param {!(string|Uint8Array)} value + * @return {!proto.push.Transaction} returns this + */ +proto.push.Transaction.prototype.setSignature = function(value) { + return jspb.Message.setProto3BytesField(this, 8, value); +}; + + +/** + * optional string fee = 9; + * @return {string} + */ +proto.push.Transaction.prototype.getFee = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 9, "")); +}; + + +/** + * @param {string} value + * @return {!proto.push.Transaction} returns this + */ +proto.push.Transaction.prototype.setFee = function(value) { + return jspb.Message.setProto3StringField(this, 9, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.push.EncryptedText.prototype.toObject = function(opt_includeInstance) { + return proto.push.EncryptedText.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.push.EncryptedText} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.push.EncryptedText.toObject = function(includeInstance, msg) { + var f, obj = { + ciphertext: jspb.Message.getFieldWithDefault(msg, 1, ""), + salt: jspb.Message.getFieldWithDefault(msg, 2, ""), + nonce: jspb.Message.getFieldWithDefault(msg, 3, ""), + version: jspb.Message.getFieldWithDefault(msg, 4, ""), + prekey: jspb.Message.getFieldWithDefault(msg, 5, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.push.EncryptedText} + */ +proto.push.EncryptedText.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.push.EncryptedText; + return proto.push.EncryptedText.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.push.EncryptedText} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.push.EncryptedText} + */ +proto.push.EncryptedText.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setCiphertext(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setSalt(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setNonce(value); + break; + case 4: + var value = /** @type {string} */ (reader.readString()); + msg.setVersion(value); + break; + case 5: + var value = /** @type {string} */ (reader.readString()); + msg.setPrekey(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.push.EncryptedText.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.push.EncryptedText.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.push.EncryptedText} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.push.EncryptedText.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getCiphertext(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getSalt(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = message.getNonce(); + if (f.length > 0) { + writer.writeString( + 3, + f + ); + } + f = message.getVersion(); + if (f.length > 0) { + writer.writeString( + 4, + f + ); + } + f = message.getPrekey(); + if (f.length > 0) { + writer.writeString( + 5, + f + ); + } +}; + + +/** + * optional string ciphertext = 1; + * @return {string} + */ +proto.push.EncryptedText.prototype.getCiphertext = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.push.EncryptedText} returns this + */ +proto.push.EncryptedText.prototype.setCiphertext = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string salt = 2; + * @return {string} + */ +proto.push.EncryptedText.prototype.getSalt = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.push.EncryptedText} returns this + */ +proto.push.EncryptedText.prototype.setSalt = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); }; /** - * @param {string} value - * @return {!proto.push.Transaction} returns this + * optional string nonce = 3; + * @return {string} */ -proto.push.Transaction.prototype.setSender = function(value) { - return jspb.Message.setProto3StringField(this, 3, value); +proto.push.EncryptedText.prototype.getNonce = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); }; /** - * repeated string recipients = 4; - * @return {!Array} + * @param {string} value + * @return {!proto.push.EncryptedText} returns this */ -proto.push.Transaction.prototype.getRecipientsList = function() { - return /** @type {!Array} */ (jspb.Message.getRepeatedField(this, 4)); +proto.push.EncryptedText.prototype.setNonce = function(value) { + return jspb.Message.setProto3StringField(this, 3, value); }; /** - * @param {!Array} value - * @return {!proto.push.Transaction} returns this + * optional string version = 4; + * @return {string} */ -proto.push.Transaction.prototype.setRecipientsList = function(value) { - return jspb.Message.setField(this, 4, value || []); +proto.push.EncryptedText.prototype.getVersion = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); }; /** * @param {string} value - * @param {number=} opt_index - * @return {!proto.push.Transaction} returns this + * @return {!proto.push.EncryptedText} returns this */ -proto.push.Transaction.prototype.addRecipients = function(value, opt_index) { - return jspb.Message.addToRepeatedField(this, 4, value, opt_index); +proto.push.EncryptedText.prototype.setVersion = function(value) { + return jspb.Message.setProto3StringField(this, 4, value); }; /** - * Clears the list making it empty but non-null. - * @return {!proto.push.Transaction} returns this + * optional string preKey = 5; + * @return {string} */ -proto.push.Transaction.prototype.clearRecipientsList = function() { - return this.setRecipientsList([]); +proto.push.EncryptedText.prototype.getPrekey = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, "")); }; /** - * optional bytes data = 5; - * @return {!(string|Uint8Array)} + * @param {string} value + * @return {!proto.push.EncryptedText} returns this */ -proto.push.Transaction.prototype.getData = function() { - return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 5, "")); +proto.push.EncryptedText.prototype.setPrekey = function(value) { + return jspb.Message.setProto3StringField(this, 5, value); }; -/** - * optional bytes data = 5; - * This is a type-conversion wrapper around `getData()` - * @return {string} - */ -proto.push.Transaction.prototype.getData_asB64 = function() { - return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getData())); -}; + +if (jspb.Message.GENERATE_TO_OBJECT) { /** - * optional bytes data = 5; - * Note that Uint8Array is not supported on all browsers. - * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getData()` - * @return {!Uint8Array} + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} */ -proto.push.Transaction.prototype.getData_asU8 = function() { - return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getData())); +proto.push.WalletToEncDerivedKey.prototype.toObject = function(opt_includeInstance) { + return proto.push.WalletToEncDerivedKey.toObject(opt_includeInstance, this); }; /** - * @param {!(string|Uint8Array)} value - * @return {!proto.push.Transaction} returns this + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.push.WalletToEncDerivedKey} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.push.Transaction.prototype.setData = function(value) { - return jspb.Message.setProto3BytesField(this, 5, value); +proto.push.WalletToEncDerivedKey.toObject = function(includeInstance, msg) { + var f, obj = { + encderivedprivkey: (f = msg.getEncderivedprivkey()) && proto.push.EncryptedText.toObject(includeInstance, f), + signature: msg.getSignature_asB64() + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; }; +} /** - * optional bytes salt = 6; - * @return {!(string|Uint8Array)} + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.push.WalletToEncDerivedKey} */ -proto.push.Transaction.prototype.getSalt = function() { - return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 6, "")); +proto.push.WalletToEncDerivedKey.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.push.WalletToEncDerivedKey; + return proto.push.WalletToEncDerivedKey.deserializeBinaryFromReader(msg, reader); }; /** - * optional bytes salt = 6; - * This is a type-conversion wrapper around `getSalt()` - * @return {string} + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.push.WalletToEncDerivedKey} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.push.WalletToEncDerivedKey} */ -proto.push.Transaction.prototype.getSalt_asB64 = function() { - return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getSalt())); +proto.push.WalletToEncDerivedKey.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.push.EncryptedText; + reader.readMessage(value,proto.push.EncryptedText.deserializeBinaryFromReader); + msg.setEncderivedprivkey(value); + break; + case 2: + var value = /** @type {!Uint8Array} */ (reader.readBytes()); + msg.setSignature(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; }; /** - * optional bytes salt = 6; - * Note that Uint8Array is not supported on all browsers. - * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getSalt()` + * Serializes the message to binary data (in protobuf wire format). * @return {!Uint8Array} */ -proto.push.Transaction.prototype.getSalt_asU8 = function() { - return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getSalt())); +proto.push.WalletToEncDerivedKey.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.push.WalletToEncDerivedKey.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); }; /** - * @param {!(string|Uint8Array)} value - * @return {!proto.push.Transaction} returns this + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.push.WalletToEncDerivedKey} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages */ -proto.push.Transaction.prototype.setSalt = function(value) { - return jspb.Message.setProto3BytesField(this, 6, value); +proto.push.WalletToEncDerivedKey.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getEncderivedprivkey(); + if (f != null) { + writer.writeMessage( + 1, + f, + proto.push.EncryptedText.serializeBinaryToWriter + ); + } + f = message.getSignature_asU8(); + if (f.length > 0) { + writer.writeBytes( + 2, + f + ); + } }; /** - * optional bytes apiToken = 7; - * @return {!(string|Uint8Array)} + * optional EncryptedText encDerivedPrivKey = 1; + * @return {?proto.push.EncryptedText} */ -proto.push.Transaction.prototype.getApitoken = function() { - return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 7, "")); +proto.push.WalletToEncDerivedKey.prototype.getEncderivedprivkey = function() { + return /** @type{?proto.push.EncryptedText} */ ( + jspb.Message.getWrapperField(this, proto.push.EncryptedText, 1)); }; /** - * optional bytes apiToken = 7; - * This is a type-conversion wrapper around `getApitoken()` - * @return {string} - */ -proto.push.Transaction.prototype.getApitoken_asB64 = function() { - return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getApitoken())); + * @param {?proto.push.EncryptedText|undefined} value + * @return {!proto.push.WalletToEncDerivedKey} returns this +*/ +proto.push.WalletToEncDerivedKey.prototype.setEncderivedprivkey = function(value) { + return jspb.Message.setWrapperField(this, 1, value); }; /** - * optional bytes apiToken = 7; - * Note that Uint8Array is not supported on all browsers. - * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getApitoken()` - * @return {!Uint8Array} + * Clears the message field making it undefined. + * @return {!proto.push.WalletToEncDerivedKey} returns this */ -proto.push.Transaction.prototype.getApitoken_asU8 = function() { - return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getApitoken())); +proto.push.WalletToEncDerivedKey.prototype.clearEncderivedprivkey = function() { + return this.setEncderivedprivkey(undefined); }; /** - * @param {!(string|Uint8Array)} value - * @return {!proto.push.Transaction} returns this + * Returns whether this field is set. + * @return {boolean} */ -proto.push.Transaction.prototype.setApitoken = function(value) { - return jspb.Message.setProto3BytesField(this, 7, value); +proto.push.WalletToEncDerivedKey.prototype.hasEncderivedprivkey = function() { + return jspb.Message.getField(this, 1) != null; }; /** - * optional bytes signature = 8; + * optional bytes signature = 2; * @return {!(string|Uint8Array)} */ -proto.push.Transaction.prototype.getSignature = function() { - return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 8, "")); +proto.push.WalletToEncDerivedKey.prototype.getSignature = function() { + return /** @type {!(string|Uint8Array)} */ (jspb.Message.getFieldWithDefault(this, 2, "")); }; /** - * optional bytes signature = 8; + * optional bytes signature = 2; * This is a type-conversion wrapper around `getSignature()` * @return {string} */ -proto.push.Transaction.prototype.getSignature_asB64 = function() { +proto.push.WalletToEncDerivedKey.prototype.getSignature_asB64 = function() { return /** @type {string} */ (jspb.Message.bytesAsB64( this.getSignature())); }; /** - * optional bytes signature = 8; + * optional bytes signature = 2; * Note that Uint8Array is not supported on all browsers. * @see http://caniuse.com/Uint8Array * This is a type-conversion wrapper around `getSignature()` * @return {!Uint8Array} */ -proto.push.Transaction.prototype.getSignature_asU8 = function() { +proto.push.WalletToEncDerivedKey.prototype.getSignature_asU8 = function() { return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( this.getSignature())); }; @@ -2373,28 +3493,10 @@ proto.push.Transaction.prototype.getSignature_asU8 = function() { /** * @param {!(string|Uint8Array)} value - * @return {!proto.push.Transaction} returns this - */ -proto.push.Transaction.prototype.setSignature = function(value) { - return jspb.Message.setProto3BytesField(this, 8, value); -}; - - -/** - * optional string fee = 9; - * @return {string} - */ -proto.push.Transaction.prototype.getFee = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 9, "")); -}; - - -/** - * @param {string} value - * @return {!proto.push.Transaction} returns this + * @return {!proto.push.WalletToEncDerivedKey} returns this */ -proto.push.Transaction.prototype.setFee = function(value) { - return jspb.Message.setProto3StringField(this, 9, value); +proto.push.WalletToEncDerivedKey.prototype.setSignature = function(value) { + return jspb.Message.setProto3BytesField(this, 2, value); }; @@ -2430,11 +3532,10 @@ proto.push.InitDid.prototype.toObject = function(opt_includeInstance) { */ proto.push.InitDid.toObject = function(includeInstance, msg) { var f, obj = { - did: jspb.Message.getFieldWithDefault(msg, 1, ""), - masterpubkey: jspb.Message.getFieldWithDefault(msg, 2, ""), - derivedkeyindex: jspb.Message.getFieldWithDefault(msg, 3, 0), - derivedpubkey: jspb.Message.getFieldWithDefault(msg, 4, ""), - wallettoencderivedkeyMap: (f = msg.getWallettoencderivedkeyMap()) ? f.toObject(includeInstance, undefined) : [] + masterpubkey: jspb.Message.getFieldWithDefault(msg, 1, ""), + derivedkeyindex: jspb.Message.getFieldWithDefault(msg, 2, 0), + derivedpubkey: jspb.Message.getFieldWithDefault(msg, 3, ""), + wallettoencderivedkeyMap: (f = msg.getWallettoencderivedkeyMap()) ? f.toObject(includeInstance, proto.push.WalletToEncDerivedKey.toObject) : [] }; if (includeInstance) { @@ -2472,25 +3573,21 @@ proto.push.InitDid.deserializeBinaryFromReader = function(msg, reader) { var field = reader.getFieldNumber(); switch (field) { case 1: - var value = /** @type {string} */ (reader.readString()); - msg.setDid(value); - break; - case 2: var value = /** @type {string} */ (reader.readString()); msg.setMasterpubkey(value); break; - case 3: + case 2: var value = /** @type {number} */ (reader.readUint32()); msg.setDerivedkeyindex(value); break; - case 4: + case 3: var value = /** @type {string} */ (reader.readString()); msg.setDerivedpubkey(value); break; - case 6: + case 4: var value = msg.getWallettoencderivedkeyMap(); reader.readMessage(value, function(message, reader) { - jspb.Map.deserializeBinary(message, reader, jspb.BinaryReader.prototype.readString, jspb.BinaryReader.prototype.readString, null, "", ""); + jspb.Map.deserializeBinary(message, reader, jspb.BinaryReader.prototype.readString, jspb.BinaryReader.prototype.readMessage, proto.push.WalletToEncDerivedKey.deserializeBinaryFromReader, "", new proto.push.WalletToEncDerivedKey()); }); break; default: @@ -2522,65 +3619,40 @@ proto.push.InitDid.prototype.serializeBinary = function() { */ proto.push.InitDid.serializeBinaryToWriter = function(message, writer) { var f = undefined; - f = message.getDid(); - if (f.length > 0) { - writer.writeString( - 1, - f - ); - } f = message.getMasterpubkey(); if (f.length > 0) { writer.writeString( - 2, + 1, f ); } f = message.getDerivedkeyindex(); if (f !== 0) { writer.writeUint32( - 3, + 2, f ); } f = message.getDerivedpubkey(); if (f.length > 0) { writer.writeString( - 4, + 3, f ); } f = message.getWallettoencderivedkeyMap(true); if (f && f.getLength() > 0) { - f.serializeBinary(6, writer, jspb.BinaryWriter.prototype.writeString, jspb.BinaryWriter.prototype.writeString); + f.serializeBinary(4, writer, jspb.BinaryWriter.prototype.writeString, jspb.BinaryWriter.prototype.writeMessage, proto.push.WalletToEncDerivedKey.serializeBinaryToWriter); } }; /** - * optional string did = 1; - * @return {string} - */ -proto.push.InitDid.prototype.getDid = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * @param {string} value - * @return {!proto.push.InitDid} returns this - */ -proto.push.InitDid.prototype.setDid = function(value) { - return jspb.Message.setProto3StringField(this, 1, value); -}; - - -/** - * optional string masterPubKey = 2; + * optional string masterPubKey = 1; * @return {string} */ proto.push.InitDid.prototype.getMasterpubkey = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); }; @@ -2589,16 +3661,16 @@ proto.push.InitDid.prototype.getMasterpubkey = function() { * @return {!proto.push.InitDid} returns this */ proto.push.InitDid.prototype.setMasterpubkey = function(value) { - return jspb.Message.setProto3StringField(this, 2, value); + return jspb.Message.setProto3StringField(this, 1, value); }; /** - * optional uint32 derivedKeyIndex = 3; + * optional uint32 derivedKeyIndex = 2; * @return {number} */ proto.push.InitDid.prototype.getDerivedkeyindex = function() { - return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0)); + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0)); }; @@ -2607,16 +3679,16 @@ proto.push.InitDid.prototype.getDerivedkeyindex = function() { * @return {!proto.push.InitDid} returns this */ proto.push.InitDid.prototype.setDerivedkeyindex = function(value) { - return jspb.Message.setProto3IntField(this, 3, value); + return jspb.Message.setProto3IntField(this, 2, value); }; /** - * optional string derivedPubKey = 4; + * optional string derivedPubKey = 3; * @return {string} */ proto.push.InitDid.prototype.getDerivedpubkey = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); }; @@ -2625,20 +3697,20 @@ proto.push.InitDid.prototype.getDerivedpubkey = function() { * @return {!proto.push.InitDid} returns this */ proto.push.InitDid.prototype.setDerivedpubkey = function(value) { - return jspb.Message.setProto3StringField(this, 4, value); + return jspb.Message.setProto3StringField(this, 3, value); }; /** - * map walletToEncDerivedKey = 6; + * map walletToEncDerivedKey = 4; * @param {boolean=} opt_noLazyCreate Do not create the map if * empty, instead returning `undefined` - * @return {!jspb.Map} + * @return {!jspb.Map} */ proto.push.InitDid.prototype.getWallettoencderivedkeyMap = function(opt_noLazyCreate) { - return /** @type {!jspb.Map} */ ( - jspb.Message.getMapField(this, 6, opt_noLazyCreate, - null)); + return /** @type {!jspb.Map} */ ( + jspb.Message.getMapField(this, 4, opt_noLazyCreate, + proto.push.WalletToEncDerivedKey)); }; @@ -2648,8 +3720,7 @@ proto.push.InitDid.prototype.getWallettoencderivedkeyMap = function(opt_noLazyCr */ proto.push.InitDid.prototype.clearWallettoencderivedkeyMap = function() { this.getWallettoencderivedkeyMap().clear(); - return this; -}; + return this;}; diff --git a/src/proto/block.proto b/src/proto/block.proto index 6ac9d38..3a276b9 100644 --- a/src/proto/block.proto +++ b/src/proto/block.proto @@ -66,16 +66,34 @@ message Block { repeated Signer signers = 3; } -message AttestorReply { - // reply per transaction (same order as in block) - repeated TxAttestorData attestorData = 1; - // signature for the whole block - // assuming that on this node TxAttestorData is filled per every tx - Signer signer = 2; +// INTERNAL NODE API + +// BLOCK ATTESTATION +message AttestBlockResult { + // reply per transaction (same order as in block) + repeated TxAttestorData attestorData = 1; + // signature for the whole block + // assuming that on this node TxAttestorData is filled per every tx + Signer signer = 2; +} + +// SIGNATURE ATTESTATION +message AttestSignaturesRequest { + repeated AttestBlockResult attestations = 1; + bytes initialBlockHash = 2; + bytes finalBlockHash = 3; +} + +message AttestSignaturesResponse { + repeated AttestorReport attestations = 1; } -message AttestorReplies { - repeated AttestorReply attestations = 1; +message AttestorReport { + string nodeId = 1 ; + string transactionHash = 2; + int32 vote = 3; + bytes dataForSc = 4; + bytes dataSigForSc = 5; } @@ -99,15 +117,26 @@ message Transaction { // PAYLOADS ------------------------------------------------------------------------------------------------------------ +message EncryptedText { + string ciphertext = 1; + string salt = 2; + string nonce = 3; + string version = 4; + string preKey = 5; + } + +message WalletToEncDerivedKey { + EncryptedText encDerivedPrivKey = 1; + // Helps Vnode to proof that encryptedData is indeed signed by account + bytes signature = 2; +} // INIT_DID + message InitDid { - string did = 1; - string masterPubKey = 2; - uint32 derivedKeyIndex = 3; - string derivedPubKey = 4; - // Map to store wallet address and corresponding encrypted derived key - // Note:- There will always be altest 1 mapping - map walletToEncDerivedKey = 6; + string masterPubKey = 1; + uint32 derivedKeyIndex = 2; + string derivedPubKey = 3; + map walletToEncDerivedKey = 4; } enum KeyAction { From dbdf49e03e2e961bedd1002c3abe34fc97bf96d8 Mon Sep 17 00:00:00 2001 From: Ashis Date: Wed, 23 Oct 2024 14:28:43 +0530 Subject: [PATCH 2/5] fix: implemented block validation --- package.json | 6 +- src/modules/archive/archive-node.service.ts | 44 +- src/utils/EthUtil.ts | 122 +++- src/utils/arrayUtil.ts | 36 ++ src/utils/bitUtil.ts | 117 ++++ src/utils/blockUtil.ts | 598 ++++++++++++++++++++ src/utils/chainUtil.ts | 72 +++ src/utils/dateUtil.ts | 56 ++ src/utils/ethersUtil.ts | 68 +++ src/utils/expressUtil.ts | 21 + src/utils/hashUtil.ts | 51 ++ src/utils/numUtil.ts | 25 +- src/utils/solUtil.ts | 42 ++ src/utils/starkNetUtil.ts | 58 ++ src/utils/strUtil.ts | 243 +++++++- yarn.lock | 513 ++++++++++++++++- 16 files changed, 2022 insertions(+), 50 deletions(-) create mode 100644 src/utils/arrayUtil.ts create mode 100644 src/utils/bitUtil.ts create mode 100644 src/utils/blockUtil.ts create mode 100644 src/utils/chainUtil.ts create mode 100644 src/utils/dateUtil.ts create mode 100644 src/utils/ethersUtil.ts create mode 100644 src/utils/expressUtil.ts create mode 100644 src/utils/hashUtil.ts create mode 100644 src/utils/solUtil.ts create mode 100644 src/utils/starkNetUtil.ts diff --git a/package.json b/package.json index 29de3df..5ed7013 100644 --- a/package.json +++ b/package.json @@ -63,16 +63,20 @@ "@nestjs/websockets": "^10.4.1", "@prisma/client": "^5.19.1", "@pushprotocol/node-core": "^0.0.8", + "@solana/web3.js": "^1.95.4", + "crypto-js": "^4.2.0", "ethers": "^5.7.2", "google-protobuf": "^3.21.4", "node-schedule": "^2.1.1", "object-hash": "^3.0.0", "prisma": "^5.19.1", "reflect-metadata": "^0.2.2", + "starknet": "^6.11.0", "swagger-ui-express": "^5.0.1", "ts-luxon": "^5.0.7-beta.0", + "tweetnacl": "^1.0.3", "typedi": "^0.10.0", "winston": "^3.14.2", "ws": "^8.18.0" } -} \ No newline at end of file +} diff --git a/src/modules/archive/archive-node.service.ts b/src/modules/archive/archive-node.service.ts index d56b76d..a22ba8c 100644 --- a/src/modules/archive/archive-node.service.ts +++ b/src/modules/archive/archive-node.service.ts @@ -3,16 +3,20 @@ import { Consumer, QItem } from '../../messaging/types/queue-types'; import { Injectable } from '@nestjs/common'; import { PrismaService } from '../../prisma/prisma.service'; import { ObjectHasher } from '../../utils/objectHasher'; +import { ValidatorContractState } from '../validator/validator-contract-state.service'; +import { BlockUtil } from '../../utils/blockUtil'; @Injectable() export class ArchiveNodeService implements Consumer { constructor(private readonly prisma: PrismaService) {} + valContractState: ValidatorContractState; public async accept(item: QItem): Promise { try { // Deserialize the block data const bytes = Uint8Array.from(Buffer.from(item.object, 'hex')); - const block = Block.deserializeBinary(bytes).toObject(); + const deserializedBlock = Block.deserializeBinary(bytes); + const block = deserializedBlock.toObject(); // Extract block hash from the block const blockHash = this.getBlockHash(block); @@ -40,6 +44,22 @@ export class ArchiveNodeService implements Consumer { return true; } + // Block validation // + // validate the hash + const calculatedHash = BlockUtil.hashBlockAsHex(bytes); + if (calculatedHash != item.object_hash) { + throw new Error( + 'received item hash= , ' + + item.object_hash + + 'which differs from calculatedHash=, ' + + calculatedHash + + 'ignoring the block because producer calculated the hash incorrectly', + ); + } + // validate the signature + if (!(await this.validateBlock(deserializedBlock))) { + throw new Error('Block validation failed'); + } // Insert block into the database await this.prisma.block.create({ data: blockData }); @@ -54,6 +74,22 @@ export class ArchiveNodeService implements Consumer { } } + private async validateBlock(block: Block) { + const validatorSet = new Set(this.valContractState.getAllNodesMap().keys()); + const validationPerBlock = this.valContractState.contractCli.valPerBlock; + const validationRes = await BlockUtil.checkBlockFinalized( + block, + validatorSet, + validationPerBlock, + ); + if (!validationRes.success) { + console.error('Error while block validation'); + return false; + } else { + return true; + } + } + private getBlockHash(block: Block.AsObject): string { // Generate a block hash using the ObjectHasher utility return ObjectHasher.hashToSha256(block); @@ -66,7 +102,7 @@ export class ArchiveNodeService implements Consumer { return block !== null; } - private recursivelyConvertToJSON(obj: any): any { + private recursivelyConvertToJSON(obj: Uint8Array | Array | object): unknown { if (obj instanceof Uint8Array) { // Convert Uint8Array to a base64 string return Buffer.from(obj).toString('base64'); @@ -77,7 +113,7 @@ export class ArchiveNodeService implements Consumer { } if (obj !== null && typeof obj === 'object') { - const convertedObj: any = {}; + const convertedObj: unknown = {}; for (const key in obj) { convertedObj[key] = this.recursivelyConvertToJSON(obj[key]); } @@ -92,7 +128,7 @@ export class ArchiveNodeService implements Consumer { txObjList: Block.AsObject['txobjList'], blockHash: string, blockTs: number, - ): Promise { + ): Promise { const transactionsData = []; for (const txObj of txObjList) { diff --git a/src/utils/EthUtil.ts b/src/utils/EthUtil.ts index 5665d8b..6b7af3d 100644 --- a/src/utils/EthUtil.ts +++ b/src/utils/EthUtil.ts @@ -1,6 +1,33 @@ +import { hashMessage } from '@ethersproject/hash' +import { recoverAddress } from '@ethersproject/transactions' +import { BytesLike, ethers, Wallet } from 'ethers' +import { verifyMessage } from 'ethers/lib/utils' +import { Logger } from 'winston' + +import { BitUtil } from './bitUtil' +import { CaipAddr } from './chainUtil' +import { Check } from './check' +import { ObjectHasher } from './objectHasher' import StrUtil from './strUtil' +import { WinstonUtil } from './winstonUtil' +/** + * Utitily class that allows + * - to sign objects with an eth private key + * - to check that signature later + * + * Ignores 'signature' properties + */ export class EthUtil { + public static log: Logger = WinstonUtil.newLog(EthUtil) + + // sign object + public static async create(wallet: Wallet, ...objectsToHash: any[]): Promise { + const ethMessage = ObjectHasher.hashToSha256IgnoreSig(objectsToHash) + const sig = await wallet.signMessage(ethMessage) + return sig + } + static parseCaipAddress(addressinCAIP: string): CaipAddr | null { if (StrUtil.isEmpty(addressinCAIP)) { return null @@ -22,14 +49,91 @@ export class EthUtil { return null } } -} -// ex: eip155:5:0xD8634C39BBFd4033c0d3289C4515275102423681 -export class CaipAddr { - // ex: eip155 - namespace: string - // ex: 5 - chainId: string | null - // ex: 0xD8634C39BBFd4033c0d3289C4515275102423681 - addr: string + // check object + public static check(sig: string, targetWallet: string, ...objectsToHash: any[]): boolean { + const ethMessage = ObjectHasher.hashToSha256IgnoreSig(objectsToHash) + const verificationAddress = verifyMessage(ethMessage, sig) + if (targetWallet !== verificationAddress) { + return false + } + return true + } + + public static isEthZero(addr: string) { + return '0x0000000000000000000000000000000000000000' === addr + } + + static getMessageHashAsInContract(message: string): string { + return ethers.utils.keccak256(ethers.utils.arrayify(message)) + } + + static toBytes(value: BytesLike | number): Uint8Array { + return ethers.utils.arrayify(value) + } + + // simple sign with a private key + static async signString(wallet: ethers.Signer, message: string): Promise { + return await wallet.signMessage(this.toBytes(message)) + } + + // simple check signature's public key (via address) + public static async checkString( + message: string, + sig: string, + targetWallet: string + ): Promise { + const verificationAddress = verifyMessage(this.toBytes(message), sig) + console.log('verification address:', verificationAddress) + if (targetWallet !== verificationAddress) { + return false + } + return true + } + + // https://ethereum.org/es/developers/tutorials/eip-1271-smart-contract-signatures/ + // sign 'message hash' + public static async signForContract(wallet: ethers.Signer, message: string): Promise { + const hash = this.getMessageHashAsInContract(message) + return await wallet.signMessage(this.toBytes(hash)) + } + + // check 'message hash' + public static async checkForContract( + message: string, + sig: string, + targetWallet: string + ): Promise { + const hash = this.getMessageHashAsInContract(message) + const verificationAddress = verifyMessage(ethers.utils.arrayify(hash), sig) + console.log('verification address:', verificationAddress) + if (targetWallet !== verificationAddress) { + return false + } + return true + } + + // 0xAAAA == eip155:1:0xAAAAA + public static recoverAddressFromMsg(message: Uint8Array, signature: Uint8Array): string { + return recoverAddress(hashMessage(message), signature) + } + + public static recoverAddress(hash: Uint8Array, signature: Uint8Array): string { + return recoverAddress(hash, signature) + } + + public static ethHash(message: Uint8Array) { + return hashMessage(message) + } + + public static async signBytes(wallet: Wallet, bytes: Uint8Array): Promise { + const sig = await wallet.signMessage(bytes) + Check.isTrue(sig.startsWith('0x')) + const sigNoPrefix = sig.slice(2) + const result = BitUtil.base16ToBytes(sigNoPrefix) + Check.isTrue(result != null && result.length > 0) + return result + } } + +export function Signed(target: Function) {} diff --git a/src/utils/arrayUtil.ts b/src/utils/arrayUtil.ts new file mode 100644 index 0000000..3661b9e --- /dev/null +++ b/src/utils/arrayUtil.ts @@ -0,0 +1,36 @@ +export class ArrayUtil { + public static isEmpty(arr: T[] | Uint8Array | null): boolean { + if (arr == null) { + return true + } + if (typeof arr !== 'object') { + return false + } + return arr.length === 0 + } + + private static isArrayEmpty(array: Uint8Array | null): boolean { + return array == null || array.length === 0 + } + + public static hasMinSize(array: Uint8Array, minSize: number): boolean { + if (minSize === 0) { + return ArrayUtil.isArrayEmpty(array) + } + return array.length >= minSize + } + + public static isEqual(arr0: Uint8Array, arr1: Uint8Array): boolean { + if (arr0 == null && arr1 == null) { + return true + } + if (arr0 == arr1) { + return true + } + if (arr0.length !== arr1.length) { + return false + } + return Buffer.from(arr0).equals(Buffer.from(arr1)) + } + } + \ No newline at end of file diff --git a/src/utils/bitUtil.ts b/src/utils/bitUtil.ts new file mode 100644 index 0000000..2ea65a1 --- /dev/null +++ b/src/utils/bitUtil.ts @@ -0,0 +1,117 @@ +// @ts-ignore +import bs58 from 'bs58' + +import { Coll } from './coll' + +// bytes (as hex numbers) = 0x41 0x41 0x42 0x42 +// Uint8Array (as decimal numbers) = 65 65 66 66 +// string (as non printable chars) = .. +// base16 string = 0xAABB +// base64 string = QUFCQg== + +export class BitUtil { + /** + * XORs 2 buffers, byte by byte: src = src XOR add + * 1 modifies src + * 2 returns srs || src's resized copy in case there is no room for add bytes + * + * @param src + * @param add + */ + public static xor(src: Buffer, add: Buffer): Buffer { + if (src == null && add == null) { + return Buffer.alloc(0) + } else if (add == null) { + return src + } else if (src == null) { + src = new Buffer(add.length) + add.copy(src, 0, 0, add.length) + return src + } + let target = src + if (add.length > src.length) { + target = new Buffer(add.length) + src.copy(target, 0, 0, src.length) + } + const length = Math.min(target.length, add.length) + for (let i = 0; i < length; ++i) { + target[i] = target[i] ^ add[i] + } + return target + } + + public static strToBase64(value: string): string { + return Buffer.from(value).toString('base64') + } + + public static base64ToStr(value: string): string { + return Buffer.from(value, 'base64').toString('utf8') + } + + public static getBit(number: number, bitOffset: number) { + return (number & (1 << bitOffset)) === 0 ? 0 : 1 + } + + public static bitsToPositions(number: number): number[] { + // return null; + const result: number[] = [] + let position = 0 + while (number !== 0) { + if ((number & 1) === 1) { + result.push(position) + } + number = number >>> 1 + position++ + } + Coll.sortNumbersAsc(result) + return result + } + + public static base16ToBytes(base16String: string): Uint8Array { + return Uint8Array.from(Buffer.from(base16String, 'hex')) + } + + public static bytesToBase16(arr: Uint8Array): string { + return Buffer.from(arr).toString('hex') + } + + public static bytesBufToBase16(buf: Buffer): string { + return buf.toString('hex') + } + + public static base64ToString(base64String: string): string { + return Buffer.from(base64String, 'base64').toString('utf8') + } + + public static bytesToBase64(bytes: Uint8Array): string { + return Buffer.from(bytes).toString('base64') + } + + public static base64ToBytes(base64String: string): Uint8Array { + return new Uint8Array(Buffer.from(base64String, 'base64')) + } + + public static bytesUtfToString(bytes: Uint8Array): string { + return Buffer.from(bytes).toString('utf8') + } + + public static stringToBytesUtf(str: string): Uint8Array { + return new Uint8Array(Buffer.from(str, 'utf-8')) + } + + public static stringToBase64(str: string): string { + return Buffer.from(str, 'utf-8').toString('base64') + } + + public static base64ToBase16(base64String: string): string { + return Buffer.from(base64String, 'base64').toString('hex') + } + + public static base58ToBytes(base58String: string): Uint8Array { + return bs58.decode(base58String) + } + + public static bytesToBase58(bytes: Uint8Array): string { + return bs58.encode(bytes) + } +} diff --git a/src/utils/blockUtil.ts b/src/utils/blockUtil.ts new file mode 100644 index 0000000..c1d0a5d --- /dev/null +++ b/src/utils/blockUtil.ts @@ -0,0 +1,598 @@ +import { Wallet } from 'ethers' +import { Logger } from 'winston' + +import { + AttestBlockResult, + Block, + InitDid, + Signer, + Transaction, + TxAttestorData, + TxValidatorData, + Vote +} from '../generated/block_pb' +import { ArrayUtil } from './arrayUtil' +import { BitUtil } from './bitUtil' +import { ChainUtil } from './chainUtil' +import { Check } from './check' +import DateUtil from './dateUtil' +import { EnvLoader } from './envLoader' +import { EthUtil } from './EthUtil' +import { HashUtil } from './hashUtil' +import { NumUtil } from './numUtil' +import { SolUtil } from './solUtil' +import { StarkNetUtil } from './starkNetUtil' +import StrUtil from './strUtil' +import { WinstonUtil } from './winstonUtil' + +export class BlockUtil { + public static readonly log: Logger = WinstonUtil.newLog(BlockUtil) + + // max serialized tx size + public static readonly MAX_TRANSACTION_SIZE_BYTES = EnvLoader.getPropertyAsNumber( + 'MAX_TRANSACTION_SIZE_BYTES', + 1000000 + ) + // max total tx data in a block , + // when reached block would stop accepting transactions + public static readonly MAX_TOTAL_TRANSACTION_SIZE_BYTES = EnvLoader.getPropertyAsNumber( + 'MAX_TOTAL_TRANSACTION_SIZE_BYTES', + 10 * 1000000 + ) + + // max total tx count + // when reached block would stop accepting transactions + public static readonly MAX_TRANSACTIONS_PER_BLOCK = EnvLoader.getPropertyAsNumber( + 'MAX_TRANSACTION_PER_BLOCK', + 1000 + ) + + // blocks older than this would get rejected by attestors + // note: attestor should have an up-to-date clock time for this (!) + public static ATTESTOR_MAX_BLOCK_AGE_SECONDS = EnvLoader.getPropertyAsNumber( + 'MAX_BLOCK_AGE_SECONDS', + 0 + ) + + // we will cache incomplete blocks for this amount of seconds + // attestSignatures will stop working after this time + public static readonly MAX_BLOCK_ASSEMBLY_TIME_SECONDS = EnvLoader.getPropertyAsNumber( + 'MAX_BLOCK_ASSEMBLY_TIME_SECONDS', + 60 + ) + + public static readonly VALID_VALIDATOR_VOTES: Set = new Set([1]) + public static readonly VALID_ATTESTOR_VOTES: Set = new Set([1, 2]) + public static readonly ATT_TOKEN_PREFIX = 'AT1' + public static readonly VAL_TOKEN_PREFIX = 'VT1' + + public static parseTx(txRaw: Uint8Array): Transaction { + if (txRaw == null || txRaw.length > BlockUtil.MAX_TRANSACTION_SIZE_BYTES) { + throw new Error('tx size is too big') + } + const tx = Transaction.deserializeBinary(txRaw) + return tx + } + + public static parseBlock(bRaw: Uint8Array): Block { + const b = Block.deserializeBinary(bRaw) + return b + } + + public static hashTxAsHex(txRaw: Uint8Array): string { + return BitUtil.bytesToBase16(BlockUtil.hashTx(txRaw)) + } + + private static hashTx(txRaw: Uint8Array) { + return HashUtil.sha256AsBytes(txRaw) + } + + public static hashBlockAsHex(blockRaw: Uint8Array): string { + return BitUtil.bytesToBase16(HashUtil.sha256AsBytes(blockRaw)) + } + + // when the block has not been signed, we still need a valid immutable hash based on tx data + // this is used to cache the block contents + // Deprecated + public static hashBlockIncomplete(blockObj: Block): string { + const txHashes: Uint8Array[] = [] + for (const txObj of blockObj.getTxobjList()) { + const tx = txObj.getTx() + const txHash = BlockUtil.hashTx(tx.serializeBinary()) + txHashes.push(txHash) + } + return BitUtil.bytesToBase16(HashUtil.sha256ArrayAsBytes(txHashes)) + } + + public static blockToJson(block: Block) { + return JSON.stringify(block.toObject()) + } + + public static transactionToJson(tx: Transaction) { + return JSON.stringify(tx.toObject()) + } + + public static blockToBase16(block: Block) { + return BitUtil.bytesToBase16(block.serializeBinary()) + } + + public static transactionToBase16(tx: Transaction) { + return BitUtil.bytesToBase16(tx.serializeBinary()) + } + + // 1) try to get first byte from caip address + // eip155:5:0xD8634C39BBFd4033c0d3289C4515275102423681 -> d8 -> 216 + // and use it as shard + // 2) take sha256(addr) -> + // shard count is a smart contract constant; normally it should never change + // lets read this value from a contract + public static calculateAffectedShard(walletInCaip: string, shardCount: number): number | null { + if (StrUtil.isEmpty(walletInCaip)) { + return null + } + + const [caip, err] = ChainUtil.parseCaipAddress(walletInCaip) + if (err != null) { + throw new Error('invalid caip address:' + err) + } + if (!(caip != null && !StrUtil.isEmpty(caip.addr) && caip.addr.length > 4)) { + return null + } + const addrWithoutPrefix = !caip.addr.startsWith('0x') ? caip.addr : caip.addr.substring(2) + const sha = HashUtil.sha256AsBytesEx(BitUtil.stringToBytesUtf(addrWithoutPrefix)) + const shardId = sha[0] + Check.notNull(shardId) + Check.isTrue(shardId >= 0 && shardId <= 255 && NumUtil.isRoundedInteger(shardId)) + Check.isTrue(shardCount >= 1) + return shardId % shardCount + } + + /** + * Evaluates all messageBlock target recipients (normally these are addresses) + * for every included packet + * + * And for every recipient finds which shard will host this address + * + * @param block + * @param shardCount total amount of shards; see smart contract for this value + * @returns a set of shard ids + */ + static calculateAffectedShards(block: Block, shardCount: number): Set { + const shards = new Set() + for (const txObj of block.getTxobjList()) { + const senderAndRecipients = [txObj.getTx().getSender(), ...txObj.getTx().getRecipientsList()] + for (const wallet of senderAndRecipients) { + const shardId = this.calculateAffectedShard(wallet, shardCount) + if (shardId == null) { + continue + } + shards.add(shardId) + } + } + return shards + } + + public static checkValidatorTokenFormat(apiTokenBytes: Uint8Array): CheckR { + const token = BitUtil.bytesUtfToString(apiTokenBytes) + if (StrUtil.isEmpty(token) || !token.startsWith(BlockUtil.VAL_TOKEN_PREFIX)) { + return CheckR.failWithText( + `invalid attestor token; ${StrUtil.fmt(apiTokenBytes)} should start with ${BlockUtil.ATT_TOKEN_PREFIX}` + ) + } + return CheckR.ok() + } + + public static checkAttestTokenFormat(attestorTokenBytes: Uint8Array): CheckR { + const token = BitUtil.bytesUtfToString(attestorTokenBytes) + if (StrUtil.isEmpty(token) || !token.startsWith(BlockUtil.ATT_TOKEN_PREFIX)) { + return CheckR.failWithText( + `invalid attestor token; ${StrUtil.fmt(attestorTokenBytes)} should start with ${BlockUtil.ATT_TOKEN_PREFIX}` + ) + } + return CheckR.ok() + } + + public static async signTxEVM(tx: Transaction, evmWallet: Wallet) { + Check.isTrue( + ArrayUtil.isEmpty(tx.getSignature_asU8()), + ' clear the signature field first, signature is:' + tx.getSignature() + ) + const tmpBytes = tx.serializeBinary() + const sig = await EthUtil.signBytes(evmWallet, tmpBytes) + tx.setSignature(sig) + } + + public static async signTxSolana(tx: Transaction, solanaPrivateKey: Uint8Array) { + Check.isTrue( + ArrayUtil.isEmpty(tx.getSignature_asU8()), + ' clear the signature field first, signature is:' + tx.getSignature() + ) + const tmpBytes = tx.serializeBinary() + const sig = SolUtil.signBytes(solanaPrivateKey, tmpBytes) + tx.setSignature(sig) + } + + public static async signTxStarkNet(tx: Transaction, starkNetPrivateKey: Uint8Array) { + Check.isTrue( + ArrayUtil.isEmpty(tx.getSignature_asU8()), + ' clear the signature field first, signature is:' + tx.getSignature() + ) + const tmpBytes = tx.serializeBinary() + const sig = StarkNetUtil.signBytes(starkNetPrivateKey, tmpBytes) + tx.setSignature(sig) + } + + public static async checkTxSignature(tx: Transaction): Promise { + const [caip, err] = ChainUtil.parseCaipAddress(tx.getSender()) + if (err != null) { + return CheckR.failWithText('failed to parse caip address: ' + err) + } + if (!ArrayUtil.hasMinSize(tx.getSignature_asU8(), 4)) { + return CheckR.failWithText('signature should have at least 4 bytes size') + } + this.log.debug('checking signature `%s`', StrUtil.fmt(tx.getSignature_asU8())) + // todo if(tx.getCategory() === 'INIT_DID') or === startsWith("CUSTOM:") or ANY OTHER ? + const sig = tx.getSignature_asU8() + const tmp = Transaction.deserializeBinary(tx.serializeBinary()) + tmp.setSignature(null) + const tmpBytes = tmp.serializeBinary() + if (caip.namespace === 'eip155') { + // EVM SIGNATURES + const recoveredAddr = EthUtil.recoverAddressFromMsg(tmpBytes, sig) + const valid = recoveredAddr === caip.addr + this.log.debug('recoveredAddr %s; valid: %s', StrUtil.fmt(recoveredAddr), valid) + if (!valid) { + return CheckR.failWithText(`sender address${tx.getSender()} does not match recovered address ${recoveredAddr} + signature was: ${StrUtil.fmt(`${tx.getSignature()}`)}`) + } + } else if (caip.namespace === 'solana') { + // EVM SIGNATURES + const expectedPubKey = SolUtil.convertAddrToPubKey(caip.addr) + const valid = SolUtil.checkSignature(expectedPubKey, tmpBytes, sig) + this.log.debug('expectedPubKey %s; valid: %s', StrUtil.fmt(expectedPubKey), valid) + if (!valid) { + return CheckR.failWithText(`sender address ${tx.getSender()} does not match + signature: ${StrUtil.fmt(`${tx.getSignature()}`)}`) + } + } else if (caip.namespace === 'starknet') { + return CheckR.failWithText('not suported') + // STARKNET SIGNATURES + // const expectedPubKey = StarkNetUtil.convertAddrToPubKey(caip.addr); + // const valid = StarkNetUtil.checkSignature(expectedPubKey, tmpBytes, sig); + // this.log.debug('expectedPubKey %s; valid: %s', StrUtil.fmt(expectedPubKey), valid); + // if (!valid) { + // return CheckR.failWithText(`sender address ${tx.getSender()} does not match + // signature: ${StrUtil.fmt(`${tx.getSignature()}`)}`); + // } + } else { + return CheckR.failWithText(`unsupported chain id: ${tx.getSender()}`) + } + return CheckR.ok() + } + + public static async checkTx(tx: Transaction): Promise { + const checkToken = BlockUtil.checkValidatorTokenFormat(tx.getApitoken_asU8()) + if (!checkToken.success) { + return checkToken + } + if (tx.getType() != 0) { + return CheckR.failWithText(`Only non-value transactions are supported`) + } + if (!ChainUtil.isFullCAIPAddress(tx.getSender())) { + return CheckR.failWithText( + `sender ${tx.getSender()} is not in full CAIP format ${tx.getSender()}` + ) + } + // todo how many recipients are required per each tx type? + for (const recipientAddr of tx.getRecipientsList()) { + if (!ChainUtil.isFullCAIPAddress(recipientAddr)) { + return CheckR.failWithText( + `recipient ${recipientAddr} is not in full CAIP format ${tx.getSender()}` + ) + } + } + + if (!ArrayUtil.hasMinSize(tx.getSalt_asU8(), 4)) { + return CheckR.failWithText( + `salt field requires >=4 bytes ; ` + StrUtil.fmt(tx.getSalt_asU8()) + ) + } + + const validSignature = await BlockUtil.checkTxSignature(tx) + if (!validSignature.success) { + return CheckR.failWithText(`signature field is invalid`) + } + return CheckR.ok() + } + + public static async checkTxPayload(tx: Transaction): Promise { + if (tx.getCategory() === 'INIT_DID') { + const txData = InitDid.deserializeBinary(tx.getData_asU8()) + if (StrUtil.isEmpty(txData.getMasterpubkey())) { + CheckR.failWithText(`masterPubKey missing`) + } + if (StrUtil.isEmpty(txData.getDerivedpubkey())) { + CheckR.failWithText(`derivedPubKey missing`) + } + if (txData.getWallettoencderivedkeyMap().size < 1) { + CheckR.failWithText(`encDerivedPrivKey missing`) + } + } else if (tx.getCategory().startsWith('CUSTOM:')) { + // no checks for user-defined transactions + } else { + CheckR.failWithText(`unsupported transaction category`) + } + return CheckR.ok() + } + + // for tests + public static async signBlockAsValidator(wallet: Wallet, blockNoSigs: Block) { + Check.isTrue(blockNoSigs.getSignersList().length == 0) + for (const txObj of blockNoSigs.getTxobjList()) { + const voteObj = new TxValidatorData() + voteObj.setVote(Vote.ACCEPTED) + txObj.setValidatordata(voteObj) + txObj.clearAttestordataList() + } + const ethSig = await EthUtil.signBytes(wallet, blockNoSigs.serializeBinary()) + const vSign = new Signer() + vSign.setSig(ethSig) + blockNoSigs.setSignersList([vSign]) + } + + // for tests + public static async signBlockAsAttestor( + wallet: Wallet, + blockSignedByV: Block + ): Promise { + const tmpBlock = Block.deserializeBinary(blockSignedByV.serializeBinary()) + Check.isTrue(blockSignedByV.getSignersList().length == 1) + // tmp block with vsig + attestor data gets signed + const ar = new AttestBlockResult() + for (const txObj of tmpBlock.getTxobjList()) { + const attestorData = new TxAttestorData() + attestorData.setVote(Vote.ACCEPTED) + + ar.getAttestordataList().push(attestorData) + txObj.setAttestordataList([attestorData]) + } + + const ethSig = await EthUtil.signBytes(wallet, tmpBlock.serializeBinary()) + + // embed attestor data and signature into real object + const aSign = new Signer() + aSign.setSig(ethSig) + ar.setSigner(aSign) + return ar + } + + // for tests + public static async appendPatchAsValidator( + wallet: Wallet, + blockSignedByVA: Block, + ar: AttestBlockResult + ): Promise { + for (let txIndex = 0; txIndex < blockSignedByVA.getTxobjList().length; txIndex++) { + const attestDataPerTx = ar.getAttestordataList()[txIndex] + blockSignedByVA.getTxobjList()[txIndex].getAttestordataList().push(attestDataPerTx) + } + blockSignedByVA.getSignersList().push(ar.getSigner()) + } + + public static async recoverPatchAddress( + wallet: Wallet, + blockSignedByVA: Readonly, + ar: AttestBlockResult + ): Promise { + const tmpBlock = Block.deserializeBinary(blockSignedByVA.serializeBinary()) + // tx0 -> attest0, ... + // is restructured into + // block.txObj[0].tx -> attest0, ... + for (let txIndex = 0; txIndex < tmpBlock.getTxobjList().length; txIndex++) { + const attestDataPerTx = ar.getAttestordataList()[txIndex] + tmpBlock.getTxobjList()[txIndex].setAttestordataList([attestDataPerTx]) + } + + const aSignatureBytes = ar.getSigner().getSig_asU8() + const tmpBlockBytes = tmpBlock.serializeBinary() + this.log.debug('recovery pub key from block with hash: %s', EthUtil.ethHash(tmpBlockBytes)) + const attestorNodeId = EthUtil.recoverAddressFromMsg(tmpBlockBytes, aSignatureBytes) + this.log.debug('attestorNodeId %o', attestorNodeId) + return attestorNodeId + } + + public static async recoverSignerAddress( + blockSignedByVA: Readonly, + signerIndex: number + ): Promise { + Check.isTrue( + signerIndex >= 0 && signerIndex < blockSignedByVA.getSignersList().length, + 'signer out of index' + ) + if (signerIndex == 0) { + // validator + const validatorSignature = blockSignedByVA.getSignersList()[0]?.getSig_asU8() + Check.notNull(validatorSignature, 'validator signature is required') + const tmpBlock = Block.deserializeBinary(blockSignedByVA.serializeBinary()) + tmpBlock.clearSignersList() + for (const txObj of tmpBlock.getTxobjList()) { + txObj.clearAttestordataList() + } + const blockBytesNoSigners = tmpBlock.serializeBinary() + const blockValidatorNodeId = EthUtil.recoverAddressFromMsg( + blockBytesNoSigners, + validatorSignature + ) + BlockUtil.log.debug('signature # %s by %s (validator) ', 0, blockValidatorNodeId) + return blockValidatorNodeId + } else { + const tmpBlock = Block.deserializeBinary(blockSignedByVA.serializeBinary()) + const onlyVSignature = [blockSignedByVA.getSignersList()[0]] + tmpBlock.setSignersList(onlyVSignature) + for (let txIndex = 0; txIndex < tmpBlock.getTxobjList().length; txIndex++) { + const txObj = tmpBlock.getTxobjList()[txIndex] + const onlyOneAttestation = blockSignedByVA.getTxobjList()[txIndex].getAttestordataList()[ + signerIndex - 1 + ] + txObj.setAttestordataList([onlyOneAttestation]) + } + + const blockBytesNoSignersAnd1Attest = tmpBlock.serializeBinary() + const attSignature = blockSignedByVA.getSignersList()[signerIndex].getSig_asU8() + const attNodeId = EthUtil.recoverAddressFromMsg(blockBytesNoSignersAnd1Attest, attSignature) + BlockUtil.log.debug('signature # %s by %s ', signerIndex - 1, attNodeId) + return attNodeId + } + } + + public static async checkBlockAsAttestor( + blockSignedByV: Block, + validatorsFromContract: Set + ): Promise { + const checkToken = BlockUtil.checkAttestTokenFormat(blockSignedByV.getAttesttoken_asU8()) + if (!checkToken.success) { + return checkToken + } + if (blockSignedByV.getTxobjList().length >= BlockUtil.MAX_TRANSACTIONS_PER_BLOCK) { + return CheckR.failWithText( + `block is full; tx count: ${blockSignedByV.getTxobjList().length} ; limit: ${BlockUtil.MAX_TRANSACTIONS_PER_BLOCK} ` + ) + } + if ( + BlockUtil.ATTESTOR_MAX_BLOCK_AGE_SECONDS != null && + BlockUtil.ATTESTOR_MAX_BLOCK_AGE_SECONDS > 0 && + Math.abs(blockSignedByV.getTs() - DateUtil.currentTimeMillis()) > + 1000 * BlockUtil.ATTESTOR_MAX_BLOCK_AGE_SECONDS + ) { + return CheckR.failWithText(`block is too old: ${blockSignedByV.getTs()}`) + } + if (!ArrayUtil.hasMinSize(blockSignedByV.getAttesttoken_asU8(), 4)) { + return CheckR.failWithText('attest token is missing or too small (4bytes min)') + } + // all tx should be valid + let totalTxBytes = 0 + for (let i = 0; i < blockSignedByV.getTxobjList().length; i++) { + const txObj = blockSignedByV.getTxobjList()[i] + const tx = txObj.getTx() + if (tx == null) { + return CheckR.failWithText('empty transaction found!') + } + const txBytes = tx.serializeBinary().length + totalTxBytes += txBytes + if (txBytes > BlockUtil.MAX_TRANSACTION_SIZE_BYTES) { + return CheckR.failWithText( + `transaction size exceeds the limit: ${txBytes} ; limit: ${BlockUtil.MAX_TRANSACTION_SIZE_BYTES}` + ) + } + if ( + txObj.getValidatordata() == null || + !BlockUtil.VALID_VALIDATOR_VOTES.has(txObj.getValidatordata().getVote()) + ) { + return CheckR.failWithText(`tx # ${i} has invalid validator data`) + } + const check1 = await BlockUtil.checkTx(tx) + if (!check1.success) { + return check1 + } + const check2 = await BlockUtil.checkTxPayload(tx) + if (!check2.success) { + return check2 + } + } + if (totalTxBytes > BlockUtil.MAX_TOTAL_TRANSACTION_SIZE_BYTES) { + return CheckR.failWithText( + `total transaction size exceeds the limit: ${totalTxBytes} ; limit: ${BlockUtil.MAX_TOTAL_TRANSACTION_SIZE_BYTES}` + ) + } + // number of signatures should be equal to number of attestations + if (blockSignedByV.getSignersList().length == 0) { + return CheckR.failWithText(`at least validator signature is required`) + } + const sigCount = blockSignedByV.getSignersList().length + for (const txObj of blockSignedByV.getTxobjList()) { + if (txObj.getAttestordataList().length != sigCount - 1) { + return CheckR.failWithText( + `number of tx attestations (salt=${txObj.getTx().getSalt()}) does not match with signature count` + ) + } + } + // do a v signature check + const blockValidatorNodeId = await BlockUtil.recoverSignerAddress(blockSignedByV, 0) + BlockUtil.log.debug('signature # %s by %s (validator) ', 0, blockValidatorNodeId) + const allowed = validatorsFromContract.has(blockValidatorNodeId) + Check.isTrue(allowed, `unregistered validator: ${blockValidatorNodeId}`) + return CheckR.ok() + } + + public static async checkBlockFinalized( + blockSignedByVA: Block, + validatorsFromContract: Set, + valPerBlockFromContract: number + ) { + const check1 = await BlockUtil.checkBlockAsAttestor(blockSignedByVA, validatorsFromContract) + if (!check1.success) { + return check1 + } + const sigCount = blockSignedByVA.getSignersList().length + if (sigCount != valPerBlockFromContract) { + return CheckR.failWithText( + `block has only ${sigCount} signatures; expected ${valPerBlockFromContract} signatures ` + ) + } + for (const txObj of blockSignedByVA.getTxobjList()) { + if (txObj.getAttestordataList().length != sigCount - 1) { + return CheckR.failWithText( + `number of tx attestations (salt=${txObj.getTx().getSalt()}) does not match with signature count` + ) + } + } + + const attestorCount = sigCount - 1 + for (let txIndex = 0; txIndex < blockSignedByVA.getTxobjList().length; txIndex++) { + const txObj = blockSignedByVA.getTxobjList()[txIndex] + const tx = txObj.getTx() + if (tx == null) { + return CheckR.failWithText('empty transaction found!') + } + if ( + txObj.getAttestordataList() == null || + txObj.getAttestordataList().length != attestorCount + ) { + return CheckR.failWithText( + `tx # ${txIndex} has invalid number of attestations; ${txObj.getAttestordataList().length} instead of ${attestorCount}` + ) + } + for (const txAttData of txObj.getAttestordataList()) { + if (txAttData == null || !BlockUtil.VALID_ATTESTOR_VOTES.has(txAttData.getVote())) { + return CheckR.failWithText(`tx # ${txIndex} has invalid attestor data`) + } + } + } + + // do A signature check + // this requires clearing all signatures + all attestor data except the current one + const tmpBlock = Block.deserializeBinary(blockSignedByVA.serializeBinary()) + const onlyVSignature = [blockSignedByVA.getSignersList()[0]] + tmpBlock.setSignersList(onlyVSignature) + for (let attIndex = 1; attIndex < sigCount; attIndex++) { + const attNodeId = await BlockUtil.recoverSignerAddress(blockSignedByVA, attIndex) + BlockUtil.log.debug('signature # %s by %s ', attIndex - 1, attNodeId) + const allowed = validatorsFromContract.has(attNodeId) + Check.isTrue(allowed, `unregistered validator_: ${attNodeId}`) + } + return CheckR.ok() + } +} + +export class CheckR { + success: boolean + err: string + + static failWithText(err: string): CheckR { + return { success: false, err: err } + } + + static ok(): CheckR { + return { success: true, err: '' } + } +} diff --git a/src/utils/chainUtil.ts b/src/utils/chainUtil.ts new file mode 100644 index 0000000..8c4f10e --- /dev/null +++ b/src/utils/chainUtil.ts @@ -0,0 +1,72 @@ +import StrUtil from './strUtil' + +export class ChainUtil { + static readonly ADDR_MAX = 64 + static readonly NAMESPACE_MAX = 8 + static readonly CHAINID_MAX = 32 + + /** + * caip10 spec https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md + * + * @param addressinCAIP or error message + */ + public static parseCaipAddress(addressinCAIP: string): Tuple { + if (StrUtil.isEmpty(addressinCAIP) || addressinCAIP.trim() === '') { + return [null, 'Address is empty'] + } + + const addressComponents = addressinCAIP.split(':') + let namespace: string + let chainId: string = null + let addr: string + + if (addressComponents.length === 3) { + ;[namespace, chainId, addr] = addressComponents + } else if (addressComponents.length === 2) { + ;[namespace, addr] = addressComponents + } else { + return [null, 'Invalid CAIP address format'] + } + + if (!StrUtil.hasSize(namespace, 1, this.NAMESPACE_MAX)) { + return [null, `Invalid namespace value: ${namespace}`] + } + if (addressComponents.length == 3 && !StrUtil.hasSize(chainId, 1, this.CHAINID_MAX)) { + return [null, `Invalid chainId value: ${chainId}`] + } + + const addrNoPrefix = addr.startsWith('0x') ? addr.substring(2) : addr + if (!StrUtil.hasSize(addrNoPrefix, 4, this.ADDR_MAX)) { + return [null, `Invalid address value: ${addr}`] + } + + return [{ namespace, chainId, addr }, null] + } + + /* + Valid addresses: + eip155:5:0xAAAAAA + e:1:0 + */ + public static isFullCAIPAddress(fullCaipAddress: string): boolean { + const [caip, err] = ChainUtil.parseCaipAddress(fullCaipAddress) + if (err != null) { + return false + } + const valid = + !StrUtil.isEmpty(caip.chainId) && + !StrUtil.isEmpty(caip.namespace) && + !StrUtil.isEmpty(caip.addr) + return valid + } +} + +// ex: eip155:5:0xD8634C39BBFd4033c0d3289C4515275102423681 +export class CaipAddr { + // ex: eip155 + namespace: string + // ex: 5 + chainId: string | null + // ex: 0xD8634C39BBFd4033c0d3289C4515275102423681 + addr: string +} diff --git a/src/utils/dateUtil.ts b/src/utils/dateUtil.ts new file mode 100644 index 0000000..a20646d --- /dev/null +++ b/src/utils/dateUtil.ts @@ -0,0 +1,56 @@ +import { DateTime } from 'ts-luxon' + +export default class DateUtil { + public static formatYYYYMMDD(yearValue: number, monthValue: number, dayValue: number): string { + return DateTime.fromObject({ year: yearValue, month: monthValue, day: dayValue }).toFormat( + 'yyyyMMdd' + ) + } + + public static formatYYYYMMDDEx(dt: DateTime): string { + return dt.toFormat('yyyyMMdd') + } + + public static formatYYYYMM(dt: DateTime): string { + return dt.toFormat('yyyyMM') + } + + public static buildDateTime(yearValue: number, monthValue: number, dayValue: number): DateTime { + return DateTime.fromObject({ year: yearValue, month: monthValue, day: dayValue }) + } + + // example: 1661214142.000000 + public static parseUnixFloatAsDouble(timestamp: string): number { + return Number.parseFloat(timestamp) + } + + // example: 1661214142 + public static parseUnixFloatAsInt(timestamp: string): number { + return Math.floor(Number.parseFloat(timestamp)) + } + + public static parseUnixFloatAsDateTime(timestamp: string): DateTime { + return DateTime.fromMillis(Number.parseFloat(timestamp) * 1000) + } + + public static dateTimeToUnixFloat(dt: DateTime): number { + return dt.toMillis() / 1000.0 + } + + public static currentTimeMillis(): number { + return Date.now() + } + + public static currentTimeSeconds(): number { + // new Date().getTime() + return Math.round(Date.now() / 1000) + } + + public static millisToDate(timestamp: number): Date { + return new Date(timestamp) + } + + public static millisToUnixSeconds(timestamp: number): number { + return Math.round(timestamp / 1000) + } +} diff --git a/src/utils/ethersUtil.ts b/src/utils/ethersUtil.ts new file mode 100644 index 0000000..96cfd14 --- /dev/null +++ b/src/utils/ethersUtil.ts @@ -0,0 +1,68 @@ +import { JsonRpcProvider } from '@ethersproject/providers/src.ts/json-rpc-provider' +import { Contract, ethers, Wallet } from 'ethers' +import fs from 'fs' +import path from 'path' + +import { WinstonUtil } from './winstonUtil' + +export class EthersUtil { + static log = WinstonUtil.newLog(EthersUtil) + + public static loadAbi(configDir: string, fileNameInConfigDir: string): string { + const fileAbsolute = path.resolve(configDir, `./${fileNameInConfigDir}`) + const file = fs.readFileSync(fileAbsolute, 'utf8') + const json = JSON.parse(file) + const abi = json.abi + console.log(`abi size:`, abi.length) + return abi + } + + // creates a client, using an encrypted private key from disk, so that we could sign/write to the blockchain + public static async connectWithKey( + configDir: string, + privateKeyFileName: string, + privateKeyPass: string, + contractAbiFileName: string, + contractAddr: string, + provider: JsonRpcProvider + ): Promise { + const abi = EthersUtil.loadAbi(configDir, contractAbiFileName) + const jsonFile = fs.readFileSync(configDir + '/' + privateKeyFileName, 'utf-8') + const nodeWallet = await Wallet.fromEncryptedJson(jsonFile, privateKeyPass) + const nodeAddress = await nodeWallet.getAddress() + const signer = nodeWallet.connect(provider) + const contract = new ethers.Contract(contractAddr, abi, signer) + this.log.debug( + 'connecting contract %s using signer %s (keydir: %s, keyfile: %s, abi: %s) ', + contractAddr, + signer.address, + configDir, + privateKeyFileName, + contractAbiFileName + ) + return { + contract, + nodeWallet, + nodeAddress + } + } + + // creates a client which can only read blockchain state + public static async connectWithoutKey( + configDir: string, + contractAbiFileName: string, + contractAddr: string, + provider: JsonRpcProvider + ): Promise { + const abi = EthersUtil.loadAbi(configDir, contractAbiFileName) + const contract = new ethers.Contract(contractAddr, abi, provider) + this.log.debug('connecting contract %s (no key, abi: %s) ', contractAddr, contractAbiFileName) + return contract + } +} + +type ContractWithMeta = { + contract: Contract + nodeWallet: Wallet + nodeAddress: string +} diff --git a/src/utils/expressUtil.ts b/src/utils/expressUtil.ts new file mode 100644 index 0000000..31badaa --- /dev/null +++ b/src/utils/expressUtil.ts @@ -0,0 +1,21 @@ +import { NextFunction, Request, Response } from 'express' + +import { WinstonUtil } from './winstonUtil' + +export class ExpressUtil { + static log = WinstonUtil.newLog('http') + + static handle(req: Request, res: Response, next: NextFunction) { + ExpressUtil.log.debug( + `>> Calling %s %s %o with body: %o`, + req.method, + req.url, + req.params, + req.body + ) + res.on('finish', function () { + ExpressUtil.log.debug(`<< Reply ${res.statusCode} with body: %s`, res.statusMessage) + }) + next() + } +} diff --git a/src/utils/hashUtil.ts b/src/utils/hashUtil.ts new file mode 100644 index 0000000..7df76b2 --- /dev/null +++ b/src/utils/hashUtil.ts @@ -0,0 +1,51 @@ +import crypto from 'crypto' +import * as CryptoJS from 'crypto-js' + +// todo use a better lib +export class HashUtil { + // for readability + private static arrayToWordArray(data: Uint8Array) { + return CryptoJS.lib.WordArray.create(data) + } + + // for readability + private static wordArrayToArray(shaAsWordArray: CryptoJS.lib.WordArray) { + const hexString = CryptoJS.enc.Hex.stringify(shaAsWordArray) + const shaAsArray = Uint8Array.from(Buffer.from(hexString, 'hex')) + return shaAsArray + } + + public static sha256AsBytes(data: Uint8Array): Uint8Array { + const wa = HashUtil.arrayToWordArray(data) + const shaAsWordArray = CryptoJS.SHA256(wa) + return HashUtil.wordArrayToArray(shaAsWordArray) + } + + public static sha256ArrayAsBytes(data: Uint8Array[]): Uint8Array { + const sha256 = CryptoJS.algo.SHA256.create() + for (const chunk of data) { + const wa = HashUtil.arrayToWordArray(chunk) + sha256.update(wa) + } + const shaAsWordArray = sha256.finalize() + return HashUtil.wordArrayToArray(shaAsWordArray) + } + + // todo compare this hash with crypto-js + public static sha512ArrayAsBytes(data: Uint8Array[]): Uint8Array { + const hasher = crypto.createHash('sha512') + for (const arr of data) { + hasher.update(arr) + } + const hash = hasher.digest() + return new Uint8Array(hash) + } + + // todo compare this hash with crypto-js + public static sha256AsBytesEx(data: Uint8Array): Uint8Array { + const hasher = crypto.createHash('sha256') + hasher.update(data) + const hash = hasher.digest() + return new Uint8Array(hash) + } +} diff --git a/src/utils/numUtil.ts b/src/utils/numUtil.ts index 676a5b1..7961ca1 100644 --- a/src/utils/numUtil.ts +++ b/src/utils/numUtil.ts @@ -1,12 +1,23 @@ export class NumUtil { - public static parseInt( - value: string | undefined, - defaultValue: number, - ): number { + public static parseInt(val: string | number | null, defaultValue: number): number { + if (val === null) { + return defaultValue + } + const valN = typeof val === 'string' ? Number(val) : val + if (isNaN(valN)) { + return defaultValue + } + return this.isRoundedInteger(valN) ? valN : Math.round(valN) + } + + static isRoundedInteger(valN: number) { + return Number.isInteger(valN) + } + + public static toString(value: number) { if (value == null) { - return defaultValue; + return '' } - const parsed = parseInt(value, 10); - return isNaN(parsed) ? defaultValue : parsed; + return '' + value } } diff --git a/src/utils/solUtil.ts b/src/utils/solUtil.ts new file mode 100644 index 0000000..5f174b9 --- /dev/null +++ b/src/utils/solUtil.ts @@ -0,0 +1,42 @@ +import { Keypair } from '@solana/web3.js' +import nacl from 'tweetnacl' + +import { BitUtil } from './bitUtil' +import { Check } from './check' + +export class SolUtil { + public static signBytes(walletPrivKey: Uint8Array, msgBytes: Uint8Array): Uint8Array { + const signature = nacl.sign.detached(msgBytes, walletPrivKey) + Check.isTrue(signature != null && signature.length > 0) + return signature + } + + public static checkSignature( + walletPubKey: Uint8Array, + msgBytes: Uint8Array, + signature: Uint8Array + ): boolean { + const result = nacl.sign.detached.verify(msgBytes, signature, walletPubKey) + return result + } + + public static convertAddrToPubKey(solAddress: string): Uint8Array { + return BitUtil.base58ToBytes(solAddress) + } + + public static convertPubKeyToAddr(pubKey: Uint8Array): string { + return BitUtil.bytesToBase58(pubKey) + } + + public static convertPrivKeyToPubKey(solanaPrivateKey: Uint8Array): Uint8Array { + const keypair = Keypair.fromSecretKey(solanaPrivateKey) + const pubKey = keypair.publicKey + return pubKey.toBytes() + } + + public static convertPrivKeyToAddr(solanaPrivateKey: Uint8Array): string { + const pubKey = SolUtil.convertPrivKeyToPubKey(solanaPrivateKey) + const addrStr = SolUtil.convertPubKeyToAddr(pubKey) + return addrStr + } +} diff --git a/src/utils/starkNetUtil.ts b/src/utils/starkNetUtil.ts new file mode 100644 index 0000000..965195f --- /dev/null +++ b/src/utils/starkNetUtil.ts @@ -0,0 +1,58 @@ +import { ec, hash, WeierstrassSignatureType, BigNumberish } from 'starknet' +import { BitUtil } from './bitUtil' + +export class StarkNetUtil { + public static signBytes(walletPrivKey: Uint8Array, msgBytes: Uint8Array): Uint8Array { + const convertedMsg: BigNumberish[] = Array.from(msgBytes) + const msgHash = hash.computeHashOnElements(convertedMsg) + const signature: WeierstrassSignatureType = ec.starkCurve.sign(msgHash, walletPrivKey) + return signature.toCompactRawBytes() + } + + public static checkSignatureWithFullPublicKey( + walletFullPubKey: Uint8Array, + msgBytes: Uint8Array, + signature: Uint8Array + ): boolean { + const convertedMsg: BigNumberish[] = Array.from(msgBytes) + const msgHash = hash.computeHashOnElements(convertedMsg) + const result = ec.starkCurve.verify(signature, msgHash, walletFullPubKey) + console.log('Result (boolean) =', result) + return result + } + + public static checkSignature( + walletAddress: Uint8Array, + msgBytes: Uint8Array, + signature: Uint8Array + ): boolean { + const convertedMsg: BigNumberish[] = Array.from(msgBytes) + const msgHash = hash.computeHashOnElements(convertedMsg) + const result = ec.starkCurve.verify(signature, msgHash, walletAddress) + console.log('Result (boolean) =', result) + return result + } + + // public static isFullPubKeyRelatedToAccount() { + // return + // publicKey.publicKey == BigInt(encode.addHexPrefix(fullPublicKey.slice(4, 68))); + // } + + public static convertPrivKeyToPubKey(walletPrivateKey: Uint8Array): Uint8Array { + return ec.starkCurve.getPublicKey(walletPrivateKey, false) + } + + public static convertPubKeyToAddr(pubKey: Uint8Array): string { + return BitUtil.bytesToBase16(pubKey) + } + + public static convertPrivKeyToAddr(starkNetPrivateKey: Uint8Array): string { + const pubKey = StarkNetUtil.convertPrivKeyToPubKey(starkNetPrivateKey) + const addrStr = StarkNetUtil.convertPubKeyToAddr(pubKey) + return addrStr + } + + public static convertAddrToPubKey(starkNetAddress: string): Uint8Array { + return BitUtil.base16ToBytes(starkNetAddress) + } +} diff --git a/src/utils/strUtil.ts b/src/utils/strUtil.ts index d2cf4cd..50c3350 100644 --- a/src/utils/strUtil.ts +++ b/src/utils/strUtil.ts @@ -1,28 +1,247 @@ +import { BitUtil } from './bitUtil' + export default class StrUtil { - public static isEmpty(s: string | undefined): boolean { - return s == null || (typeof s === 'string' && s.length === 0); + public static replaceAll( + str: string, + find: string[], + replace: string[], + regexFlags: string + ): string { + let gFlag = false + + if (typeof str !== 'string') { + throw new TypeError('`str` parameter must be a string!') + } + + if (!Array.isArray(find)) { + throw new TypeError('`find` parameter must be an array!') + } + + if (!Array.isArray(replace)) { + throw new TypeError('`replace` parameter must be an array!') + } + + if (!find.length || !replace.length) { + throw new Error('`find` and `replace` parameters must not be empty!') + } + + if (find.length !== replace.length) { + throw new Error('`find` and `replace` parameters must be equal in length!') + } + + if (regexFlags) { + if (typeof regexFlags !== 'string') { + throw new TypeError('`regexFlags` parameter must be a string!') + } else if (~regexFlags.indexOf('g')) { + gFlag = true + } else { + regexFlags += 'g' + } + } else { + regexFlags = 'g' + } + + const done = [] + const joined = find.join(')|(') + const regex = new RegExp('(' + joined + ')', regexFlags) + + return str.replace(regex, (match, ...finds) => { + let replaced + + finds.some((found, index) => { + if (found !== undefined) { + if (gFlag) { + replaced = replace[index] + } else if (!~done.indexOf(found)) { + done.push(found) + replaced = replace[index] + } else { + replaced = found + } + + return true + } + }) + + return replaced + }) + } + + /** + * replaces MySql placeholders ? with Postre placehoslers $1 $2 $3 + * example: + * aaaa?bbbb?cccc? => aaaa$1bbbb$2cccc$3 + */ + public static replaceAllMySqlToPostre(s: string): string { + let cnt = 1 + return s.replace(/\?/g, function () { + return `$${cnt++}` + }) + } + + public static isEmpty(s: string): boolean { + if (s == null) { + return true + } + if (typeof s !== 'string') { + return false + } + return s.length === 0 + } + + public static hasSize(s: string, minSize: number | null, maxSize: number | null): boolean { + if (s == null || typeof s !== 'string') { + return false + } + const length = s.length + if (minSize !== null && length < minSize) { + return false + } + if (maxSize !== null && length > maxSize) { + return false + } + return true } public static isHex(s: string): boolean { if (StrUtil.isEmpty(s)) { - return false; + return false } - const pattern = /^[A-F0-9]+$/i; - return pattern.test(s); + const pattern = /^[A-F0-9]+$/i + const result = pattern.test(s) + return result } - public static getOrDefault( - s: string | undefined, - defaultValue: string, - ): string { - return StrUtil.isEmpty(s) ? defaultValue : (s ?? defaultValue); + /** + * Return s if this is not empty, defaultValue otherwise + * @param s + * @param defaultValue + */ + public static getOrDefault(s: string, defaultValue: string) { + return StrUtil.isEmpty(s) ? defaultValue : s } public static toStringDeep(obj: any): string { - return JSON.stringify(obj, null, 4); + return JSON.stringify(obj, null, 4) } + // https://ethereum.stackexchange.com/questions/2045/is-ethereum-wallet-address-case-sensitive public static normalizeEthAddress(addr: string): string { - return addr; + return addr + } + + public static fmtProtoBytes(obj: any): string { + if (typeof obj.serializeBinary === 'function') { + return StrUtil.fmt(obj.serializeBinary()) + } + } + + public static fmtProtoObj(obj: any): string { + if (typeof obj.toObject === 'function') { + return StrUtil.fmt(obj.toObject()) + } + } + + // write a good recurive format for every possible type + public static fmt(obj: any, visited = new WeakMap()): string { + if (obj === null) { + return 'null' + } + if (obj === undefined) { + return 'undef' + } + if (typeof obj === 'boolean') { + return '' + obj + } + if (typeof obj === 'bigint') { + return '' + obj.toString() + } + if (typeof obj === 'function' || typeof obj === 'symbol') { + return '?' + } + if (typeof obj === 'string') { + return "'" + obj + "'" + } + if (typeof obj === 'number') { + return '' + obj + } + if (typeof obj === 'object') { + if (visited.has(obj)) { + return '[Circular]' + } + try { + visited.set(obj, 0) + if (obj instanceof Date) { + return obj.toISOString() + } + if (obj instanceof RegExp) { + return obj.toString() + } + if (obj instanceof Error) { + return `Error:${obj.message}` + } + if (obj instanceof Uint8Array) { + return BitUtil.bytesToBase16(obj) + } + if (obj instanceof Buffer) { + return obj.toString('hex') + } + if (typeof obj.serializeBinary === 'function') { + const result = obj.serializeBinary() + if (result instanceof Uint8Array) { + return StrUtil.fmtProtoObj(obj) + } + } + if (Array.isArray(obj)) { + let result = '' + obj.forEach((val, index, array) => { + if (result.length != 0) { + result += ',' + } + result += StrUtil.fmt(val, visited) + }) + return '[' + result + ']' + } + if (obj instanceof Set) { + let result = '' + obj.forEach((value, value2, set) => { + if (result.length != 0) { + result += ',' + } + result += StrUtil.fmt(value, visited) + }) + return '[[' + result + ']]' + } + if (obj instanceof Map) { + let result = '' + obj.forEach((value: string, key: number) => { + if (result.length != 0) { + result += ',' + } + const fmtKey = StrUtil.fmt(key, visited) + const fmtValue = StrUtil.fmt(value, visited) + result += `${fmtKey}->${fmtValue}` + }) + return '[[' + result + ']]' + } + if (obj instanceof Object) { + let result = '' + for (const key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + if (result.length != 0) { + result += ',' + } + const value = obj[key] + const fmtValue = StrUtil.fmt(value, visited) + result += `${key}:${fmtValue}` + } + } + return '{' + result + '}' + } + } finally { + visited.delete(obj) + } + } + return '?' } } diff --git a/yarn.lock b/yarn.lock index de51740..b98758b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -295,6 +295,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.24.8" +"@babel/runtime@^7.25.0": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.9.tgz#65884fd6dc255a775402cc1d9811082918f4bf00" + integrity sha512-4zpTHZ9Cm6L9L+uIqghQX8ZXg8HKFcjYO3qHoO8zTmRm6HQUJ8SSJ+KRvbMBZn0EGVlT4DRYeQ/6hjlyXBh+Kg== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/template@^7.25.0", "@babel/template@^7.3.3": version "7.25.0" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.0.tgz#e733dc3134b4fede528c15bc95e89cb98c52592a" @@ -1163,13 +1170,20 @@ dependencies: "@noble/hashes" "1.4.0" -"@noble/curves@^1.4.0": +"@noble/curves@^1.4.0", "@noble/curves@^1.4.2": version "1.6.0" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.6.0.tgz#be5296ebcd5a1730fccea4786d420f87abfeb40b" integrity sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ== dependencies: "@noble/hashes" "1.5.0" +"@noble/curves@~1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.3.0.tgz#01be46da4fd195822dab821e72f71bf4aeec635e" + integrity sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA== + dependencies: + "@noble/hashes" "1.3.3" + "@noble/curves@~1.4.0": version "1.4.2" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" @@ -1177,6 +1191,11 @@ dependencies: "@noble/hashes" "1.4.0" +"@noble/hashes@1.3.3", "@noble/hashes@~1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" + integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== + "@noble/hashes@1.4.0", "@noble/hashes@~1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" @@ -1281,7 +1300,7 @@ resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== -"@scure/base@~1.1.6", "@scure/base@~1.1.8": +"@scure/base@~1.1.3", "@scure/base@~1.1.6", "@scure/base@~1.1.8": version "1.1.9" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1" integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg== @@ -1303,6 +1322,14 @@ "@noble/hashes" "~1.5.0" "@scure/base" "~1.1.8" +"@scure/starknet@~1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@scure/starknet/-/starknet-1.0.0.tgz#4419bc2fdf70f3dd6cb461d36c878c9ef4419f8c" + integrity sha512-o5J57zY0f+2IL/mq8+AYJJ4Xpc1fOtDhr+mFQKbHnYFmm3WQrC+8zj2HEgxak1a+x86mhmBC1Kq305KUpVf0wg== + dependencies: + "@noble/curves" "~1.3.0" + "@noble/hashes" "~1.3.3" + "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" @@ -1322,6 +1349,46 @@ dependencies: "@sinonjs/commons" "^3.0.0" +"@solana/buffer-layout@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz#b996235eaec15b1e0b5092a8ed6028df77fa6c15" + integrity sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA== + dependencies: + buffer "~6.0.3" + +"@solana/web3.js@^1.95.4": + version "1.95.4" + resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.95.4.tgz#771603f60d75cf7556ad867e1fd2efae32f9ad09" + integrity sha512-sdewnNEA42ZSMxqkzdwEWi6fDgzwtJHaQa5ndUGEJYtoOnM6X5cvPmjoTUp7/k7bRrVAxfBgDnvQQHD6yhlLYw== + dependencies: + "@babel/runtime" "^7.25.0" + "@noble/curves" "^1.4.2" + "@noble/hashes" "^1.4.0" + "@solana/buffer-layout" "^4.0.1" + agentkeepalive "^4.5.0" + bigint-buffer "^1.1.5" + bn.js "^5.2.1" + borsh "^0.7.0" + bs58 "^4.0.1" + buffer "6.0.3" + fast-stable-stringify "^1.0.0" + jayson "^4.1.1" + node-fetch "^2.7.0" + rpc-websockets "^9.0.2" + superstruct "^2.0.2" + +"@starknet-io/types-js@^0.7.7": + version "0.7.7" + resolved "https://registry.yarnpkg.com/@starknet-io/types-js/-/types-js-0.7.7.tgz#444be5e4e585ec6f599d42d3407280d98b2dfdf8" + integrity sha512-WLrpK7LIaIb8Ymxu6KF/6JkGW1sso988DweWu7p5QY/3y7waBIiPvzh27D9bX5KIJNRDyOoOVoHVEKYUYWZ/RQ== + +"@swc/helpers@^0.5.11": + version "0.5.13" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.13.tgz#33e63ff3cd0cade557672bd7888a39ce7d115a8c" + integrity sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w== + dependencies: + tslib "^2.4.0" + "@types/babel__core@^7.1.14": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" @@ -1360,6 +1427,13 @@ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.20.tgz#cb291577ed342ca92600430841a00329ba05cecc" integrity sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ== +"@types/connect@^3.4.33": + version "3.4.38" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== + dependencies: + "@types/node" "*" + "@types/estree@^1.0.5": version "1.0.6" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" @@ -1428,6 +1502,11 @@ dependencies: undici-types "~6.19.2" +"@types/node@^12.12.54": + version "12.20.55" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" + integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== + "@types/object-hash@^3.0.6": version "3.0.6" resolved "https://registry.yarnpkg.com/@types/object-hash/-/object-hash-3.0.6.tgz#25c052428199d374ef723b7b0ed44b5bfe1b3029" @@ -1443,6 +1522,11 @@ resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.5.tgz#74fef9ffbaa198eb8b588be029f38b00299caa2c" integrity sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw== +"@types/uuid@^8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" + integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== + "@types/winston@^2.4.4": version "2.4.4" resolved "https://registry.yarnpkg.com/@types/winston/-/winston-2.4.4.tgz#48cc744b7b42fad74b9a2e8490e0112bd9a3d08d" @@ -1450,6 +1534,20 @@ dependencies: winston "*" +"@types/ws@^7.4.4": + version "7.4.7" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" + integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww== + dependencies: + "@types/node" "*" + +"@types/ws@^8.2.2": + version "8.5.12" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.12.tgz#619475fe98f35ccca2a2f6c137702d85ec247b7e" + integrity sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ== + dependencies: + "@types/node" "*" + "@types/yargs-parser@*": version "21.0.3" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" @@ -1679,6 +1777,24 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== +JSONStream@^1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" + integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + +abi-wan-kanabi@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/abi-wan-kanabi/-/abi-wan-kanabi-2.2.3.tgz#d1c410325aac866f31f3d589279a87b341e5641f" + integrity sha512-JlqiAl9CPvTm5kKG0QXmVCWNWoC/XyRMOeT77cQlbxXWllgjf6SqUmaNqFon72C2o5OSZids+5FvLdsw6dvWaw== + dependencies: + ansicolors "^0.3.2" + cardinal "^2.1.1" + fs-extra "^10.0.0" + yargs "^17.7.2" + abitype@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.5.tgz#29d0daa3eea867ca90f7e4123144c1d1270774b6" @@ -1712,6 +1828,13 @@ aes-js@3.0.0: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== +agentkeepalive@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923" + integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew== + dependencies: + humanize-ms "^1.2.1" + ajv-formats@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" @@ -1800,6 +1923,11 @@ ansi-styles@^6.1.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== +ansicolors@^0.3.2, ansicolors@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" + integrity sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg== + anymatch@^3.0.3, anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" @@ -2005,6 +2133,13 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base-x@^3.0.2: + version "3.0.10" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.10.tgz#62de58653f8762b5d6f8d9fe30fa75f7b2585a75" + integrity sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ== + dependencies: + safe-buffer "^5.0.1" + base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -2020,11 +2155,25 @@ bech32@^2.0.0: resolved "https://registry.yarnpkg.com/bech32/-/bech32-2.0.0.tgz#078d3686535075c8c79709f054b1b226a133b355" integrity sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg== +bigint-buffer@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/bigint-buffer/-/bigint-buffer-1.1.5.tgz#d038f31c8e4534c1f8d0015209bf34b4fa6dd442" + integrity sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA== + dependencies: + bindings "^1.3.0" + binary-extensions@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== +bindings@^1.3.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + bl@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" @@ -2039,7 +2188,7 @@ bn.js@^4.11.9: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.2.1: +bn.js@^5.2.0, bn.js@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== @@ -2062,6 +2211,15 @@ body-parser@1.20.3: type-is "~1.6.18" unpipe "1.0.0" +borsh@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.7.0.tgz#6e9560d719d86d90dc589bca60ffc8a6c51fec2a" + integrity sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA== + dependencies: + bn.js "^5.2.0" + bs58 "^4.0.0" + text-encoding-utf-8 "^1.0.2" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2111,6 +2269,13 @@ bs-logger@^0.2.6: dependencies: fast-json-stable-stringify "2.x" +bs58@^4.0.0, bs58@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== + dependencies: + base-x "^3.0.2" + bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" @@ -2123,6 +2288,14 @@ buffer-from@^1.0.0, buffer-from@^1.1.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +buffer@6.0.3, buffer@^6.0.3, buffer@~6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" @@ -2131,6 +2304,13 @@ buffer@^5.5.0: base64-js "^1.3.1" ieee754 "^1.1.13" +bufferutil@^4.0.1: + version "4.0.8" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.8.tgz#1de6a71092d65d7766c4d8a522b261a6e787e8ea" + integrity sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw== + dependencies: + node-gyp-build "^4.3.0" + busboy@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" @@ -2174,6 +2354,14 @@ caniuse-lite@^1.0.30001663: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001664.tgz#d588d75c9682d3301956b05a3749652a80677df4" integrity sha512-AmE7k4dXiNKQipgn7a2xg558IRqPN3jMQY/rOsbxDhrd0tyChwbITBfiwtnqz8bi2M5mIWbxAYBvk7W7QBUS2g== +cardinal@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/cardinal/-/cardinal-2.1.1.tgz#7cc1055d822d212954d07b085dea251cc7bc5505" + integrity sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw== + dependencies: + ansicolors "~0.3.2" + redeyed "~2.1.0" + chai@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.1.tgz#f035d9792a22b481ead1c65908d14bb62ec1c82c" @@ -2376,7 +2564,7 @@ commander@4.1.1: resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== -commander@^2.20.0: +commander@^2.20.0, commander@^2.20.3: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -2491,6 +2679,11 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +crypto-js@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631" + integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q== + data-view-buffer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" @@ -2589,6 +2782,11 @@ define-properties@^1.2.0, define-properties@^1.2.1: has-property-descriptors "^1.0.0" object-keys "^1.1.1" +delay@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" + integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw== + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -2829,6 +3027,18 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +es6-promise@^4.0.3: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ== + dependencies: + es6-promise "^4.0.3" + escalade@^3.1.1, escalade@^3.1.2: version "3.2.0" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" @@ -2968,7 +3178,7 @@ espree@^9.6.0, espree@^9.6.1: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.4.1" -esprima@^4.0.0, esprima@^4.0.1: +esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== @@ -3043,6 +3253,11 @@ ethers@^5.7.2: "@ethersproject/web" "5.7.1" "@ethersproject/wordlists" "5.7.0" +eventemitter3@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + events@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" @@ -3125,6 +3340,11 @@ external-editor@^3.0.3, external-editor@^3.1.0: iconv-lite "^0.4.24" tmp "^0.0.33" +eyes@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" + integrity sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -3156,6 +3376,11 @@ fast-safe-stringify@2.1.1: resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== +fast-stable-stringify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz#5c5543462b22aeeefd36d05b34e51c78cb86d313" + integrity sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag== + fast-uri@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.2.tgz#d78b298cf70fd3b752fd951175a3da6a7b48f024" @@ -3180,6 +3405,14 @@ fecha@^4.2.0: resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== +fetch-cookie@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fetch-cookie/-/fetch-cookie-3.0.1.tgz#6a77f7495e1a639ae019db916a234db8c85d5963" + integrity sha512-ZGXe8Y5Z/1FWqQ9q/CrJhkUD73DyBU9VF0hBQmEO/wPHe4A9PKTjplFDLeFX8aOsYypZUcX5Ji/eByn3VCVO3Q== + dependencies: + set-cookie-parser "^2.4.8" + tough-cookie "^4.0.0" + figures@^3.0.0, figures@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" @@ -3194,6 +3427,11 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + filelist@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" @@ -3393,6 +3631,13 @@ get-package-type@^0.1.0: resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== +get-starknet-core@^4.0.0-next.3: + version "4.0.0" + resolved "https://registry.yarnpkg.com/get-starknet-core/-/get-starknet-core-4.0.0.tgz#9a81101b3a4e54e090f76492b566abaa3b5865c7" + integrity sha512-6pLmidQZkC3wZsrHY99grQHoGpuuXqkbSP65F8ov1/JsEI8DDLkhsAuLCKFzNOK56cJp+f1bWWfTJ57e9r5eqQ== + dependencies: + "@starknet-io/types-js" "^0.7.7" + get-stream@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" @@ -3602,6 +3847,13 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== + dependencies: + ms "^2.0.0" + husky@^9.1.4: version "9.1.6" resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.6.tgz#e23aa996b6203ab33534bdc82306b0cf2cb07d6c" @@ -3614,7 +3866,7 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -ieee754@^1.1.13: +ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -3902,6 +4154,19 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +isomorphic-fetch@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz#0267b005049046d2421207215d45d6a262b8b8b4" + integrity sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA== + dependencies: + node-fetch "^2.6.1" + whatwg-fetch "^3.4.1" + +isomorphic-ws@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" + integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== + isows@1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.4.tgz#810cd0d90cc4995c26395d2aa4cfa4037ebdf061" @@ -3984,6 +4249,24 @@ jake@^10.8.5: filelist "^1.0.4" minimatch "^3.1.2" +jayson@^4.1.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/jayson/-/jayson-4.1.2.tgz#443c26a8658703e0b2e881117b09395d88b6982e" + integrity sha512-5nzMWDHy6f+koZOuYsArh2AXs73NfWYVlFyJJuCedr93GpY+Ku8qq10ropSXVfHK+H0T6paA88ww+/dV+1fBNA== + dependencies: + "@types/connect" "^3.4.33" + "@types/node" "^12.12.54" + "@types/ws" "^7.4.4" + JSONStream "^1.3.5" + commander "^2.20.3" + delay "^5.0.0" + es6-promisify "^5.0.0" + eyes "^0.1.8" + isomorphic-ws "^4.0.1" + json-stringify-safe "^5.0.1" + uuid "^8.3.2" + ws "^7.5.10" + jest-changed-files@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" @@ -4406,6 +4689,11 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== +json-stringify-safe@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + json5@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" @@ -4437,6 +4725,11 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== + keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -4531,6 +4824,11 @@ long-timeout@0.1.1: resolved "https://registry.yarnpkg.com/long-timeout/-/long-timeout-0.1.1.tgz#9721d788b47e0bcb5a24c2e2bee1a0da55dab514" integrity sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w== +lossless-json@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/lossless-json/-/lossless-json-4.0.2.tgz#f00c52815805d1421930a87e2670e27350958a3f" + integrity sha512-+z0EaLi2UcWi8MZRxA5iTb6m4Ys4E80uftGY+yG5KNFJb5EceQXOhdW/pWJZ8m97s26u7yZZAYMcKWNztSZssA== + loupe@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.1.tgz#71d038d59007d890e3247c5db97c1ec5a92edc54" @@ -4722,7 +5020,7 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== -ms@2.1.3, ms@^2.1.1, ms@^2.1.3: +ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -4777,13 +5075,18 @@ node-emoji@1.11.0: dependencies: lodash "^4.17.21" -node-fetch@^2.6.1: +node-fetch@^2.6.1, node-fetch@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" +node-gyp-build@^4.3.0: + version "4.8.2" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.2.tgz#4f802b71c1ab2ca16af830e6c1ea7dd1ad9496fa" + integrity sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -4971,6 +5274,11 @@ package-json-from-dist@^1.0.0: resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz#e501cd3094b278495eb4258d4c9f6d5ac3019f00" integrity sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw== +pako@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" + integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -5132,7 +5440,12 @@ proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -punycode@^2.1.0: +psl@^1.1.33: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +punycode@^2.1.0, punycode@^2.1.1: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== @@ -5149,6 +5462,11 @@ qs@6.13.0: dependencies: side-channel "^1.0.6" +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -5210,11 +5528,23 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +redeyed@~2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/redeyed/-/redeyed-2.1.1.tgz#8984b5815d99cb220469c99eeeffe38913e6cc0b" + integrity sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ== + dependencies: + esprima "~4.0.0" + reflect-metadata@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.2.tgz#400c845b6cba87a21f2c65c4aeb158f4fa4d9c5b" integrity sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q== +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + regexp.prototype.flags@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" @@ -5240,6 +5570,11 @@ require-from-string@^2.0.2: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -5291,6 +5626,22 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +rpc-websockets@^9.0.2: + version "9.0.4" + resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-9.0.4.tgz#9d8ee82533b5d1e13d9ded729e3e38d0d8fa083f" + integrity sha512-yWZWN0M+bivtoNLnaDbtny4XchdAIF5Q4g/ZsC5UC61Ckbp0QczwO8fg44rV3uYmY4WHd+EZQbn90W1d8ojzqQ== + dependencies: + "@swc/helpers" "^0.5.11" + "@types/uuid" "^8.3.4" + "@types/ws" "^8.2.2" + buffer "^6.0.3" + eventemitter3 "^5.0.1" + uuid "^8.3.2" + ws "^8.5.0" + optionalDependencies: + bufferutil "^4.0.1" + utf-8-validate "^5.0.2" + run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" @@ -5325,7 +5676,7 @@ safe-array-concat@^1.1.2: has-symbols "^1.0.3" isarray "^2.0.5" -safe-buffer@5.2.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -5414,6 +5765,11 @@ serve-static@1.16.2: parseurl "~1.3.3" send "0.19.0" +set-cookie-parser@^2.4.8: + version "2.7.1" + resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz#3016f150072202dfbe90fadee053573cc89d2943" + integrity sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ== + set-function-length@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" @@ -5538,6 +5894,30 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" +"starknet-types-07@npm:@starknet-io/types-js@^0.7.7": + version "0.7.7" + resolved "https://registry.yarnpkg.com/@starknet-io/types-js/-/types-js-0.7.7.tgz#444be5e4e585ec6f599d42d3407280d98b2dfdf8" + integrity sha512-WLrpK7LIaIb8Ymxu6KF/6JkGW1sso988DweWu7p5QY/3y7waBIiPvzh27D9bX5KIJNRDyOoOVoHVEKYUYWZ/RQ== + +starknet@^6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/starknet/-/starknet-6.11.0.tgz#5d7e868e913777e9bf64323e59ed8be86437f291" + integrity sha512-u50KrGDi9fbu1Ogu7ynwF/tSeFlp3mzOg1/Y5x50tYFICImo3OfY4lOz9OtYDk404HK4eUujKkhov9tG7GAKlg== + dependencies: + "@noble/curves" "~1.4.0" + "@noble/hashes" "^1.4.0" + "@scure/base" "~1.1.3" + "@scure/starknet" "~1.0.0" + abi-wan-kanabi "^2.2.2" + fetch-cookie "^3.0.0" + get-starknet-core "^4.0.0-next.3" + isomorphic-fetch "^3.0.0" + lossless-json "^4.0.1" + pako "^2.0.4" + starknet-types-07 "npm:@starknet-io/types-js@^0.7.7" + ts-mixer "^6.0.3" + url-join "^4.0.1" + statuses@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" @@ -5556,7 +5936,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -5616,7 +6005,14 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -5650,6 +6046,11 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +superstruct@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-2.0.2.tgz#3f6d32fbdc11c357deff127d591a39b996300c54" + integrity sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A== + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -5728,6 +6129,11 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +text-encoding-utf-8@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13" + integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg== + text-hex@1.0.x: version "1.0.0" resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" @@ -5738,7 +6144,7 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== -through@^2.3.6: +"through@>=2.2.7 <3", through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -5772,6 +6178,16 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +tough-cookie@^4.0.0: + version "4.1.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" + integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -5812,6 +6228,11 @@ ts-luxon@^5.0.7-beta.0: resolved "https://registry.yarnpkg.com/ts-luxon/-/ts-luxon-5.0.7-beta.0.tgz#dcc11fa910df58efff3391965ca03ae50fe23338" integrity sha512-mmBCXl8MXqeZ24pKcdORJShvgSNq9Eb7MD5++w+/gjERu8yJn02mhpDf/gDK9YAZiWuppRLivgPV1ipRjlFuvg== +ts-mixer@^6.0.3: + version "6.0.4" + resolved "https://registry.yarnpkg.com/ts-mixer/-/ts-mixer-6.0.4.tgz#1da39ceabc09d947a82140d9f09db0f84919ca28" + integrity sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA== + ts-mocha@^10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-10.0.0.tgz#41a8d099ac90dbbc64b06976c5025ffaebc53cb9" @@ -5875,6 +6296,16 @@ tslib@2.7.0, tslib@^2.1.0, tslib@^2.3.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== +tslib@^2.4.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.0.tgz#d124c86c3c05a40a91e6fdea4021bd31d377971b" + integrity sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA== + +tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -6000,6 +6431,11 @@ undici-types@~6.19.2: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== +universalify@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== + universalify@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" @@ -6025,6 +6461,26 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +url-join@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7" + integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA== + +url-parse@^1.5.3: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +utf-8-validate@^5.0.2: + version "5.0.10" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" + integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== + dependencies: + node-gyp-build "^4.3.0" + util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -6045,6 +6501,11 @@ uuid@^10.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294" integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ== +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + v8-to-istanbul@^9.0.1: version "9.3.0" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" @@ -6148,6 +6609,11 @@ webpack@5.94.0: watchpack "^2.4.1" webpack-sources "^3.2.3" +whatwg-fetch@^3.4.1: + version "3.6.20" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70" + integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg== + whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" @@ -6221,8 +6687,7 @@ workerpool@^6.5.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: - name wrap-ansi-cjs +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -6240,6 +6705,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -6272,7 +6746,12 @@ ws@8.17.1: resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== -ws@^8.18.0: +ws@^7.5.10: + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== + +ws@^8.18.0, ws@^8.5.0: version "8.18.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== @@ -6325,7 +6804,7 @@ yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.3.1: +yargs@^17.3.1, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== From 4872817ddec2a7f5f4ec4eeccc8afb7c3ce47202 Mon Sep 17 00:00:00 2001 From: Ashis Date: Wed, 23 Oct 2024 16:52:34 +0530 Subject: [PATCH 3/5] fix: implemented block validation --- src/modules/archive/archive-node.service.ts | 61 +++++++++++++-------- src/utils/chainUtil.ts | 1 + src/utils/tuple.ts | 1 + 3 files changed, 41 insertions(+), 22 deletions(-) create mode 100644 src/utils/tuple.ts diff --git a/src/modules/archive/archive-node.service.ts b/src/modules/archive/archive-node.service.ts index a22ba8c..c11208a 100644 --- a/src/modules/archive/archive-node.service.ts +++ b/src/modules/archive/archive-node.service.ts @@ -5,7 +5,24 @@ import { PrismaService } from '../../prisma/prisma.service'; import { ObjectHasher } from '../../utils/objectHasher'; import { ValidatorContractState } from '../validator/validator-contract-state.service'; import { BlockUtil } from '../../utils/blockUtil'; - +import { + InputJsonValue, + InputJsonObject, +} from '@prisma/client/runtime/library'; + +type Transaction = { + ts?: bigint | number; + txn_hash: string; + block_hash: string; + category: string; + sender: string; + status: string; + from: string; + recipients: InputJsonValue; + data: Buffer; + data_as_json: InputJsonValue; + sig: string; +}; @Injectable() export class ArchiveNodeService implements Consumer { constructor(private readonly prisma: PrismaService) {} @@ -18,6 +35,22 @@ export class ArchiveNodeService implements Consumer { const deserializedBlock = Block.deserializeBinary(bytes); const block = deserializedBlock.toObject(); + // Block validation // + // validate the hash + const calculatedHash = BlockUtil.hashBlockAsHex(bytes); + if (calculatedHash != item.object_hash) { + throw new Error( + 'received item hash= , ' + + item.object_hash + + 'which differs from calculatedHash=, ' + + calculatedHash + + 'ignoring the block because producer calculated the hash incorrectly', + ); + } + // validate the signature + if (!(await this.validateBlock(deserializedBlock))) { + throw new Error('Block validation failed'); + } // Extract block hash from the block const blockHash = this.getBlockHash(block); if (await this.isBlockAlreadyStored(blockHash)) { @@ -43,23 +76,6 @@ export class ArchiveNodeService implements Consumer { console.log('All transactions already exist, skipping block insert.'); return true; } - - // Block validation // - // validate the hash - const calculatedHash = BlockUtil.hashBlockAsHex(bytes); - if (calculatedHash != item.object_hash) { - throw new Error( - 'received item hash= , ' + - item.object_hash + - 'which differs from calculatedHash=, ' + - calculatedHash + - 'ignoring the block because producer calculated the hash incorrectly', - ); - } - // validate the signature - if (!(await this.validateBlock(deserializedBlock))) { - throw new Error('Block validation failed'); - } // Insert block into the database await this.prisma.block.create({ data: blockData }); @@ -102,7 +118,9 @@ export class ArchiveNodeService implements Consumer { return block !== null; } - private recursivelyConvertToJSON(obj: Uint8Array | Array | object): unknown { + private recursivelyConvertToJSON( + obj: Uint8Array | Array | object, + ): InputJsonObject | InputJsonValue { if (obj instanceof Uint8Array) { // Convert Uint8Array to a base64 string return Buffer.from(obj).toString('base64'); @@ -117,7 +135,7 @@ export class ArchiveNodeService implements Consumer { for (const key in obj) { convertedObj[key] = this.recursivelyConvertToJSON(obj[key]); } - return convertedObj; + return convertedObj as InputJsonObject; } return obj; @@ -128,7 +146,7 @@ export class ArchiveNodeService implements Consumer { txObjList: Block.AsObject['txobjList'], blockHash: string, blockTs: number, - ): Promise { + ): Promise { const transactionsData = []; for (const txObj of txObjList) { @@ -161,7 +179,6 @@ export class ArchiveNodeService implements Consumer { data_as_json: this.recursivelyConvertToJSON(transaction), // Convert to JSON-compatible format sig: txObj.tx?.signature, }; - transactionsData.push(txData); } diff --git a/src/utils/chainUtil.ts b/src/utils/chainUtil.ts index 8c4f10e..c725930 100644 --- a/src/utils/chainUtil.ts +++ b/src/utils/chainUtil.ts @@ -1,4 +1,5 @@ import StrUtil from './strUtil' +import { Tuple } from './tuple' export class ChainUtil { static readonly ADDR_MAX = 64 diff --git a/src/utils/tuple.ts b/src/utils/tuple.ts new file mode 100644 index 0000000..dd0dd7a --- /dev/null +++ b/src/utils/tuple.ts @@ -0,0 +1 @@ +export type Tuple = [A, undefined?] | [undefined, B] From 79420482c16194b798a3c3c6a470061b7fffc973 Mon Sep 17 00:00:00 2001 From: Ashis Date: Wed, 23 Oct 2024 18:06:30 +0530 Subject: [PATCH 4/5] fix: fix dependency issues --- package.json | 2 ++ src/modules/archive/archive-node.service.ts | 10 ++++++++-- src/utils/bitUtil.ts | 1 - yarn.lock | 22 ++++++++++++++++++++- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 5ed7013..35c7ceb 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,8 @@ "@prisma/client": "^5.19.1", "@pushprotocol/node-core": "^0.0.8", "@solana/web3.js": "^1.95.4", + "@types/bs58": "^4.0.4", + "bs58": "^6.0.0", "crypto-js": "^4.2.0", "ethers": "^5.7.2", "google-protobuf": "^3.21.4", diff --git a/src/modules/archive/archive-node.service.ts b/src/modules/archive/archive-node.service.ts index c11208a..1f200bd 100644 --- a/src/modules/archive/archive-node.service.ts +++ b/src/modules/archive/archive-node.service.ts @@ -25,9 +25,15 @@ type Transaction = { }; @Injectable() export class ArchiveNodeService implements Consumer { - constructor(private readonly prisma: PrismaService) {} + valContractState: ValidatorContractState = new ValidatorContractState(); + + async postConstruct() { + await this.valContractState.onModuleInit(); + } + constructor(private readonly prisma: PrismaService) { + this.postConstruct() + } - valContractState: ValidatorContractState; public async accept(item: QItem): Promise { try { // Deserialize the block data diff --git a/src/utils/bitUtil.ts b/src/utils/bitUtil.ts index 2ea65a1..8c3988a 100644 --- a/src/utils/bitUtil.ts +++ b/src/utils/bitUtil.ts @@ -1,4 +1,3 @@ -// @ts-ignore import bs58 from 'bs58' import { Coll } from './coll' diff --git a/yarn.lock b/yarn.lock index b98758b..3ca6f44 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1422,6 +1422,14 @@ dependencies: "@babel/types" "^7.20.7" +"@types/bs58@^4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@types/bs58/-/bs58-4.0.4.tgz#49fbcb0c7db5f7cea26f0e0f61dc4a41a2445aab" + integrity sha512-0IEpMFXXQi2zXaXl9GJ3sRwQo0uEkD+yFOv+FnAU5lkPtcu6h61xb7jc2CFPEZ5BUOaiP13ThuGc9HD4R8lR5g== + dependencies: + "@types/node" "*" + base-x "^3.0.6" + "@types/chai@^4.3.17": version "4.3.20" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.20.tgz#cb291577ed342ca92600430841a00329ba05cecc" @@ -2133,13 +2141,18 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base-x@^3.0.2: +base-x@^3.0.2, base-x@^3.0.6: version "3.0.10" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.10.tgz#62de58653f8762b5d6f8d9fe30fa75f7b2585a75" integrity sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ== dependencies: safe-buffer "^5.0.1" +base-x@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-5.0.0.tgz#6d835ceae379130e1a4cb846a70ac4746f28ea9b" + integrity sha512-sMW3VGSX1QWVFA6l8U62MLKz29rRfpTlYdCqLdpLo1/Yd4zZwSbnUaDfciIAowAqvq7YFnWq9hrhdg1KYgc1lQ== + base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" @@ -2276,6 +2289,13 @@ bs58@^4.0.0, bs58@^4.0.1: dependencies: base-x "^3.0.2" +bs58@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-6.0.0.tgz#a2cda0130558535dd281a2f8697df79caaf425d8" + integrity sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw== + dependencies: + base-x "^5.0.0" + bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" From 7dc44df650acb6756cf7ad8b61e67b51dd125c89 Mon Sep 17 00:00:00 2001 From: Ashis Date: Thu, 24 Oct 2024 12:56:23 +0530 Subject: [PATCH 5/5] fix: updated the new validation logic --- package.json | 2 + src/utils/bitUtil.ts | 83 ++++-- src/utils/blockUtil.ts | 572 ++++++++++++++++++--------------------- src/utils/pushSdkUtil.ts | 139 ++++++++++ yarn.lock | 30 +- 5 files changed, 492 insertions(+), 334 deletions(-) create mode 100644 src/utils/pushSdkUtil.ts diff --git a/package.json b/package.json index 35c7ceb..87d6494 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "typescript-eslint": "^8.0.1" }, "dependencies": { + "@ethersproject/transactions": "^5.7.0", "@klerick/nestjs-json-rpc": "^1.0.0", "@nestjs/common": "^10.3.10", "@nestjs/config": "^3.2.3", @@ -78,6 +79,7 @@ "ts-luxon": "^5.0.7-beta.0", "tweetnacl": "^1.0.3", "typedi": "^0.10.0", + "util": "^0.12.5", "winston": "^3.14.2", "ws": "^8.18.0" } diff --git a/src/utils/bitUtil.ts b/src/utils/bitUtil.ts index 8c3988a..010e648 100644 --- a/src/utils/bitUtil.ts +++ b/src/utils/bitUtil.ts @@ -1,6 +1,7 @@ -import bs58 from 'bs58' - -import { Coll } from './coll' +import {Coll} from './coll'; +// @ts-ignore +import bs58 from 'bs58'; +import {Check} from "./check"; // bytes (as hex numbers) = 0x41 0x41 0x42 0x42 // Uint8Array (as decimal numbers) = 65 65 66 66 @@ -66,51 +67,101 @@ export class BitUtil { return result } + public static base16ToBytes(base16String: string): Uint8Array { - return Uint8Array.from(Buffer.from(base16String, 'hex')) + if(base16String.length % 2 == 1) { + base16String = '0' + base16String; + } + const result = Uint8Array.from(Buffer.from(base16String, 'hex')); + const conversionHadNoErrors = base16String.length == 0 || result.length == base16String.length / 2; + Check.isTrue(conversionHadNoErrors, 'failed to convert hex string ' + base16String); + return result; } public static bytesToBase16(arr: Uint8Array): string { - return Buffer.from(arr).toString('hex') + return Buffer.from(arr).toString('hex'); } public static bytesBufToBase16(buf: Buffer): string { - return buf.toString('hex') + return buf.toString('hex'); } public static base64ToString(base64String: string): string { - return Buffer.from(base64String, 'base64').toString('utf8') + return Buffer.from(base64String, 'base64').toString('utf8'); } public static bytesToBase64(bytes: Uint8Array): string { - return Buffer.from(bytes).toString('base64') + return Buffer.from(bytes).toString('base64'); } public static base64ToBytes(base64String: string): Uint8Array { - return new Uint8Array(Buffer.from(base64String, 'base64')) + return new Uint8Array(Buffer.from(base64String, 'base64')); } public static bytesUtfToString(bytes: Uint8Array): string { - return Buffer.from(bytes).toString('utf8') + return Buffer.from(bytes).toString('utf8'); } public static stringToBytesUtf(str: string): Uint8Array { - return new Uint8Array(Buffer.from(str, 'utf-8')) + return new Uint8Array(Buffer.from(str, 'utf-8')); } public static stringToBase64(str: string): string { - return Buffer.from(str, 'utf-8').toString('base64') + return Buffer.from(str, 'utf-8').toString('base64'); } public static base64ToBase16(base64String: string): string { - return Buffer.from(base64String, 'base64').toString('hex') + return Buffer.from(base64String, 'base64').toString('hex'); } public static base58ToBytes(base58String: string): Uint8Array { - return bs58.decode(base58String) + return bs58.decode(base58String); } public static bytesToBase58(bytes: Uint8Array): string { - return bs58.encode(bytes) + return bs58.encode(bytes); + } + + static asciis = {_0: 48, _9: 57, _A: 65, _F: 70, _a: 97, _f: 102} as const; + + public static asciiToBase16(char: number): number | undefined { + const a = this.asciis; + if (char >= a._0 && char <= a._9) return char - a._0; + if (char >= a._A && char <= a._F) return char - (a._A - 10); + if (char >= a._a && char <= a._f) return char - (a._a - 10); + return; + } + + public static hex0xToBytes(hexString: string): Uint8Array { + hexString = this.hex0xRemove(hexString); + const result = this.base16ToBytes(hexString); + // there is no way to check for illegal characters without iterating over each char + // and Buffer silently ignores invalid chars + // so we will simply compare the output length; it should be 1 byte per 2 chars of input! + const conversionHadNoErrors = result.length == hexString.length / 2; + Check.isTrue(hexString.length == 0 || conversionHadNoErrors, 'hex string contains invalid chars'); + return result; } -} + + public static hex0xRemove(hexString: string) { + Check.notNull(hexString, 'hex string is null'); + Check.isTrue(typeof hexString === 'string', 'string is expected'); + if (hexString.length >= 2 && (hexString.startsWith('0x') || hexString.startsWith('0X'))) { + hexString = hexString.substring(2); + } + if (hexString.length % 2 == 1) { + hexString = '0' + hexString; + } + return hexString.toLowerCase(); + } + + public static hex0xAppend(hexString: string) { + Check.notNull(hexString, 'hex string is null'); + Check.isTrue(typeof hexString === 'string', 'string is expected'); + if (hexString.length >= 2 && (hexString.startsWith('0x') || hexString.startsWith('0X'))) { + return hexString; + } + return '0x' + hexString; + } + +} \ No newline at end of file diff --git a/src/utils/blockUtil.ts b/src/utils/blockUtil.ts index c1d0a5d..d79fde4 100644 --- a/src/utils/blockUtil.ts +++ b/src/utils/blockUtil.ts @@ -24,134 +24,135 @@ import { SolUtil } from './solUtil' import { StarkNetUtil } from './starkNetUtil' import StrUtil from './strUtil' import { WinstonUtil } from './winstonUtil' +import { PushSdkUtil } from './pushSdkUtil' export class BlockUtil { - public static readonly log: Logger = WinstonUtil.newLog(BlockUtil) + public static readonly log: Logger = WinstonUtil.newLog(BlockUtil); // max serialized tx size - public static readonly MAX_TRANSACTION_SIZE_BYTES = EnvLoader.getPropertyAsNumber( - 'MAX_TRANSACTION_SIZE_BYTES', - 1000000 - ) + public static readonly MAX_TRANSACTION_SIZE_BYTES = EnvLoader.getPropertyAsNumber('MAX_TRANSACTION_SIZE_BYTES', 1000000); // max total tx data in a block , // when reached block would stop accepting transactions - public static readonly MAX_TOTAL_TRANSACTION_SIZE_BYTES = EnvLoader.getPropertyAsNumber( - 'MAX_TOTAL_TRANSACTION_SIZE_BYTES', - 10 * 1000000 - ) + public static readonly MAX_TOTAL_TRANSACTION_SIZE_BYTES = EnvLoader.getPropertyAsNumber('MAX_TOTAL_TRANSACTION_SIZE_BYTES', 10 * 1000000); // max total tx count // when reached block would stop accepting transactions - public static readonly MAX_TRANSACTIONS_PER_BLOCK = EnvLoader.getPropertyAsNumber( - 'MAX_TRANSACTION_PER_BLOCK', - 1000 - ) + public static readonly MAX_TRANSACTIONS_PER_BLOCK = EnvLoader.getPropertyAsNumber('MAX_TRANSACTION_PER_BLOCK', 1000); // blocks older than this would get rejected by attestors // note: attestor should have an up-to-date clock time for this (!) - public static ATTESTOR_MAX_BLOCK_AGE_SECONDS = EnvLoader.getPropertyAsNumber( - 'MAX_BLOCK_AGE_SECONDS', - 0 - ) + public static ATTESTOR_MAX_BLOCK_AGE_SECONDS = EnvLoader.getPropertyAsNumber('MAX_BLOCK_AGE_SECONDS', 0); // we will cache incomplete blocks for this amount of seconds // attestSignatures will stop working after this time - public static readonly MAX_BLOCK_ASSEMBLY_TIME_SECONDS = EnvLoader.getPropertyAsNumber( - 'MAX_BLOCK_ASSEMBLY_TIME_SECONDS', - 60 - ) + public static readonly MAX_BLOCK_ASSEMBLY_TIME_SECONDS = EnvLoader.getPropertyAsNumber('MAX_BLOCK_ASSEMBLY_TIME_SECONDS', 60); - public static readonly VALID_VALIDATOR_VOTES: Set = new Set([1]) - public static readonly VALID_ATTESTOR_VOTES: Set = new Set([1, 2]) - public static readonly ATT_TOKEN_PREFIX = 'AT1' - public static readonly VAL_TOKEN_PREFIX = 'VT1' + public static readonly VALID_VALIDATOR_VOTES: Set = new Set([1]); + public static readonly VALID_ATTESTOR_VOTES: Set = new Set([1, 2]); + public static readonly ATT_TOKEN_PREFIX = 'AT1'; + public static readonly VAL_TOKEN_PREFIX = 'VT1'; public static parseTx(txRaw: Uint8Array): Transaction { if (txRaw == null || txRaw.length > BlockUtil.MAX_TRANSACTION_SIZE_BYTES) { - throw new Error('tx size is too big') + throw new Error('tx size is too big'); } - const tx = Transaction.deserializeBinary(txRaw) - return tx + const tx = Transaction.deserializeBinary(txRaw); + return tx; } public static parseBlock(bRaw: Uint8Array): Block { - const b = Block.deserializeBinary(bRaw) - return b + const b = Block.deserializeBinary(bRaw); + return b; } public static hashTxAsHex(txRaw: Uint8Array): string { - return BitUtil.bytesToBase16(BlockUtil.hashTx(txRaw)) + return BitUtil.bytesToBase16(BlockUtil.hashTx(txRaw)); } private static hashTx(txRaw: Uint8Array) { - return HashUtil.sha256AsBytes(txRaw) + return HashUtil.sha256AsBytes(txRaw); } public static hashBlockAsHex(blockRaw: Uint8Array): string { - return BitUtil.bytesToBase16(HashUtil.sha256AsBytes(blockRaw)) + return BitUtil.bytesToBase16(HashUtil.sha256AsBytes(blockRaw)); } // when the block has not been signed, we still need a valid immutable hash based on tx data // this is used to cache the block contents // Deprecated public static hashBlockIncomplete(blockObj: Block): string { - const txHashes: Uint8Array[] = [] + const txHashes: Uint8Array[] = []; for (const txObj of blockObj.getTxobjList()) { - const tx = txObj.getTx() - const txHash = BlockUtil.hashTx(tx.serializeBinary()) - txHashes.push(txHash) + const tx = txObj.getTx(); + const txHash = BlockUtil.hashTx(tx.serializeBinary()); + txHashes.push(txHash); } - return BitUtil.bytesToBase16(HashUtil.sha256ArrayAsBytes(txHashes)) + return BitUtil.bytesToBase16(HashUtil.sha256ArrayAsBytes(txHashes)); } public static blockToJson(block: Block) { - return JSON.stringify(block.toObject()) + return JSON.stringify(block.toObject()); } public static transactionToJson(tx: Transaction) { - return JSON.stringify(tx.toObject()) + return JSON.stringify(tx.toObject()); } public static blockToBase16(block: Block) { - return BitUtil.bytesToBase16(block.serializeBinary()) + return BitUtil.bytesToBase16(block.serializeBinary()); } public static transactionToBase16(tx: Transaction) { - return BitUtil.bytesToBase16(tx.serializeBinary()) + return BitUtil.bytesToBase16(tx.serializeBinary()); } - // 1) try to get first byte from caip address - // eip155:5:0xD8634C39BBFd4033c0d3289C4515275102423681 -> d8 -> 216 - // and use it as shard - // 2) take sha256(addr) -> - // shard count is a smart contract constant; normally it should never change - // lets read this value from a contract + public static calculateAffectedShard(walletInCaip: string, shardCount: number): number | null { if (StrUtil.isEmpty(walletInCaip)) { return null } - const [caip, err] = ChainUtil.parseCaipAddress(walletInCaip) + const [caip, err] = ChainUtil.parseCaipAddress(walletInCaip); if (err != null) { - throw new Error('invalid caip address:' + err) + throw new Error('invalid caip address:' + err); } - if (!(caip != null && !StrUtil.isEmpty(caip.addr) && caip.addr.length > 4)) { - return null + if ( + !(caip != null && + !StrUtil.isEmpty(caip.addr) && + caip.addr.length > 4) + ) { + return null; } - const addrWithoutPrefix = !caip.addr.startsWith('0x') ? caip.addr : caip.addr.substring(2) - const sha = HashUtil.sha256AsBytesEx(BitUtil.stringToBytesUtf(addrWithoutPrefix)) - const shardId = sha[0] + const addrWithoutPrefix = !caip.addr.startsWith('0x') ? caip.addr : caip.addr.substring(2); + const sha = HashUtil.sha256AsBytesEx(BitUtil.stringToBytesUtf(addrWithoutPrefix)); + const shardId = sha[0]; Check.notNull(shardId) Check.isTrue(shardId >= 0 && shardId <= 255 && NumUtil.isRoundedInteger(shardId)) Check.isTrue(shardCount >= 1) - return shardId % shardCount + return shardId % shardCount; + } + + static calculateAffectedShardsTx(tx: Transaction, shardCount: number, shards = new Set()): Set { + const category = tx.getCategory() + if (category === 'INIT_DID') { + return shards; + } + const senderAndRecipients = [tx.getSender(), ...tx.getRecipientsList()]; + for (const wallet of senderAndRecipients) { + const shardId = this.calculateAffectedShard(wallet, shardCount) + if (shardId == null) { + continue + } + shards.add(shardId); + } + return shards; } /** * Evaluates all messageBlock target recipients (normally these are addresses) * for every included packet * - * And for every recipient finds which shard will host this address + * And for every tx finds which shard will host this address * * @param block * @param shardCount total amount of shards; see smart contract for this value @@ -160,439 +161,378 @@ export class BlockUtil { static calculateAffectedShards(block: Block, shardCount: number): Set { const shards = new Set() for (const txObj of block.getTxobjList()) { - const senderAndRecipients = [txObj.getTx().getSender(), ...txObj.getTx().getRecipientsList()] - for (const wallet of senderAndRecipients) { - const shardId = this.calculateAffectedShard(wallet, shardCount) - if (shardId == null) { - continue - } - shards.add(shardId) - } + const tx = txObj.getTx(); + this.calculateAffectedShardsTx(tx, shardCount, shards); } - return shards + return shards; } public static checkValidatorTokenFormat(apiTokenBytes: Uint8Array): CheckR { const token = BitUtil.bytesUtfToString(apiTokenBytes) if (StrUtil.isEmpty(token) || !token.startsWith(BlockUtil.VAL_TOKEN_PREFIX)) { - return CheckR.failWithText( - `invalid attestor token; ${StrUtil.fmt(apiTokenBytes)} should start with ${BlockUtil.ATT_TOKEN_PREFIX}` - ) + return CheckR.failWithText(`invalid attestor token; ${StrUtil.fmt(apiTokenBytes)} should start with ${BlockUtil.ATT_TOKEN_PREFIX}`); } - return CheckR.ok() + return CheckR.ok(); } public static checkAttestTokenFormat(attestorTokenBytes: Uint8Array): CheckR { const token = BitUtil.bytesUtfToString(attestorTokenBytes) if (StrUtil.isEmpty(token) || !token.startsWith(BlockUtil.ATT_TOKEN_PREFIX)) { - return CheckR.failWithText( - `invalid attestor token; ${StrUtil.fmt(attestorTokenBytes)} should start with ${BlockUtil.ATT_TOKEN_PREFIX}` - ) + return CheckR.failWithText(`invalid attestor token; ${StrUtil.fmt(attestorTokenBytes)} should start with ${BlockUtil.ATT_TOKEN_PREFIX}`); } - return CheckR.ok() + return CheckR.ok(); + } + + // for tests + // signs InitDid(has masterPublicKey field) with the same private key + public static async signInitDid(tx: Transaction, evmWallet: Wallet) { + Check.isTrue(ArrayUtil.isEmpty(tx.getSignature_asU8()), ' clear the signature field first, signature is:' + tx.getSignature()); + Check.isTrue(tx.getCategory() == 'INIT_DID', 'not an INIT_DID transaction'); + const initDid = InitDid.deserializeBinary(tx.getData_asU8()); + Check.isTrue(initDid.getMasterpubkey() == evmWallet.publicKey, + `masterPublicKey ${initDid.getMasterpubkey()} + does not match evmWallet publicKey ${evmWallet.publicKey}`); + const tmpBytes = PushSdkUtil.messageBytesToHashBytes(tx.serializeBinary()); + const sig = await EthUtil.signBytes(evmWallet, tmpBytes); + tx.setSignature(sig); } + // for tests public static async signTxEVM(tx: Transaction, evmWallet: Wallet) { - Check.isTrue( - ArrayUtil.isEmpty(tx.getSignature_asU8()), - ' clear the signature field first, signature is:' + tx.getSignature() - ) - const tmpBytes = tx.serializeBinary() - const sig = await EthUtil.signBytes(evmWallet, tmpBytes) - tx.setSignature(sig) + Check.isTrue(ArrayUtil.isEmpty(tx.getSignature_asU8()), ' clear the signature field first, signature is:' + tx.getSignature()); + const tmpBytes = PushSdkUtil.messageBytesToHashBytes(tx.serializeBinary()); + const sig = await EthUtil.signBytes(evmWallet, tmpBytes); + tx.setSignature(sig); } + // for tests public static async signTxSolana(tx: Transaction, solanaPrivateKey: Uint8Array) { - Check.isTrue( - ArrayUtil.isEmpty(tx.getSignature_asU8()), - ' clear the signature field first, signature is:' + tx.getSignature() - ) - const tmpBytes = tx.serializeBinary() - const sig = SolUtil.signBytes(solanaPrivateKey, tmpBytes) - tx.setSignature(sig) + Check.isTrue(ArrayUtil.isEmpty(tx.getSignature_asU8()), ' clear the signature field first, signature is:' + tx.getSignature()); + const tmpBytes = PushSdkUtil.messageBytesToHashBytes(tx.serializeBinary()); + const sig = SolUtil.signBytes(solanaPrivateKey, tmpBytes); + tx.setSignature(sig); } + // for tests public static async signTxStarkNet(tx: Transaction, starkNetPrivateKey: Uint8Array) { - Check.isTrue( - ArrayUtil.isEmpty(tx.getSignature_asU8()), - ' clear the signature field first, signature is:' + tx.getSignature() - ) - const tmpBytes = tx.serializeBinary() - const sig = StarkNetUtil.signBytes(starkNetPrivateKey, tmpBytes) - tx.setSignature(sig) + Check.isTrue(ArrayUtil.isEmpty(tx.getSignature_asU8()), ' clear the signature field first, signature is:' + tx.getSignature()); + const tmpBytes = PushSdkUtil.messageBytesToHashBytes(tx.serializeBinary()); + const sig = StarkNetUtil.signBytes(starkNetPrivateKey, tmpBytes); + tx.setSignature(sig); } public static async checkTxSignature(tx: Transaction): Promise { - const [caip, err] = ChainUtil.parseCaipAddress(tx.getSender()) + const [caip, err] = ChainUtil.parseCaipAddress(tx.getSender()); if (err != null) { - return CheckR.failWithText('failed to parse caip address: ' + err) + return CheckR.failWithText('failed to parse caip address: ' + err); } if (!ArrayUtil.hasMinSize(tx.getSignature_asU8(), 4)) { - return CheckR.failWithText('signature should have at least 4 bytes size') - } - this.log.debug('checking signature `%s`', StrUtil.fmt(tx.getSignature_asU8())) - // todo if(tx.getCategory() === 'INIT_DID') or === startsWith("CUSTOM:") or ANY OTHER ? - const sig = tx.getSignature_asU8() - const tmp = Transaction.deserializeBinary(tx.serializeBinary()) - tmp.setSignature(null) - const tmpBytes = tmp.serializeBinary() - if (caip.namespace === 'eip155') { - // EVM SIGNATURES - const recoveredAddr = EthUtil.recoverAddressFromMsg(tmpBytes, sig) - const valid = recoveredAddr === caip.addr - this.log.debug('recoveredAddr %s; valid: %s', StrUtil.fmt(recoveredAddr), valid) - if (!valid) { - return CheckR.failWithText(`sender address${tx.getSender()} does not match recovered address ${recoveredAddr} - signature was: ${StrUtil.fmt(`${tx.getSignature()}`)}`) - } - } else if (caip.namespace === 'solana') { - // EVM SIGNATURES - const expectedPubKey = SolUtil.convertAddrToPubKey(caip.addr) - const valid = SolUtil.checkSignature(expectedPubKey, tmpBytes, sig) - this.log.debug('expectedPubKey %s; valid: %s', StrUtil.fmt(expectedPubKey), valid) - if (!valid) { - return CheckR.failWithText(`sender address ${tx.getSender()} does not match - signature: ${StrUtil.fmt(`${tx.getSignature()}`)}`) + return CheckR.failWithText('signature should have at least 4 bytes size'); + } + this.log.debug("checking signature `%s`", StrUtil.fmt(tx.getSignature_asU8())); + if (tx.getCategory() === 'INIT_DID') { + const sig = tx.getSignature_asU8(); + const tmp = Transaction.deserializeBinary(tx.serializeBinary()); + tmp.setSignature(null); + const tmpBytes = tmp.serializeBinary(); + + const initDid = InitDid.deserializeBinary(tx.getData_asU8()); + const masterPublicKeyBytesUncompressed = BitUtil.hex0xToBytes(initDid.getMasterpubkey()); + + const sigCheck = await PushSdkUtil.checkPushInitDidSignature(masterPublicKeyBytesUncompressed, tmpBytes, sig); + if (!sigCheck.success) { + return CheckR.failWithText(sigCheck.err); } - } else if (caip.namespace === 'starknet') { - return CheckR.failWithText('not suported') - // STARKNET SIGNATURES - // const expectedPubKey = StarkNetUtil.convertAddrToPubKey(caip.addr); - // const valid = StarkNetUtil.checkSignature(expectedPubKey, tmpBytes, sig); - // this.log.debug('expectedPubKey %s; valid: %s', StrUtil.fmt(expectedPubKey), valid); - // if (!valid) { - // return CheckR.failWithText(`sender address ${tx.getSender()} does not match - // signature: ${StrUtil.fmt(`${tx.getSignature()}`)}`); - // } - } else { - return CheckR.failWithText(`unsupported chain id: ${tx.getSender()}`) + return CheckR.ok(); } - return CheckR.ok() + const sig = tx.getSignature_asU8(); + const tmp = Transaction.deserializeBinary(tx.serializeBinary()); + tmp.setSignature(null); + const tmpBytes = tmp.serializeBinary(); + + const sigCheck = await PushSdkUtil.checkPushNetworkSignature(caip.namespace, caip.chainId, caip.addr, tmpBytes, sig); + if (!sigCheck.success) { + return CheckR.failWithText(sigCheck.err); + } + return CheckR.ok(); } + public static async checkTx(tx: Transaction): Promise { - const checkToken = BlockUtil.checkValidatorTokenFormat(tx.getApitoken_asU8()) + const checkToken = BlockUtil.checkValidatorTokenFormat(tx.getApitoken_asU8()); if (!checkToken.success) { - return checkToken + return checkToken; } if (tx.getType() != 0) { - return CheckR.failWithText(`Only non-value transactions are supported`) + return CheckR.failWithText(`Only non-value transactions are supported`); } if (!ChainUtil.isFullCAIPAddress(tx.getSender())) { - return CheckR.failWithText( - `sender ${tx.getSender()} is not in full CAIP format ${tx.getSender()}` - ) + return CheckR.failWithText(`sender ${tx.getSender()} is not in full CAIP format ${tx.getSender()}`); } // todo how many recipients are required per each tx type? for (const recipientAddr of tx.getRecipientsList()) { if (!ChainUtil.isFullCAIPAddress(recipientAddr)) { - return CheckR.failWithText( - `recipient ${recipientAddr} is not in full CAIP format ${tx.getSender()}` - ) + return CheckR.failWithText(`recipient ${recipientAddr} is not in full CAIP format ${tx.getSender()}`); } } if (!ArrayUtil.hasMinSize(tx.getSalt_asU8(), 4)) { - return CheckR.failWithText( - `salt field requires >=4 bytes ; ` + StrUtil.fmt(tx.getSalt_asU8()) - ) + return CheckR.failWithText(`salt field requires >=4 bytes ; ` + StrUtil.fmt(tx.getSalt_asU8())); } - - const validSignature = await BlockUtil.checkTxSignature(tx) + const payloadCheck = await BlockUtil.checkTxPayload(tx); + if (!payloadCheck.success) { + return payloadCheck; + } + const validSignature = await BlockUtil.checkTxSignature(tx); if (!validSignature.success) { - return CheckR.failWithText(`signature field is invalid`) + return CheckR.failWithText(validSignature.err); } - return CheckR.ok() + return CheckR.ok(); } + public static async checkTxPayload(tx: Transaction): Promise { if (tx.getCategory() === 'INIT_DID') { - const txData = InitDid.deserializeBinary(tx.getData_asU8()) + const txData = InitDid.deserializeBinary(tx.getData_asU8()); if (StrUtil.isEmpty(txData.getMasterpubkey())) { - CheckR.failWithText(`masterPubKey missing`) + CheckR.failWithText(`masterPubKey missing`); } if (StrUtil.isEmpty(txData.getDerivedpubkey())) { - CheckR.failWithText(`derivedPubKey missing`) + CheckR.failWithText(`derivedPubKey missing`); } if (txData.getWallettoencderivedkeyMap().size < 1) { - CheckR.failWithText(`encDerivedPrivKey missing`) + CheckR.failWithText(`encDerivedPrivKey missing`); } - } else if (tx.getCategory().startsWith('CUSTOM:')) { + } else if (tx.getCategory().startsWith("CUSTOM:")) { // no checks for user-defined transactions } else { - CheckR.failWithText(`unsupported transaction category`) + CheckR.failWithText(`unsupported transaction category`); } - return CheckR.ok() + return CheckR.ok(); } + // for tests public static async signBlockAsValidator(wallet: Wallet, blockNoSigs: Block) { - Check.isTrue(blockNoSigs.getSignersList().length == 0) + Check.isTrue(blockNoSigs.getSignersList().length == 0); for (const txObj of blockNoSigs.getTxobjList()) { - const voteObj = new TxValidatorData() - voteObj.setVote(Vote.ACCEPTED) - txObj.setValidatordata(voteObj) - txObj.clearAttestordataList() - } - const ethSig = await EthUtil.signBytes(wallet, blockNoSigs.serializeBinary()) - const vSign = new Signer() - vSign.setSig(ethSig) - blockNoSigs.setSignersList([vSign]) + const voteObj = new TxValidatorData(); + voteObj.setVote(Vote.ACCEPTED); + txObj.setValidatordata(voteObj); + txObj.clearAttestordataList(); + } + const ethSig = await EthUtil.signBytes(wallet, blockNoSigs.serializeBinary()); + const vSign = new Signer(); + vSign.setSig(ethSig); + blockNoSigs.setSignersList([vSign]); } // for tests - public static async signBlockAsAttestor( - wallet: Wallet, - blockSignedByV: Block - ): Promise { - const tmpBlock = Block.deserializeBinary(blockSignedByV.serializeBinary()) - Check.isTrue(blockSignedByV.getSignersList().length == 1) + public static async signBlockAsAttestor(wallet: Wallet, blockSignedByV: Block): Promise { + const tmpBlock = Block.deserializeBinary(blockSignedByV.serializeBinary()); + Check.isTrue(blockSignedByV.getSignersList().length == 1); // tmp block with vsig + attestor data gets signed - const ar = new AttestBlockResult() + const ar = new AttestBlockResult(); for (const txObj of tmpBlock.getTxobjList()) { - const attestorData = new TxAttestorData() - attestorData.setVote(Vote.ACCEPTED) + const attestorData = new TxAttestorData(); + attestorData.setVote(Vote.ACCEPTED); - ar.getAttestordataList().push(attestorData) - txObj.setAttestordataList([attestorData]) + ar.getAttestordataList().push(attestorData); + txObj.setAttestordataList([attestorData]); } - const ethSig = await EthUtil.signBytes(wallet, tmpBlock.serializeBinary()) + const ethSig = await EthUtil.signBytes(wallet, tmpBlock.serializeBinary()); // embed attestor data and signature into real object - const aSign = new Signer() - aSign.setSig(ethSig) - ar.setSigner(aSign) - return ar + const aSign = new Signer(); + aSign.setSig(ethSig); + ar.setSigner(aSign); + return ar; } // for tests - public static async appendPatchAsValidator( - wallet: Wallet, - blockSignedByVA: Block, - ar: AttestBlockResult - ): Promise { + public static async appendPatchAsValidator(wallet: Wallet, blockSignedByVA: Block, ar: AttestBlockResult): Promise { for (let txIndex = 0; txIndex < blockSignedByVA.getTxobjList().length; txIndex++) { - const attestDataPerTx = ar.getAttestordataList()[txIndex] - blockSignedByVA.getTxobjList()[txIndex].getAttestordataList().push(attestDataPerTx) + const attestDataPerTx = ar.getAttestordataList()[txIndex]; + blockSignedByVA.getTxobjList()[txIndex].getAttestordataList().push(attestDataPerTx); } - blockSignedByVA.getSignersList().push(ar.getSigner()) + blockSignedByVA.getSignersList().push(ar.getSigner()); } - public static async recoverPatchAddress( - wallet: Wallet, - blockSignedByVA: Readonly, - ar: AttestBlockResult - ): Promise { - const tmpBlock = Block.deserializeBinary(blockSignedByVA.serializeBinary()) + public static async recoverPatchAddress(wallet: Wallet, blockSignedByVA: Readonly, ar: AttestBlockResult): Promise { + const tmpBlock = Block.deserializeBinary(blockSignedByVA.serializeBinary()); // tx0 -> attest0, ... // is restructured into // block.txObj[0].tx -> attest0, ... for (let txIndex = 0; txIndex < tmpBlock.getTxobjList().length; txIndex++) { - const attestDataPerTx = ar.getAttestordataList()[txIndex] - tmpBlock.getTxobjList()[txIndex].setAttestordataList([attestDataPerTx]) + const attestDataPerTx = ar.getAttestordataList()[txIndex]; + tmpBlock.getTxobjList()[txIndex].setAttestordataList([attestDataPerTx]); } - const aSignatureBytes = ar.getSigner().getSig_asU8() - const tmpBlockBytes = tmpBlock.serializeBinary() - this.log.debug('recovery pub key from block with hash: %s', EthUtil.ethHash(tmpBlockBytes)) - const attestorNodeId = EthUtil.recoverAddressFromMsg(tmpBlockBytes, aSignatureBytes) - this.log.debug('attestorNodeId %o', attestorNodeId) - return attestorNodeId + const aSignatureBytes = ar.getSigner().getSig_asU8(); + const tmpBlockBytes = tmpBlock.serializeBinary(); + this.log.debug('recovery pub key from block with hash: %s', EthUtil.ethHash(tmpBlockBytes)); + const attestorNodeId = EthUtil.recoverAddressFromMsg(tmpBlockBytes, aSignatureBytes); + this.log.debug('attestorNodeId %o', attestorNodeId); + return attestorNodeId; } - public static async recoverSignerAddress( - blockSignedByVA: Readonly, - signerIndex: number - ): Promise { - Check.isTrue( - signerIndex >= 0 && signerIndex < blockSignedByVA.getSignersList().length, - 'signer out of index' - ) + public static async recoverSignerAddress(blockSignedByVA: Readonly, signerIndex: number): Promise { + Check.isTrue(signerIndex >= 0 && signerIndex < blockSignedByVA.getSignersList().length, 'signer out of index'); if (signerIndex == 0) { // validator - const validatorSignature = blockSignedByVA.getSignersList()[0]?.getSig_asU8() - Check.notNull(validatorSignature, 'validator signature is required') - const tmpBlock = Block.deserializeBinary(blockSignedByVA.serializeBinary()) - tmpBlock.clearSignersList() + const validatorSignature = blockSignedByVA.getSignersList()[0]?.getSig_asU8(); + Check.notNull(validatorSignature, "validator signature is required"); + const tmpBlock = Block.deserializeBinary(blockSignedByVA.serializeBinary()); + tmpBlock.clearSignersList(); for (const txObj of tmpBlock.getTxobjList()) { - txObj.clearAttestordataList() + txObj.clearAttestordataList(); } - const blockBytesNoSigners = tmpBlock.serializeBinary() - const blockValidatorNodeId = EthUtil.recoverAddressFromMsg( - blockBytesNoSigners, - validatorSignature - ) - BlockUtil.log.debug('signature # %s by %s (validator) ', 0, blockValidatorNodeId) - return blockValidatorNodeId + const blockBytesNoSigners = tmpBlock.serializeBinary(); + const blockValidatorNodeId = EthUtil.recoverAddressFromMsg(blockBytesNoSigners, validatorSignature); + BlockUtil.log.debug('signature # %s by %s (validator) ', 0, blockValidatorNodeId); + return blockValidatorNodeId; } else { - const tmpBlock = Block.deserializeBinary(blockSignedByVA.serializeBinary()) - const onlyVSignature = [blockSignedByVA.getSignersList()[0]] - tmpBlock.setSignersList(onlyVSignature) + const tmpBlock = Block.deserializeBinary(blockSignedByVA.serializeBinary()); + const onlyVSignature = [blockSignedByVA.getSignersList()[0]]; + tmpBlock.setSignersList(onlyVSignature); for (let txIndex = 0; txIndex < tmpBlock.getTxobjList().length; txIndex++) { - const txObj = tmpBlock.getTxobjList()[txIndex] - const onlyOneAttestation = blockSignedByVA.getTxobjList()[txIndex].getAttestordataList()[ - signerIndex - 1 - ] - txObj.setAttestordataList([onlyOneAttestation]) + const txObj = tmpBlock.getTxobjList()[txIndex]; + const onlyOneAttestation = blockSignedByVA.getTxobjList()[txIndex].getAttestordataList()[signerIndex - 1]; + txObj.setAttestordataList([onlyOneAttestation]); } - const blockBytesNoSignersAnd1Attest = tmpBlock.serializeBinary() - const attSignature = blockSignedByVA.getSignersList()[signerIndex].getSig_asU8() - const attNodeId = EthUtil.recoverAddressFromMsg(blockBytesNoSignersAnd1Attest, attSignature) - BlockUtil.log.debug('signature # %s by %s ', signerIndex - 1, attNodeId) - return attNodeId + const blockBytesNoSignersAnd1Attest = tmpBlock.serializeBinary(); + const attSignature = blockSignedByVA.getSignersList()[signerIndex].getSig_asU8(); + const attNodeId = EthUtil.recoverAddressFromMsg(blockBytesNoSignersAnd1Attest, attSignature); + BlockUtil.log.debug('signature # %s by %s ', signerIndex - 1, attNodeId); + return attNodeId; } } - public static async checkBlockAsAttestor( - blockSignedByV: Block, - validatorsFromContract: Set - ): Promise { - const checkToken = BlockUtil.checkAttestTokenFormat(blockSignedByV.getAttesttoken_asU8()) + public static async checkBlockAsAttestor(blockSignedByV: Block, validatorsFromContract: Set): Promise { + const checkToken = BlockUtil.checkAttestTokenFormat(blockSignedByV.getAttesttoken_asU8()); if (!checkToken.success) { - return checkToken + return checkToken; } if (blockSignedByV.getTxobjList().length >= BlockUtil.MAX_TRANSACTIONS_PER_BLOCK) { return CheckR.failWithText( - `block is full; tx count: ${blockSignedByV.getTxobjList().length} ; limit: ${BlockUtil.MAX_TRANSACTIONS_PER_BLOCK} ` - ) + `block is full; tx count: ${blockSignedByV.getTxobjList().length} ; limit: ${BlockUtil.MAX_TRANSACTIONS_PER_BLOCK} `); } - if ( - BlockUtil.ATTESTOR_MAX_BLOCK_AGE_SECONDS != null && + if (BlockUtil.ATTESTOR_MAX_BLOCK_AGE_SECONDS != null && BlockUtil.ATTESTOR_MAX_BLOCK_AGE_SECONDS > 0 && - Math.abs(blockSignedByV.getTs() - DateUtil.currentTimeMillis()) > - 1000 * BlockUtil.ATTESTOR_MAX_BLOCK_AGE_SECONDS - ) { - return CheckR.failWithText(`block is too old: ${blockSignedByV.getTs()}`) + Math.abs(blockSignedByV.getTs() - DateUtil.currentTimeMillis()) > 1000 * BlockUtil.ATTESTOR_MAX_BLOCK_AGE_SECONDS) { + return CheckR.failWithText(`block is too old: ${blockSignedByV.getTs()}`); } if (!ArrayUtil.hasMinSize(blockSignedByV.getAttesttoken_asU8(), 4)) { - return CheckR.failWithText('attest token is missing or too small (4bytes min)') + return CheckR.failWithText('attest token is missing or too small (4bytes min)'); } // all tx should be valid - let totalTxBytes = 0 + let totalTxBytes = 0; for (let i = 0; i < blockSignedByV.getTxobjList().length; i++) { - const txObj = blockSignedByV.getTxobjList()[i] - const tx = txObj.getTx() + const txObj = blockSignedByV.getTxobjList()[i]; + const tx = txObj.getTx(); if (tx == null) { - return CheckR.failWithText('empty transaction found!') + return CheckR.failWithText('empty transaction found!'); } - const txBytes = tx.serializeBinary().length - totalTxBytes += txBytes + const txBytes = tx.serializeBinary().length; + totalTxBytes += txBytes; if (txBytes > BlockUtil.MAX_TRANSACTION_SIZE_BYTES) { return CheckR.failWithText( - `transaction size exceeds the limit: ${txBytes} ; limit: ${BlockUtil.MAX_TRANSACTION_SIZE_BYTES}` - ) + `transaction size exceeds the limit: ${txBytes} ; limit: ${BlockUtil.MAX_TRANSACTION_SIZE_BYTES}`); } - if ( - txObj.getValidatordata() == null || - !BlockUtil.VALID_VALIDATOR_VOTES.has(txObj.getValidatordata().getVote()) - ) { - return CheckR.failWithText(`tx # ${i} has invalid validator data`) + if (txObj.getValidatordata() == null || !BlockUtil.VALID_VALIDATOR_VOTES.has(txObj.getValidatordata().getVote())) { + return CheckR.failWithText(`tx # ${i} has invalid validator data`); } - const check1 = await BlockUtil.checkTx(tx) + const check1 = await BlockUtil.checkTx(tx); if (!check1.success) { - return check1 - } - const check2 = await BlockUtil.checkTxPayload(tx) - if (!check2.success) { - return check2 + return check1; } } if (totalTxBytes > BlockUtil.MAX_TOTAL_TRANSACTION_SIZE_BYTES) { return CheckR.failWithText( - `total transaction size exceeds the limit: ${totalTxBytes} ; limit: ${BlockUtil.MAX_TOTAL_TRANSACTION_SIZE_BYTES}` - ) + `total transaction size exceeds the limit: ${totalTxBytes} ; limit: ${BlockUtil.MAX_TOTAL_TRANSACTION_SIZE_BYTES}`); } // number of signatures should be equal to number of attestations if (blockSignedByV.getSignersList().length == 0) { - return CheckR.failWithText(`at least validator signature is required`) + return CheckR.failWithText(`at least validator signature is required`); } - const sigCount = blockSignedByV.getSignersList().length + const sigCount = blockSignedByV.getSignersList().length; for (const txObj of blockSignedByV.getTxobjList()) { if (txObj.getAttestordataList().length != sigCount - 1) { return CheckR.failWithText( - `number of tx attestations (salt=${txObj.getTx().getSalt()}) does not match with signature count` - ) + `number of tx attestations (salt=${txObj.getTx().getSalt()}) does not match with signature count`); } } // do a v signature check - const blockValidatorNodeId = await BlockUtil.recoverSignerAddress(blockSignedByV, 0) - BlockUtil.log.debug('signature # %s by %s (validator) ', 0, blockValidatorNodeId) - const allowed = validatorsFromContract.has(blockValidatorNodeId) - Check.isTrue(allowed, `unregistered validator: ${blockValidatorNodeId}`) - return CheckR.ok() + const blockValidatorNodeId = await BlockUtil.recoverSignerAddress(blockSignedByV, 0); + BlockUtil.log.debug('signature # %s by %s (validator) ', 0, blockValidatorNodeId); + const allowed = validatorsFromContract.has(blockValidatorNodeId); + Check.isTrue(allowed, `unregistered validator: ${blockValidatorNodeId}`); + return CheckR.ok(); } - public static async checkBlockFinalized( - blockSignedByVA: Block, - validatorsFromContract: Set, - valPerBlockFromContract: number - ) { - const check1 = await BlockUtil.checkBlockAsAttestor(blockSignedByVA, validatorsFromContract) + public static async checkBlockFinalized(blockSignedByVA: Block, + validatorsFromContract: Set, + valPerBlockFromContract: number) { + const check1 = await BlockUtil.checkBlockAsAttestor(blockSignedByVA, validatorsFromContract); if (!check1.success) { - return check1 + return check1; } - const sigCount = blockSignedByVA.getSignersList().length + const sigCount = blockSignedByVA.getSignersList().length; if (sigCount != valPerBlockFromContract) { - return CheckR.failWithText( - `block has only ${sigCount} signatures; expected ${valPerBlockFromContract} signatures ` - ) + return CheckR.failWithText(`block has only ${sigCount} signatures; expected ${valPerBlockFromContract} signatures `); } for (const txObj of blockSignedByVA.getTxobjList()) { if (txObj.getAttestordataList().length != sigCount - 1) { return CheckR.failWithText( - `number of tx attestations (salt=${txObj.getTx().getSalt()}) does not match with signature count` - ) + `number of tx attestations (salt=${txObj.getTx().getSalt()}) does not match with signature count`); } } - const attestorCount = sigCount - 1 + const attestorCount = sigCount - 1; for (let txIndex = 0; txIndex < blockSignedByVA.getTxobjList().length; txIndex++) { - const txObj = blockSignedByVA.getTxobjList()[txIndex] - const tx = txObj.getTx() + const txObj = blockSignedByVA.getTxobjList()[txIndex]; + const tx = txObj.getTx(); if (tx == null) { - return CheckR.failWithText('empty transaction found!') + return CheckR.failWithText('empty transaction found!'); } - if ( - txObj.getAttestordataList() == null || - txObj.getAttestordataList().length != attestorCount - ) { + if (txObj.getAttestordataList() == null || txObj.getAttestordataList().length != attestorCount) { return CheckR.failWithText( - `tx # ${txIndex} has invalid number of attestations; ${txObj.getAttestordataList().length} instead of ${attestorCount}` - ) + `tx # ${txIndex} has invalid number of attestations; ${txObj.getAttestordataList().length} instead of ${attestorCount}`); } for (const txAttData of txObj.getAttestordataList()) { if (txAttData == null || !BlockUtil.VALID_ATTESTOR_VOTES.has(txAttData.getVote())) { - return CheckR.failWithText(`tx # ${txIndex} has invalid attestor data`) + return CheckR.failWithText(`tx # ${txIndex} has invalid attestor data`); } } } // do A signature check // this requires clearing all signatures + all attestor data except the current one - const tmpBlock = Block.deserializeBinary(blockSignedByVA.serializeBinary()) - const onlyVSignature = [blockSignedByVA.getSignersList()[0]] - tmpBlock.setSignersList(onlyVSignature) + const tmpBlock = Block.deserializeBinary(blockSignedByVA.serializeBinary()); + const onlyVSignature = [blockSignedByVA.getSignersList()[0]]; + tmpBlock.setSignersList(onlyVSignature); for (let attIndex = 1; attIndex < sigCount; attIndex++) { - const attNodeId = await BlockUtil.recoverSignerAddress(blockSignedByVA, attIndex) - BlockUtil.log.debug('signature # %s by %s ', attIndex - 1, attNodeId) + const attNodeId = await BlockUtil.recoverSignerAddress(blockSignedByVA, attIndex); + BlockUtil.log.debug('signature # %s by %s ', attIndex - 1, attNodeId); const allowed = validatorsFromContract.has(attNodeId) Check.isTrue(allowed, `unregistered validator_: ${attNodeId}`) } - return CheckR.ok() + return CheckR.ok(); } } + export class CheckR { success: boolean err: string static failWithText(err: string): CheckR { - return { success: false, err: err } + return {success: false, err: err} } static ok(): CheckR { - return { success: true, err: '' } + return {success: true, err: ''} } } diff --git a/src/utils/pushSdkUtil.ts b/src/utils/pushSdkUtil.ts new file mode 100644 index 0000000..eaba485 --- /dev/null +++ b/src/utils/pushSdkUtil.ts @@ -0,0 +1,139 @@ +import {ethers} from "ethers"; +import nacl from "tweetnacl"; +import bs58 from "bs58"; +import {sha256} from '@noble/hashes/sha256'; +import util from "util"; +import {getAddress, verifyMessage} from "ethers/lib/utils"; +import {computeAddress} from "@ethersproject/transactions"; +import { bech32m } from 'bech32'; + +const hexes = /*#__PURE__*/ Array.from({length: 256}, (_v, i) => + i.toString(16).padStart(2, '0'), +) + +/* +A utility SDK class which is shared between back and front. +Provides signature validation logic which should be in sync. + +Rules: +1. Don't use any utility classes +2. Only public libs which work in the browser +3. NO BACKEND DEPENDENCIES: THIS IS FRONT END LIB + +*/ +export class PushSdkUtil { + + + public static async checkPushInitDidSignature(masterPublicKeyUncompressed: Uint8Array, msgBytes: Uint8Array, + sig: Uint8Array): Promise { + const masterAddrStr = computeAddress(masterPublicKeyUncompressed).toLowerCase(); + const hashBytes = this.messageBytesToHashBytes(msgBytes); + const recoverAddrStr = verifyMessage(hashBytes, sig).toLowerCase(); + if (recoverAddrStr !== masterAddrStr) { + return SigCheck.failWithText(`masterPublicKey address ${masterAddrStr} differs from signature addr ${recoverAddrStr}`); + } + return SigCheck.ok(); + } + + public static async checkPushNetworkSignature(caipNamespace: string, caipChainId: string, caipAddr: string, + msgBytes: Uint8Array, sig: Uint8Array): Promise { + const hashBytes = this.messageBytesToHashBytes(msgBytes); + if (caipNamespace === 'push') { + // PUSH NETWORK SIGNATURES + const evmAddr = this.pushAddrToEvmAddr(caipAddr); + const recoveredAddr = ethers.utils.recoverAddress(ethers.utils.hashMessage(hashBytes), sig); + const valid = recoveredAddr?.toLowerCase() === evmAddr?.toLowerCase(); + if (!valid) { + return SigCheck.failWithText(`sender address ${caipAddr} does not match recovered address ${recoveredAddr} signature was: ${sig}`); + } + return SigCheck.ok(); + } else if (caipNamespace === 'eip155') { + // EVM SIGNATURES + const recoveredAddr = ethers.utils.recoverAddress(ethers.utils.hashMessage(hashBytes), sig); + const valid = recoveredAddr === caipAddr; + if (!valid) { + return SigCheck.failWithText(`sender address ${caipAddr} does not match recovered address ${recoveredAddr} signature was: ${sig}`); + } + return SigCheck.ok(); + } else if (caipNamespace === 'solana') { + // SOLANA SIGNATURES + const expectedPubKey = bs58.decode(caipAddr); + const valid = nacl.sign.detached.verify(hashBytes, sig, expectedPubKey); + if (!valid) { + return SigCheck.failWithText(`sender address ${caipAddr} does not match with signature: ${sig}`); + } + return SigCheck.ok(); + } else { + return SigCheck.failWithText(`unsupported chain id: ${caipNamespace}`); + } + } + + /** + * Converts a Push (bech32m) address to an EVM address + * @param address Push address, + * ex: pushconsumer1ulpxwud78ctaar5zgeuhmju5k8gpz8najcvxkn + * @returns EVM address in checksum format, + * ex: 0xE7C26771bE3E17dE8e8246797DCB94b1D0111E7D + */ + public static pushAddrToEvmAddr(address: string): string { + const decoded = bech32m.decode(address); + const bytes = new Uint8Array(bech32m.fromWords(decoded.words)); + const result = getAddress(this.toHex(bytes)); + return result; + }; + + + /** + * For some web3 wallet compatibility we cannot sign + * 1. raw bytes - Phantom tries to decode this (https://docs.phantom.app/solana/signing-a-message) + * 2. base16 text - Metamask adds 0x prefix + * 3. long base16 text - this breaks UX + * + * So the only good option to sign is to use + * 1. short + * 2. 0x prefixed + * 3. string + * 4. in utf8 bytes + * + * so we try to convert this payload into a 0xSHA bytes first + * @param payload + */ + public static messageBytesToHashBytes(payload: Uint8Array): Uint8Array { + const txSha = sha256(payload); // raw bytes (non ascii) + const hexedSha = this.toHex(txSha); + const textShaInBytesUtf8 = new util.TextEncoder().encode(hexedSha); // utf-8 + return textShaInBytesUtf8; + } + + public static toHex(value: Uint8Array): string { + let string = '' + for (let i = 0; i < value.length; i++) { + string += hexes[value[i]] + } + const hex = `0x${string}` as const + return hex + } + + public static hex0xRemove(hexString: string) { + if (hexString.length >= 2 && (hexString.startsWith('0x') || hexString.startsWith('0X'))) { + hexString = hexString.substring(2); + } + if (hexString.length % 2 == 1) { + hexString = '0' + hexString; + } + return hexString.toLowerCase(); + } +} + +export class SigCheck { + success: boolean + err: string + + static failWithText(err: string): SigCheck { + return {success: false, err: err} + } + + static ok(): SigCheck { + return {success: true, err: ''} + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 3ca6f44..a3b3510 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3986,6 +3986,14 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + is-array-buffer@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" @@ -4067,6 +4075,13 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== +is-generator-function@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -4140,7 +4155,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.13: +is-typed-array@^1.1.13, is-typed-array@^1.1.3: version "1.1.13" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== @@ -6506,6 +6521,17 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +util@^0.12.5: + version "0.12.5" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + which-typed-array "^1.1.2" + utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" @@ -6653,7 +6679,7 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" -which-typed-array@^1.1.14, which-typed-array@^1.1.15: +which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.2: version "1.1.15" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==