From 2a107e809c77c2f909d84e69b3ae4f2359b932a2 Mon Sep 17 00:00:00 2001 From: lklimek <842586+lklimek@users.noreply.github.com> Date: Thu, 29 Jun 2023 17:57:17 +0200 Subject: [PATCH 01/19] feat: build dapi-gprc rust client (#1182) --- Cargo.lock | 250 +++++++++++++++++++++++++++++++++- packages/dapi-grpc/Cargo.toml | 9 +- packages/dapi-grpc/build.rs | 17 ++- 3 files changed, 266 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f99d485330..90796d46bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -160,6 +160,28 @@ dependencies = [ "event-listener", ] +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + [[package]] name = "async-trait" version = "0.1.68" @@ -188,6 +210,51 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "axum" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8175979259124331c1d7bf6586ee7e0da434155e4b2d48ec2c8386281d8df39" +dependencies = [ + "async-trait", + "axum-core", + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + [[package]] name = "backtrace" version = "0.3.67" @@ -922,8 +989,9 @@ name = "dapi-grpc" version = "0.25.0-dev.6" dependencies = [ "prost", - "prost-build", "prost-types", + "tonic", + "tonic-build", ] [[package]] @@ -1673,6 +1741,25 @@ dependencies = [ "visualize", ] +[[package]] +name = "h2" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "half" version = "1.8.2" @@ -1786,6 +1873,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", + "h2", "http", "http-body", "httparse", @@ -1799,6 +1887,18 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + [[package]] name = "iana-time-zone" version = "0.1.57" @@ -2148,6 +2248,12 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "matchit" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" + [[package]] name = "memchr" version = "2.5.0" @@ -2242,6 +2348,12 @@ dependencies = [ "sketches-ddsketch", ] +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -2607,6 +2719,26 @@ dependencies = [ "indexmap", ] +[[package]] +name = "pin-project" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -3212,6 +3344,15 @@ dependencies = [ "sct", ] +[[package]] +name = "rustls-pemfile" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +dependencies = [ + "base64 0.21.2", +] + [[package]] name = "rustls-webpki" version = "0.100.1" @@ -3615,6 +3756,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "synstructure" version = "0.12.6" @@ -3869,6 +4016,16 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-macros" version = "2.1.0" @@ -3880,6 +4037,27 @@ dependencies = [ "syn 2.0.18", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.8" @@ -3920,6 +4098,76 @@ dependencies = [ "winnow", ] +[[package]] +name = "tonic" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.21.2", + "bytes", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "rustls-pemfile", + "tokio", + "tokio-rustls", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-build" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6fdaae4c2c638bb70fe42803a26fbd6fc6ac8c72f5c59f67ecc2a2dcabf4b07" +dependencies = [ + "prettyplease 0.1.25", + "proc-macro2", + "prost-build", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" diff --git a/packages/dapi-grpc/Cargo.toml b/packages/dapi-grpc/Cargo.toml index 046a044931..76c95d980b 100644 --- a/packages/dapi-grpc/Cargo.toml +++ b/packages/dapi-grpc/Cargo.toml @@ -15,14 +15,19 @@ license = "MIT" [dependencies] prost = { version = "0.11.9" } prost-types = { version = "0.11.9" } +tonic = { version = "0.9.2", features = [ + "codegen", + "prost", +], default-features = false } [build-dependencies] -prost-build = { version = "0.11" } +tonic-build = { version = "0.9.2" } [features] -default = ["core", "platform"] +default = ["core", "platform", "client"] core = ["core_v0"] platform = ["platform_v0"] +client = ["tonic/channel", "tonic/tls", "tonic/tls-roots", "platform"] core_v0 = [] platform_v0 = [] diff --git a/packages/dapi-grpc/build.rs b/packages/dapi-grpc/build.rs index 8ae4b360ee..067f2ec119 100644 --- a/packages/dapi-grpc/build.rs +++ b/packages/dapi-grpc/build.rs @@ -8,8 +8,6 @@ fn main() { generate().expect("failed to compile protobuf definitions"); println!("cargo:rerun-if-changed=./protos"); - println!("cargo:rerun-if-changed=./src/core/proto"); - println!("cargo:rerun-if-changed=./src/platform/proto"); } /// Generate Rust definitions from Protobuf definitions @@ -50,11 +48,16 @@ fn generate1( proto_includes: &[PathBuf], out_dir: &PathBuf, ) -> Result<(), std::io::Error> { - let mut pb = prost_build::Config::new(); - pb.out_dir(out_dir); - pb.format(true); - pb.protoc_arg("--experimental_allow_proto3_optional"); - pb.compile_protos(files, proto_includes) + let pb = tonic_build::configure() + .build_server(false) + .out_dir(out_dir) + .protoc_arg("--experimental_allow_proto3_optional"); + #[cfg(feature = "client")] + let pb = pb.build_client(true).build_transport(true); + #[cfg(not(feature = "client"))] + let pb = pb.build_client(false).build_transport(false); + + pb.compile(files, proto_includes) } fn abs_path(path: &PathBuf) -> PathBuf { From ec839d2ed0e27e35321dbc410125796f8683e3cb Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Fri, 7 Jul 2023 17:29:11 +0800 Subject: [PATCH 02/19] feat: fetch data contract history endpoint (#1149) --- .../dash/platform/dapi/v0/PlatformGrpc.java | 86 ++++- .../v0/nodejs/PlatformPromiseClient.js | 39 +++ .../platform/v0/nodejs/platform_pbjs.js | 315 +++++------------- .../platform/v0/nodejs/platform_protoc.js | 311 +++-------------- .../platform/v0/objective-c/Platform.pbobjc.h | 24 +- .../platform/v0/objective-c/Platform.pbobjc.m | 77 +---- .../platform/v0/objective-c/Platform.pbrpc.h | 13 + .../platform/v0/objective-c/Platform.pbrpc.m | 20 ++ .../platform/v0/python/platform_pb2.py | 173 ++++------ .../platform/v0/python/platform_pb2_grpc.py | 33 ++ .../platform/v0/web/PlatformPromiseClient.js | 15 + .../clients/platform/v0/web/platform_pb.d.ts | 44 +-- .../clients/platform/v0/web/platform_pb.js | 311 +++-------------- .../platform/v0/web/platform_pb_service.d.ts | 19 ++ .../platform/v0/web/platform_pb_service.js | 40 +++ .../protos/platform/v0/platform.proto | 13 +- .../lib/externalApis/drive/DriveClient.js | 14 + .../getDataContractHistoryHandlerFactory.js | 43 +++ .../platform/platformHandlersFactory.js | 23 ++ .../methods/platform/PlatformMethodsFacade.js | 2 + .../GetDataContractHistoryResponse.js | 55 +++ .../getDataContractHistoryFactory.js | 81 +++++ .../GetDataContractHistoryResponse.spec.js | 198 +++++++++++ .../getDataContractHistoryFactory.spec.js | 179 ++++++++++ .../SDK/Client/Platform/Fetcher/Fetcher.ts | 29 +- .../src/SDK/Client/Platform/Platform.ts | 3 + .../methods/contracts/history.spec.ts | 111 ++++++ .../Platform/methods/contracts/history.ts | 61 ++++ .../Platform/methods/contracts/update.ts | 4 +- .../test/fixtures/getDataContractFixture.js | 10 +- .../functional/platform/DataContract.spec.js | 38 ++- .../test/functional/platform/Identity.spec.js | 2 - .../data_contract/data_contract_factory.rs | 19 +- .../data_contract_create_transition/mod.rs | 22 ++ .../document_create_transition_action.rs | 4 +- .../document_replace_transition_action.rs | 4 +- ...lidate_documents_batch_transition_state.rs | 2 +- packages/rs-dpp/src/errors/consensus/codes.rs | 1 + .../data_contract_config_update_error.rs | 40 +++ .../consensus/state/data_contract/mod.rs | 1 + .../src/errors/consensus/state/state_error.rs | 4 + .../data_contract_update/mod.rs | 82 ++++- .../data_contract_update/state/v0/mod.rs | 64 ++++ .../src/platform_types/query/v0/mod.rs | 69 ++-- packages/rs-drive/src/drive/contract/mod.rs | 6 +- .../rs-drive/src/drive/contract/queries.rs | 4 +- .../test/fixtures/getDataContractFixture.js | 10 +- .../src/data_contract/data_contract.rs | 12 + .../data_contract_create_transition/mod.rs | 19 +- .../data_contract_update_transition/mod.rs | 19 +- .../data_contract_factory.rs | 13 +- .../src/errors/consensus/consensus_error.rs | 6 +- .../data_contract_config_update_error.rs | 53 +++ .../consensus/state/data_contract/mod.rs | 2 + .../unit/dataContract/DataContract.spec.js | 18 + .../dataContract/DataContractFactory.spec.js | 20 ++ .../DataContractCreateTransition.spec.js | 10 + .../DataContractUpdateTransition.spec.js | 10 + 58 files changed, 1796 insertions(+), 1104 deletions(-) create mode 100644 packages/dapi/lib/grpcServer/handlers/platform/getDataContractHistoryHandlerFactory.js create mode 100644 packages/js-dapi-client/lib/methods/platform/getDataContractHistory/GetDataContractHistoryResponse.js create mode 100644 packages/js-dapi-client/lib/methods/platform/getDataContractHistory/getDataContractHistoryFactory.js create mode 100644 packages/js-dapi-client/test/unit/methods/platform/getDataContractHistory/GetDataContractHistoryResponse.spec.js create mode 100644 packages/js-dapi-client/test/unit/methods/platform/getDataContractHistory/getDataContractHistoryFactory.spec.js create mode 100644 packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/history.spec.ts create mode 100644 packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/history.ts create mode 100644 packages/rs-dpp/src/errors/consensus/state/data_contract/data_contract_config_update_error.rs create mode 100644 packages/wasm-dpp/src/errors/consensus/state/data_contract/data_contract_config_update_error.rs diff --git a/packages/dapi-grpc/clients/platform/v0/java/org/dash/platform/dapi/v0/PlatformGrpc.java b/packages/dapi-grpc/clients/platform/v0/java/org/dash/platform/dapi/v0/PlatformGrpc.java index f362b71118..38d1720fdd 100644 --- a/packages/dapi-grpc/clients/platform/v0/java/org/dash/platform/dapi/v0/PlatformGrpc.java +++ b/packages/dapi-grpc/clients/platform/v0/java/org/dash/platform/dapi/v0/PlatformGrpc.java @@ -263,6 +263,37 @@ org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractResponse> getGetData return getGetDataContractMethod; } + private static volatile io.grpc.MethodDescriptor getGetDataContractHistoryMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "getDataContractHistory", + requestType = org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractHistoryRequest.class, + responseType = org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractHistoryResponse.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor getGetDataContractHistoryMethod() { + io.grpc.MethodDescriptor getGetDataContractHistoryMethod; + if ((getGetDataContractHistoryMethod = PlatformGrpc.getGetDataContractHistoryMethod) == null) { + synchronized (PlatformGrpc.class) { + if ((getGetDataContractHistoryMethod = PlatformGrpc.getGetDataContractHistoryMethod) == null) { + PlatformGrpc.getGetDataContractHistoryMethod = getGetDataContractHistoryMethod = + io.grpc.MethodDescriptor.newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "getDataContractHistory")) + .setSampledToLocalTracing(true) + .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractHistoryRequest.getDefaultInstance())) + .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( + org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractHistoryResponse.getDefaultInstance())) + .setSchemaDescriptor(new PlatformMethodDescriptorSupplier("getDataContractHistory")) + .build(); + } + } + } + return getGetDataContractHistoryMethod; + } + private static volatile io.grpc.MethodDescriptor getGetDataContractsMethod; @@ -556,6 +587,13 @@ public void getDataContract(org.dash.platform.dapi.v0.PlatformOuterClass.GetData io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetDataContractMethod(), responseObserver); } + /** + */ + public void getDataContractHistory(org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractHistoryRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getGetDataContractHistoryMethod(), responseObserver); + } + /** */ public void getDataContracts(org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractsRequest request, @@ -656,6 +694,13 @@ public void getConsensusParams(org.dash.platform.dapi.v0.PlatformOuterClass.GetC org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractRequest, org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractResponse>( this, METHODID_GET_DATA_CONTRACT))) + .addMethod( + getGetDataContractHistoryMethod(), + io.grpc.stub.ServerCalls.asyncUnaryCall( + new MethodHandlers< + org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractHistoryRequest, + org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractHistoryResponse>( + this, METHODID_GET_DATA_CONTRACT_HISTORY))) .addMethod( getGetDataContractsMethod(), io.grpc.stub.ServerCalls.asyncUnaryCall( @@ -783,6 +828,14 @@ public void getDataContract(org.dash.platform.dapi.v0.PlatformOuterClass.GetData getChannel().newCall(getGetDataContractMethod(), getCallOptions()), request, responseObserver); } + /** + */ + public void getDataContractHistory(org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractHistoryRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ClientCalls.asyncUnaryCall( + getChannel().newCall(getGetDataContractHistoryMethod(), getCallOptions()), request, responseObserver); + } + /** */ public void getDataContracts(org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractsRequest request, @@ -905,6 +958,13 @@ public org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractResponse getD getChannel(), getGetDataContractMethod(), getCallOptions(), request); } + /** + */ + public org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractHistoryResponse getDataContractHistory(org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractHistoryRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetDataContractHistoryMethod(), getCallOptions(), request); + } + /** */ public org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractsResponse getDataContracts(org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractsRequest request) { @@ -1029,6 +1089,14 @@ public com.google.common.util.concurrent.ListenableFuture getDataContractHistory( + org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractHistoryRequest request) { + return io.grpc.stub.ClientCalls.futureUnaryCall( + getChannel().newCall(getGetDataContractHistoryMethod(), getCallOptions()), request); + } + /** */ public com.google.common.util.concurrent.ListenableFuture getDataContracts( @@ -1086,12 +1154,13 @@ public com.google.common.util.concurrent.ListenableFuture implements io.grpc.stub.ServerCalls.UnaryMethod, @@ -1142,6 +1211,10 @@ public void invoke(Req request, io.grpc.stub.StreamObserver responseObserv serviceImpl.getDataContract((org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractRequest) request, (io.grpc.stub.StreamObserver) responseObserver); break; + case METHODID_GET_DATA_CONTRACT_HISTORY: + serviceImpl.getDataContractHistory((org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractHistoryRequest) request, + (io.grpc.stub.StreamObserver) responseObserver); + break; case METHODID_GET_DATA_CONTRACTS: serviceImpl.getDataContracts((org.dash.platform.dapi.v0.PlatformOuterClass.GetDataContractsRequest) request, (io.grpc.stub.StreamObserver) responseObserver); @@ -1235,6 +1308,7 @@ public static io.grpc.ServiceDescriptor getServiceDescriptor() { .addMethod(getGetIdentityBalanceAndRevisionMethod()) .addMethod(getGetProofsMethod()) .addMethod(getGetDataContractMethod()) + .addMethod(getGetDataContractHistoryMethod()) .addMethod(getGetDataContractsMethod()) .addMethod(getGetDocumentsMethod()) .addMethod(getGetIdentitiesByPublicKeyHashesMethod()) diff --git a/packages/dapi-grpc/clients/platform/v0/nodejs/PlatformPromiseClient.js b/packages/dapi-grpc/clients/platform/v0/nodejs/PlatformPromiseClient.js index 79c356fce9..634d31ca4d 100644 --- a/packages/dapi-grpc/clients/platform/v0/nodejs/PlatformPromiseClient.js +++ b/packages/dapi-grpc/clients/platform/v0/nodejs/PlatformPromiseClient.js @@ -30,6 +30,8 @@ const { GetIdentityResponse: PBJSGetIdentityResponse, GetDataContractRequest: PBJSGetDataContractRequest, GetDataContractResponse: PBJSGetDataContractResponse, + GetDataContractHistoryRequest: PBJSGetDataContractHistoryRequest, + GetDataContractHistoryResponse: PBJSGetDataContractHistoryResponse, GetDocumentsRequest: PBJSGetDocumentsRequest, GetDocumentsResponse: PBJSGetDocumentsResponse, GetIdentitiesByPublicKeyHashesRequest: PBJSGetIdentitiesByPublicKeyHashesRequest, @@ -49,6 +51,7 @@ const { BroadcastStateTransitionResponse: ProtocBroadcastStateTransitionResponse, GetIdentityResponse: ProtocGetIdentityResponse, GetDataContractResponse: ProtocGetDataContractResponse, + GetDataContractHistoryResponse: ProtocGetDataContractHistoryResponse, GetDocumentsResponse: ProtocGetDocumentsResponse, GetIdentitiesByPublicKeyHashesResponse: ProtocGetIdentitiesByPublicKeyHashesResponse, WaitForStateTransitionResultResponse: ProtocWaitForStateTransitionResultResponse, @@ -91,6 +94,10 @@ class PlatformPromiseClient { this.client.getDataContract.bind(this.client), ); + this.client.getDataContractHistory = promisify( + this.client.getDataContractHistory.bind(this.client), + ); + this.client.getDocuments = promisify( this.client.getDocuments.bind(this.client), ); @@ -204,6 +211,38 @@ class PlatformPromiseClient { ); } + /** + * + * @param {!GetDataContractHistoryRequest} getDataContractHistoryRequest + * @param {?Object} metadata + * @param {CallOptions} [options={}] + * @returns {Promise} + */ + getDataContractHistory(getDataContractHistoryRequest, metadata = {}, options = {}) { + if (!isObject(metadata)) { + throw new Error('metadata must be an object'); + } + + return this.client.getDataContractHistory( + getDataContractHistoryRequest, + convertObjectToMetadata(metadata), + { + interceptors: [ + jsonToProtobufInterceptorFactory( + jsonToProtobufFactory( + ProtocGetDataContractHistoryResponse, + PBJSGetDataContractHistoryResponse, + ), + protobufToJsonFactory( + PBJSGetDataContractHistoryRequest, + ), + ), + ], + ...options, + }, + ); + } + /** * * @param {!GetDocumentsRequest} getDocumentsRequest diff --git a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js index 777804fbfd..119e19815a 100644 --- a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js +++ b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_pbjs.js @@ -350,6 +350,39 @@ $root.org = (function() { * @variation 2 */ + /** + * Callback as used by {@link org.dash.platform.dapi.v0.Platform#getDataContractHistory}. + * @memberof org.dash.platform.dapi.v0.Platform + * @typedef getDataContractHistoryCallback + * @type {function} + * @param {Error|null} error Error, if any + * @param {org.dash.platform.dapi.v0.GetDataContractHistoryResponse} [response] GetDataContractHistoryResponse + */ + + /** + * Calls getDataContractHistory. + * @function getDataContractHistory + * @memberof org.dash.platform.dapi.v0.Platform + * @instance + * @param {org.dash.platform.dapi.v0.IGetDataContractHistoryRequest} request GetDataContractHistoryRequest message or plain object + * @param {org.dash.platform.dapi.v0.Platform.getDataContractHistoryCallback} callback Node-style callback called with the error, if any, and GetDataContractHistoryResponse + * @returns {undefined} + * @variation 1 + */ + Object.defineProperty(Platform.prototype.getDataContractHistory = function getDataContractHistory(request, callback) { + return this.rpcCall(getDataContractHistory, $root.org.dash.platform.dapi.v0.GetDataContractHistoryRequest, $root.org.dash.platform.dapi.v0.GetDataContractHistoryResponse, request, callback); + }, "name", { value: "getDataContractHistory" }); + + /** + * Calls getDataContractHistory. + * @function getDataContractHistory + * @memberof org.dash.platform.dapi.v0.Platform + * @instance + * @param {org.dash.platform.dapi.v0.IGetDataContractHistoryRequest} request GetDataContractHistoryRequest message or plain object + * @returns {Promise} Promise + * @variation 2 + */ + /** * Callback as used by {@link org.dash.platform.dapi.v0.Platform#getDataContracts}. * @memberof org.dash.platform.dapi.v0.Platform @@ -10333,7 +10366,7 @@ $root.org = (function() { * @property {Uint8Array|null} [id] GetDataContractHistoryRequest id * @property {number|null} [limit] GetDataContractHistoryRequest limit * @property {number|null} [offset] GetDataContractHistoryRequest offset - * @property {number|Long|null} [startAtSeconds] GetDataContractHistoryRequest startAtSeconds + * @property {number|Long|null} [startAtMs] GetDataContractHistoryRequest startAtMs * @property {boolean|null} [prove] GetDataContractHistoryRequest prove */ @@ -10377,12 +10410,12 @@ $root.org = (function() { GetDataContractHistoryRequest.prototype.offset = 0; /** - * GetDataContractHistoryRequest startAtSeconds. - * @member {number|Long} startAtSeconds + * GetDataContractHistoryRequest startAtMs. + * @member {number|Long} startAtMs * @memberof org.dash.platform.dapi.v0.GetDataContractHistoryRequest * @instance */ - GetDataContractHistoryRequest.prototype.startAtSeconds = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + GetDataContractHistoryRequest.prototype.startAtMs = $util.Long ? $util.Long.fromBits(0,0,true) : 0; /** * GetDataContractHistoryRequest prove. @@ -10422,8 +10455,8 @@ $root.org = (function() { writer.uint32(/* id 2, wireType 0 =*/16).uint32(message.limit); if (message.offset != null && Object.hasOwnProperty.call(message, "offset")) writer.uint32(/* id 3, wireType 0 =*/24).uint32(message.offset); - if (message.startAtSeconds != null && Object.hasOwnProperty.call(message, "startAtSeconds")) - writer.uint32(/* id 4, wireType 0 =*/32).uint64(message.startAtSeconds); + if (message.startAtMs != null && Object.hasOwnProperty.call(message, "startAtMs")) + writer.uint32(/* id 4, wireType 0 =*/32).uint64(message.startAtMs); if (message.prove != null && Object.hasOwnProperty.call(message, "prove")) writer.uint32(/* id 5, wireType 0 =*/40).bool(message.prove); return writer; @@ -10470,7 +10503,7 @@ $root.org = (function() { message.offset = reader.uint32(); break; case 4: - message.startAtSeconds = reader.uint64(); + message.startAtMs = reader.uint64(); break; case 5: message.prove = reader.bool(); @@ -10519,9 +10552,9 @@ $root.org = (function() { if (message.offset != null && message.hasOwnProperty("offset")) if (!$util.isInteger(message.offset)) return "offset: integer expected"; - if (message.startAtSeconds != null && message.hasOwnProperty("startAtSeconds")) - if (!$util.isInteger(message.startAtSeconds) && !(message.startAtSeconds && $util.isInteger(message.startAtSeconds.low) && $util.isInteger(message.startAtSeconds.high))) - return "startAtSeconds: integer|Long expected"; + if (message.startAtMs != null && message.hasOwnProperty("startAtMs")) + if (!$util.isInteger(message.startAtMs) && !(message.startAtMs && $util.isInteger(message.startAtMs.low) && $util.isInteger(message.startAtMs.high))) + return "startAtMs: integer|Long expected"; if (message.prove != null && message.hasOwnProperty("prove")) if (typeof message.prove !== "boolean") return "prove: boolean expected"; @@ -10549,15 +10582,15 @@ $root.org = (function() { message.limit = object.limit >>> 0; if (object.offset != null) message.offset = object.offset >>> 0; - if (object.startAtSeconds != null) + if (object.startAtMs != null) if ($util.Long) - (message.startAtSeconds = $util.Long.fromValue(object.startAtSeconds)).unsigned = true; - else if (typeof object.startAtSeconds === "string") - message.startAtSeconds = parseInt(object.startAtSeconds, 10); - else if (typeof object.startAtSeconds === "number") - message.startAtSeconds = object.startAtSeconds; - else if (typeof object.startAtSeconds === "object") - message.startAtSeconds = new $util.LongBits(object.startAtSeconds.low >>> 0, object.startAtSeconds.high >>> 0).toNumber(true); + (message.startAtMs = $util.Long.fromValue(object.startAtMs)).unsigned = true; + else if (typeof object.startAtMs === "string") + message.startAtMs = parseInt(object.startAtMs, 10); + else if (typeof object.startAtMs === "number") + message.startAtMs = object.startAtMs; + else if (typeof object.startAtMs === "object") + message.startAtMs = new $util.LongBits(object.startAtMs.low >>> 0, object.startAtMs.high >>> 0).toNumber(true); if (object.prove != null) message.prove = Boolean(object.prove); return message; @@ -10588,9 +10621,9 @@ $root.org = (function() { object.offset = 0; if ($util.Long) { var long = new $util.Long(0, 0, true); - object.startAtSeconds = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; + object.startAtMs = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; } else - object.startAtSeconds = options.longs === String ? "0" : 0; + object.startAtMs = options.longs === String ? "0" : 0; object.prove = false; } if (message.id != null && message.hasOwnProperty("id")) @@ -10599,11 +10632,11 @@ $root.org = (function() { object.limit = message.limit; if (message.offset != null && message.hasOwnProperty("offset")) object.offset = message.offset; - if (message.startAtSeconds != null && message.hasOwnProperty("startAtSeconds")) - if (typeof message.startAtSeconds === "number") - object.startAtSeconds = options.longs === String ? String(message.startAtSeconds) : message.startAtSeconds; + if (message.startAtMs != null && message.hasOwnProperty("startAtMs")) + if (typeof message.startAtMs === "number") + object.startAtMs = options.longs === String ? String(message.startAtMs) : message.startAtMs; else - object.startAtSeconds = options.longs === String ? $util.Long.prototype.toString.call(message.startAtSeconds) : options.longs === Number ? new $util.LongBits(message.startAtSeconds.low >>> 0, message.startAtSeconds.high >>> 0).toNumber(true) : message.startAtSeconds; + object.startAtMs = options.longs === String ? $util.Long.prototype.toString.call(message.startAtMs) : options.longs === Number ? new $util.LongBits(message.startAtMs.low >>> 0, message.startAtMs.high >>> 0).toNumber(true) : message.startAtMs; if (message.prove != null && message.hasOwnProperty("prove")) object.prove = message.prove; return object; @@ -10893,202 +10926,6 @@ $root.org = (function() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; - GetDataContractHistoryResponse.DataContractValue = (function() { - - /** - * Properties of a DataContractValue. - * @memberof org.dash.platform.dapi.v0.GetDataContractHistoryResponse - * @interface IDataContractValue - * @property {Uint8Array|null} [value] DataContractValue value - */ - - /** - * Constructs a new DataContractValue. - * @memberof org.dash.platform.dapi.v0.GetDataContractHistoryResponse - * @classdesc Represents a DataContractValue. - * @implements IDataContractValue - * @constructor - * @param {org.dash.platform.dapi.v0.GetDataContractHistoryResponse.IDataContractValue=} [properties] Properties to set - */ - function DataContractValue(properties) { - if (properties) - for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i) - if (properties[keys[i]] != null) - this[keys[i]] = properties[keys[i]]; - } - - /** - * DataContractValue value. - * @member {Uint8Array} value - * @memberof org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue - * @instance - */ - DataContractValue.prototype.value = $util.newBuffer([]); - - /** - * Creates a new DataContractValue instance using the specified properties. - * @function create - * @memberof org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue - * @static - * @param {org.dash.platform.dapi.v0.GetDataContractHistoryResponse.IDataContractValue=} [properties] Properties to set - * @returns {org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} DataContractValue instance - */ - DataContractValue.create = function create(properties) { - return new DataContractValue(properties); - }; - - /** - * Encodes the specified DataContractValue message. Does not implicitly {@link org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.verify|verify} messages. - * @function encode - * @memberof org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue - * @static - * @param {org.dash.platform.dapi.v0.GetDataContractHistoryResponse.IDataContractValue} message DataContractValue message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - DataContractValue.encode = function encode(message, writer) { - if (!writer) - writer = $Writer.create(); - if (message.value != null && Object.hasOwnProperty.call(message, "value")) - writer.uint32(/* id 1, wireType 2 =*/10).bytes(message.value); - return writer; - }; - - /** - * Encodes the specified DataContractValue message, length delimited. Does not implicitly {@link org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.verify|verify} messages. - * @function encodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue - * @static - * @param {org.dash.platform.dapi.v0.GetDataContractHistoryResponse.IDataContractValue} message DataContractValue message or plain object to encode - * @param {$protobuf.Writer} [writer] Writer to encode to - * @returns {$protobuf.Writer} Writer - */ - DataContractValue.encodeDelimited = function encodeDelimited(message, writer) { - return this.encode(message, writer).ldelim(); - }; - - /** - * Decodes a DataContractValue message from the specified reader or buffer. - * @function decode - * @memberof org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @param {number} [length] Message length if known beforehand - * @returns {org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} DataContractValue - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - DataContractValue.decode = function decode(reader, length) { - if (!(reader instanceof $Reader)) - reader = $Reader.create(reader); - var end = length === undefined ? reader.len : reader.pos + length, message = new $root.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue(); - while (reader.pos < end) { - var tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.value = reader.bytes(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }; - - /** - * Decodes a DataContractValue message from the specified reader or buffer, length delimited. - * @function decodeDelimited - * @memberof org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue - * @static - * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} DataContractValue - * @throws {Error} If the payload is not a reader or valid buffer - * @throws {$protobuf.util.ProtocolError} If required fields are missing - */ - DataContractValue.decodeDelimited = function decodeDelimited(reader) { - if (!(reader instanceof $Reader)) - reader = new $Reader(reader); - return this.decode(reader, reader.uint32()); - }; - - /** - * Verifies a DataContractValue message. - * @function verify - * @memberof org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue - * @static - * @param {Object.} message Plain object to verify - * @returns {string|null} `null` if valid, otherwise the reason why it is not - */ - DataContractValue.verify = function verify(message) { - if (typeof message !== "object" || message === null) - return "object expected"; - if (message.value != null && message.hasOwnProperty("value")) - if (!(message.value && typeof message.value.length === "number" || $util.isString(message.value))) - return "value: buffer expected"; - return null; - }; - - /** - * Creates a DataContractValue message from a plain object. Also converts values to their respective internal types. - * @function fromObject - * @memberof org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue - * @static - * @param {Object.} object Plain object - * @returns {org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} DataContractValue - */ - DataContractValue.fromObject = function fromObject(object) { - if (object instanceof $root.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue) - return object; - var message = new $root.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue(); - if (object.value != null) - if (typeof object.value === "string") - $util.base64.decode(object.value, message.value = $util.newBuffer($util.base64.length(object.value)), 0); - else if (object.value.length >= 0) - message.value = object.value; - return message; - }; - - /** - * Creates a plain object from a DataContractValue message. Also converts values to other types if specified. - * @function toObject - * @memberof org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue - * @static - * @param {org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} message DataContractValue - * @param {$protobuf.IConversionOptions} [options] Conversion options - * @returns {Object.} Plain object - */ - DataContractValue.toObject = function toObject(message, options) { - if (!options) - options = {}; - var object = {}; - if (options.defaults) - if (options.bytes === String) - object.value = ""; - else { - object.value = []; - if (options.bytes !== Array) - object.value = $util.newBuffer(object.value); - } - if (message.value != null && message.hasOwnProperty("value")) - object.value = options.bytes === String ? $util.base64.encode(message.value, 0, message.value.length) : options.bytes === Array ? Array.prototype.slice.call(message.value) : message.value; - return object; - }; - - /** - * Converts this DataContractValue to JSON. - * @function toJSON - * @memberof org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue - * @instance - * @returns {Object.} JSON object - */ - DataContractValue.prototype.toJSON = function toJSON() { - return this.constructor.toObject(this, $protobuf.util.toJSONOptions); - }; - - return DataContractValue; - })(); - GetDataContractHistoryResponse.DataContractHistoryEntry = (function() { /** @@ -11096,7 +10933,7 @@ $root.org = (function() { * @memberof org.dash.platform.dapi.v0.GetDataContractHistoryResponse * @interface IDataContractHistoryEntry * @property {number|Long|null} [date] DataContractHistoryEntry date - * @property {org.dash.platform.dapi.v0.GetDataContractHistoryResponse.IDataContractValue|null} [value] DataContractHistoryEntry value + * @property {Uint8Array|null} [value] DataContractHistoryEntry value */ /** @@ -11124,11 +10961,11 @@ $root.org = (function() { /** * DataContractHistoryEntry value. - * @member {org.dash.platform.dapi.v0.GetDataContractHistoryResponse.IDataContractValue|null|undefined} value + * @member {Uint8Array} value * @memberof org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry * @instance */ - DataContractHistoryEntry.prototype.value = null; + DataContractHistoryEntry.prototype.value = $util.newBuffer([]); /** * Creates a new DataContractHistoryEntry instance using the specified properties. @@ -11157,7 +10994,7 @@ $root.org = (function() { if (message.date != null && Object.hasOwnProperty.call(message, "date")) writer.uint32(/* id 1, wireType 0 =*/8).uint64(message.date); if (message.value != null && Object.hasOwnProperty.call(message, "value")) - $root.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.encode(message.value, writer.uint32(/* id 2, wireType 2 =*/18).fork()).ldelim(); + writer.uint32(/* id 2, wireType 2 =*/18).bytes(message.value); return writer; }; @@ -11196,7 +11033,7 @@ $root.org = (function() { message.date = reader.uint64(); break; case 2: - message.value = $root.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.decode(reader, reader.uint32()); + message.value = reader.bytes(); break; default: reader.skipType(tag & 7); @@ -11236,11 +11073,9 @@ $root.org = (function() { if (message.date != null && message.hasOwnProperty("date")) if (!$util.isInteger(message.date) && !(message.date && $util.isInteger(message.date.low) && $util.isInteger(message.date.high))) return "date: integer|Long expected"; - if (message.value != null && message.hasOwnProperty("value")) { - var error = $root.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.verify(message.value); - if (error) - return "value." + error; - } + if (message.value != null && message.hasOwnProperty("value")) + if (!(message.value && typeof message.value.length === "number" || $util.isString(message.value))) + return "value: buffer expected"; return null; }; @@ -11265,11 +11100,11 @@ $root.org = (function() { message.date = object.date; else if (typeof object.date === "object") message.date = new $util.LongBits(object.date.low >>> 0, object.date.high >>> 0).toNumber(true); - if (object.value != null) { - if (typeof object.value !== "object") - throw TypeError(".org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.value: object expected"); - message.value = $root.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.fromObject(object.value); - } + if (object.value != null) + if (typeof object.value === "string") + $util.base64.decode(object.value, message.value = $util.newBuffer($util.base64.length(object.value)), 0); + else if (object.value.length >= 0) + message.value = object.value; return message; }; @@ -11292,7 +11127,13 @@ $root.org = (function() { object.date = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; } else object.date = options.longs === String ? "0" : 0; - object.value = null; + if (options.bytes === String) + object.value = ""; + else { + object.value = []; + if (options.bytes !== Array) + object.value = $util.newBuffer(object.value); + } } if (message.date != null && message.hasOwnProperty("date")) if (typeof message.date === "number") @@ -11300,7 +11141,7 @@ $root.org = (function() { else object.date = options.longs === String ? $util.Long.prototype.toString.call(message.date) : options.longs === Number ? new $util.LongBits(message.date.low >>> 0, message.date.high >>> 0).toNumber(true) : message.date; if (message.value != null && message.hasOwnProperty("value")) - object.value = $root.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.toObject(message.value, options); + object.value = options.bytes === String ? $util.base64.encode(message.value, 0, message.value.length) : options.bytes === Array ? Array.prototype.slice.call(message.value) : message.value; return object; }; diff --git a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js index d1ce0d56c6..a570e7dbc6 100644 --- a/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js +++ b/packages/dapi-grpc/clients/platform/v0/nodejs/platform_protoc.js @@ -32,7 +32,6 @@ goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistory', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.ResultCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractRequest', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractResponse', null, { proto }); @@ -1002,27 +1001,6 @@ if (goog.DEBUG && !COMPILED) { */ proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.displayName = 'proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse'; } -/** - * 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.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.displayName = 'proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue'; -} /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -10112,7 +10090,7 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.toObject = functio id: msg.getId_asB64(), limit: jspb.Message.getFieldWithDefault(msg, 2, 0), offset: jspb.Message.getFieldWithDefault(msg, 3, 0), - startAtSeconds: jspb.Message.getFieldWithDefault(msg, 4, 0), + startAtMs: jspb.Message.getFieldWithDefault(msg, 4, 0), prove: jspb.Message.getBooleanFieldWithDefault(msg, 5, false) }; @@ -10164,7 +10142,7 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.deserializeBinaryF break; case 4: var value = /** @type {number} */ (reader.readUint64()); - msg.setStartAtSeconds(value); + msg.setStartAtMs(value); break; case 5: var value = /** @type {boolean} */ (reader.readBool()); @@ -10206,22 +10184,22 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.serializeBinaryToW f ); } - f = /** @type {number} */ (jspb.Message.getField(message, 2)); - if (f != null) { + f = message.getLimit(); + if (f !== 0) { writer.writeUint32( 2, f ); } - f = /** @type {number} */ (jspb.Message.getField(message, 3)); - if (f != null) { + f = message.getOffset(); + if (f !== 0) { writer.writeUint32( 3, f ); } - f = /** @type {number} */ (jspb.Message.getField(message, 4)); - if (f != null) { + f = message.getStartAtMs(); + if (f !== 0) { writer.writeUint64( 4, f @@ -10293,25 +10271,7 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.getLimit * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest} returns this */ proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.setLimit = function(value) { - return jspb.Message.setField(this, 2, value); -}; - - -/** - * Clears the field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest} returns this - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.clearLimit = function() { - return jspb.Message.setField(this, 2, undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.hasLimit = function() { - return jspb.Message.getField(this, 2) != null; + return jspb.Message.setProto3IntField(this, 2, value); }; @@ -10329,33 +10289,15 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.getOffse * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest} returns this */ proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.setOffset = function(value) { - return jspb.Message.setField(this, 3, value); -}; - - -/** - * Clears the field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest} returns this - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.clearOffset = function() { - return jspb.Message.setField(this, 3, undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.hasOffset = function() { - return jspb.Message.getField(this, 3) != null; + return jspb.Message.setProto3IntField(this, 3, value); }; /** - * optional uint64 start_at_seconds = 4; + * optional uint64 start_at_ms = 4; * @return {number} */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.getStartAtSeconds = function() { +proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.getStartAtMs = function() { return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0)); }; @@ -10364,26 +10306,8 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.getStart * @param {number} value * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest} returns this */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.setStartAtSeconds = function(value) { - return jspb.Message.setField(this, 4, value); -}; - - -/** - * Clears the field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest} returns this - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.clearStartAtSeconds = function() { - return jspb.Message.setField(this, 4, undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.hasStartAtSeconds = function() { - return jspb.Message.getField(this, 4) != null; +proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.setStartAtMs = function(value) { + return jspb.Message.setProto3IntField(this, 4, value); }; @@ -10576,160 +10500,6 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.serializeBinaryTo -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.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.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.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.toObject = function(includeInstance, msg) { - var f, obj = { - value: msg.getValue_asB64() - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue; - return proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setValue(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getValue_asU8(); - if (f.length > 0) { - writer.writeBytes( - 1, - f - ); - } -}; - - -/** - * optional bytes value = 1; - * @return {string} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.prototype.getValue = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * optional bytes value = 1; - * This is a type-conversion wrapper around `getValue()` - * @return {string} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.prototype.getValue_asB64 = function() { - return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getValue())); -}; - - -/** - * optional bytes value = 1; - * Note that Uint8Array is not supported on all browsers. - * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getValue()` - * @return {!Uint8Array} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.prototype.getValue_asU8 = function() { - return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getValue())); -}; - - -/** - * @param {!(string|Uint8Array)} value - * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} returns this - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.prototype.setValue = function(value) { - return jspb.Message.setProto3BytesField(this, 1, value); -}; - - - - - if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto. @@ -10760,7 +10530,7 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHisto proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.toObject = function(includeInstance, msg) { var f, obj = { date: jspb.Message.getFieldWithDefault(msg, 1, 0), - value: (f = msg.getValue()) && proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.toObject(includeInstance, f) + value: msg.getValue_asB64() }; if (includeInstance) { @@ -10802,8 +10572,7 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHisto msg.setDate(value); break; case 2: - var value = new proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.deserializeBinaryFromReader); + var value = /** @type {!Uint8Array} */ (reader.readBytes()); msg.setValue(value); break; default: @@ -10842,12 +10611,11 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHisto f ); } - f = message.getValue(); - if (f != null) { - writer.writeMessage( + f = message.getValue_asU8(); + if (f.length > 0) { + writer.writeBytes( 2, - f, - proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.serializeBinaryToWriter + f ); } }; @@ -10872,39 +10640,44 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHisto /** - * optional DataContractValue value = 2; - * @return {?proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} + * optional bytes value = 2; + * @return {string} */ proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.prototype.getValue = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue, 2)); + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); }; /** - * @param {?proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry} returns this -*/ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.prototype.setValue = function(value) { - return jspb.Message.setWrapperField(this, 2, value); + * optional bytes value = 2; + * This is a type-conversion wrapper around `getValue()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.prototype.getValue_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getValue())); }; /** - * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry} returns this + * optional bytes value = 2; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getValue()` + * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.prototype.clearValue = function() { - return this.setValue(undefined); +proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.prototype.getValue_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getValue())); }; /** - * Returns whether this field is set. - * @return {boolean} + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry} returns this */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.prototype.hasValue = function() { - return jspb.Message.getField(this, 2) != null; +proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.prototype.setValue = function(value) { + return jspb.Message.setProto3BytesField(this, 2, value); }; diff --git a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h index 37b3109642..79a63560bc 100644 --- a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h +++ b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.h @@ -34,7 +34,6 @@ CF_EXTERN_C_BEGIN @class GPBUInt64Value; @class GetDataContractHistoryResponse_DataContractHistory; @class GetDataContractHistoryResponse_DataContractHistoryEntry; -@class GetDataContractHistoryResponse_DataContractValue; @class GetDataContractsResponse_DataContractEntry; @class GetDataContractsResponse_DataContractValue; @class GetDataContractsResponse_DataContracts; @@ -974,7 +973,7 @@ typedef GPB_ENUM(GetDataContractHistoryRequest_FieldNumber) { GetDataContractHistoryRequest_FieldNumber_Id_p = 1, GetDataContractHistoryRequest_FieldNumber_Limit = 2, GetDataContractHistoryRequest_FieldNumber_Offset = 3, - GetDataContractHistoryRequest_FieldNumber_StartAtSeconds = 4, + GetDataContractHistoryRequest_FieldNumber_StartAtMs = 4, GetDataContractHistoryRequest_FieldNumber_Prove = 5, }; @@ -984,13 +983,10 @@ GPB_FINAL @interface GetDataContractHistoryRequest : GPBMessage @property(nonatomic, readwrite) uint32_t limit; -@property(nonatomic, readwrite) BOOL hasLimit; @property(nonatomic, readwrite) uint32_t offset; -@property(nonatomic, readwrite) BOOL hasOffset; -@property(nonatomic, readwrite) uint64_t startAtSeconds; +@property(nonatomic, readwrite) uint64_t startAtMs; -@property(nonatomic, readwrite) BOOL hasStartAtSeconds; @property(nonatomic, readwrite) BOOL prove; @end @@ -1028,18 +1024,6 @@ GPB_FINAL @interface GetDataContractHistoryResponse : GPBMessage **/ void GetDataContractHistoryResponse_ClearResultOneOfCase(GetDataContractHistoryResponse *message); -#pragma mark - GetDataContractHistoryResponse_DataContractValue - -typedef GPB_ENUM(GetDataContractHistoryResponse_DataContractValue_FieldNumber) { - GetDataContractHistoryResponse_DataContractValue_FieldNumber_Value = 1, -}; - -GPB_FINAL @interface GetDataContractHistoryResponse_DataContractValue : GPBMessage - -@property(nonatomic, readwrite, copy, null_resettable) NSData *value; - -@end - #pragma mark - GetDataContractHistoryResponse_DataContractHistoryEntry typedef GPB_ENUM(GetDataContractHistoryResponse_DataContractHistoryEntry_FieldNumber) { @@ -1051,9 +1035,7 @@ GPB_FINAL @interface GetDataContractHistoryResponse_DataContractHistoryEntry : G @property(nonatomic, readwrite) uint64_t date; -@property(nonatomic, readwrite, strong, null_resettable) GetDataContractHistoryResponse_DataContractValue *value; -/** Test to see if @c value has been set. */ -@property(nonatomic, readwrite) BOOL hasValue; +@property(nonatomic, readwrite, copy, null_resettable) NSData *value; @end diff --git a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m index a5b70d0489..571ac7643a 100644 --- a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m +++ b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbobjc.m @@ -35,7 +35,6 @@ GPBObjCClassDeclaration(GetDataContractHistoryResponse); GPBObjCClassDeclaration(GetDataContractHistoryResponse_DataContractHistory); GPBObjCClassDeclaration(GetDataContractHistoryResponse_DataContractHistoryEntry); -GPBObjCClassDeclaration(GetDataContractHistoryResponse_DataContractValue); GPBObjCClassDeclaration(GetDataContractsResponse); GPBObjCClassDeclaration(GetDataContractsResponse_DataContractEntry); GPBObjCClassDeclaration(GetDataContractsResponse_DataContractValue); @@ -2690,9 +2689,9 @@ + (GPBDescriptor *)descriptor { @implementation GetDataContractHistoryRequest @dynamic id_p; -@dynamic hasLimit, limit; -@dynamic hasOffset, offset; -@dynamic hasStartAtSeconds, startAtSeconds; +@dynamic limit; +@dynamic offset; +@dynamic startAtMs; @dynamic prove; typedef struct GetDataContractHistoryRequest__storage_ { @@ -2700,7 +2699,7 @@ @implementation GetDataContractHistoryRequest uint32_t limit; uint32_t offset; NSData *id_p; - uint64_t startAtSeconds; + uint64_t startAtMs; } GetDataContractHistoryRequest__storage_; // This method is threadsafe because it is initially called @@ -2724,7 +2723,7 @@ + (GPBDescriptor *)descriptor { .number = GetDataContractHistoryRequest_FieldNumber_Limit, .hasIndex = 1, .offset = (uint32_t)offsetof(GetDataContractHistoryRequest__storage_, limit), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeUInt32, }, { @@ -2733,16 +2732,16 @@ + (GPBDescriptor *)descriptor { .number = GetDataContractHistoryRequest_FieldNumber_Offset, .hasIndex = 2, .offset = (uint32_t)offsetof(GetDataContractHistoryRequest__storage_, offset), - .flags = GPBFieldOptional, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeUInt32, }, { - .name = "startAtSeconds", + .name = "startAtMs", .dataTypeSpecific.clazz = Nil, - .number = GetDataContractHistoryRequest_FieldNumber_StartAtSeconds, + .number = GetDataContractHistoryRequest_FieldNumber_StartAtMs, .hasIndex = 3, - .offset = (uint32_t)offsetof(GetDataContractHistoryRequest__storage_, startAtSeconds), - .flags = GPBFieldOptional, + .offset = (uint32_t)offsetof(GetDataContractHistoryRequest__storage_, startAtMs), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeUInt64, }, { @@ -2852,62 +2851,16 @@ void GetDataContractHistoryResponse_ClearResultOneOfCase(GetDataContractHistoryR GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:0]; GPBClearOneof(message, oneof); } -#pragma mark - GetDataContractHistoryResponse_DataContractValue - -@implementation GetDataContractHistoryResponse_DataContractValue - -@dynamic value; - -typedef struct GetDataContractHistoryResponse_DataContractValue__storage_ { - uint32_t _has_storage_[1]; - NSData *value; -} GetDataContractHistoryResponse_DataContractValue__storage_; - -// This method is threadsafe because it is initially called -// in +initialize for each subclass. -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = nil; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - { - .name = "value", - .dataTypeSpecific.clazz = Nil, - .number = GetDataContractHistoryResponse_DataContractValue_FieldNumber_Value, - .hasIndex = 0, - .offset = (uint32_t)offsetof(GetDataContractHistoryResponse_DataContractValue__storage_, value), - .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), - .dataType = GPBDataTypeBytes, - }, - }; - GPBDescriptor *localDescriptor = - [GPBDescriptor allocDescriptorForClass:[GetDataContractHistoryResponse_DataContractValue class] - rootClass:[PlatformRoot class] - file:PlatformRoot_FileDescriptor() - fields:fields - fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription)) - storageSize:sizeof(GetDataContractHistoryResponse_DataContractValue__storage_) - flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)]; - [localDescriptor setupContainingMessageClass:GPBObjCClass(GetDataContractHistoryResponse)]; - #if defined(DEBUG) && DEBUG - NSAssert(descriptor == nil, @"Startup recursed!"); - #endif // DEBUG - descriptor = localDescriptor; - } - return descriptor; -} - -@end - #pragma mark - GetDataContractHistoryResponse_DataContractHistoryEntry @implementation GetDataContractHistoryResponse_DataContractHistoryEntry @dynamic date; -@dynamic hasValue, value; +@dynamic value; typedef struct GetDataContractHistoryResponse_DataContractHistoryEntry__storage_ { uint32_t _has_storage_[1]; - GetDataContractHistoryResponse_DataContractValue *value; + NSData *value; uint64_t date; } GetDataContractHistoryResponse_DataContractHistoryEntry__storage_; @@ -2928,12 +2881,12 @@ + (GPBDescriptor *)descriptor { }, { .name = "value", - .dataTypeSpecific.clazz = GPBObjCClass(GetDataContractHistoryResponse_DataContractValue), + .dataTypeSpecific.clazz = Nil, .number = GetDataContractHistoryResponse_DataContractHistoryEntry_FieldNumber_Value, .hasIndex = 1, .offset = (uint32_t)offsetof(GetDataContractHistoryResponse_DataContractHistoryEntry__storage_, value), - .flags = GPBFieldOptional, - .dataType = GPBDataTypeMessage, + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeBytes, }, }; GPBDescriptor *localDescriptor = diff --git a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbrpc.h b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbrpc.h index 7c74e13b64..73073dc540 100644 --- a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbrpc.h +++ b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbrpc.h @@ -18,6 +18,8 @@ @class BroadcastStateTransitionResponse; @class GetConsensusParamsRequest; @class GetConsensusParamsResponse; +@class GetDataContractHistoryRequest; +@class GetDataContractHistoryResponse; @class GetDataContractRequest; @class GetDataContractResponse; @class GetDataContractsRequest; @@ -105,6 +107,10 @@ NS_ASSUME_NONNULL_BEGIN - (GRPCUnaryProtoCall *)getDataContractWithMessage:(GetDataContractRequest *)message responseHandler:(id)handler callOptions:(GRPCCallOptions *_Nullable)callOptions; +#pragma mark getDataContractHistory(GetDataContractHistoryRequest) returns (GetDataContractHistoryResponse) + +- (GRPCUnaryProtoCall *)getDataContractHistoryWithMessage:(GetDataContractHistoryRequest *)message responseHandler:(id)handler callOptions:(GRPCCallOptions *_Nullable)callOptions; + #pragma mark getDataContracts(GetDataContractsRequest) returns (GetDataContractsResponse) - (GRPCUnaryProtoCall *)getDataContractsWithMessage:(GetDataContractsRequest *)message responseHandler:(id)handler callOptions:(GRPCCallOptions *_Nullable)callOptions; @@ -203,6 +209,13 @@ NS_ASSUME_NONNULL_BEGIN - (GRPCProtoCall *)RPCTogetDataContractWithRequest:(GetDataContractRequest *)request handler:(void(^)(GetDataContractResponse *_Nullable response, NSError *_Nullable error))handler; +#pragma mark getDataContractHistory(GetDataContractHistoryRequest) returns (GetDataContractHistoryResponse) + +- (void)getDataContractHistoryWithRequest:(GetDataContractHistoryRequest *)request handler:(void(^)(GetDataContractHistoryResponse *_Nullable response, NSError *_Nullable error))handler; + +- (GRPCProtoCall *)RPCTogetDataContractHistoryWithRequest:(GetDataContractHistoryRequest *)request handler:(void(^)(GetDataContractHistoryResponse *_Nullable response, NSError *_Nullable error))handler; + + #pragma mark getDataContracts(GetDataContractsRequest) returns (GetDataContractsResponse) - (void)getDataContractsWithRequest:(GetDataContractsRequest *)request handler:(void(^)(GetDataContractsResponse *_Nullable response, NSError *_Nullable error))handler; diff --git a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbrpc.m b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbrpc.m index 8f67bebfc4..8d5cb8dce7 100644 --- a/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbrpc.m +++ b/packages/dapi-grpc/clients/platform/v0/objective-c/Platform.pbrpc.m @@ -243,6 +243,26 @@ - (GRPCUnaryProtoCall *)getDataContractWithMessage:(GetDataContractRequest *)mes responseClass:[GetDataContractResponse class]]; } +#pragma mark getDataContractHistory(GetDataContractHistoryRequest) returns (GetDataContractHistoryResponse) + +- (void)getDataContractHistoryWithRequest:(GetDataContractHistoryRequest *)request handler:(void(^)(GetDataContractHistoryResponse *_Nullable response, NSError *_Nullable error))handler{ + [[self RPCTogetDataContractHistoryWithRequest:request handler:handler] start]; +} +// Returns a not-yet-started RPC object. +- (GRPCProtoCall *)RPCTogetDataContractHistoryWithRequest:(GetDataContractHistoryRequest *)request handler:(void(^)(GetDataContractHistoryResponse *_Nullable response, NSError *_Nullable error))handler{ + return [self RPCToMethod:@"getDataContractHistory" + requestsWriter:[GRXWriter writerWithValue:request] + responseClass:[GetDataContractHistoryResponse class] + responsesWriteable:[GRXWriteable writeableWithSingleHandler:handler]]; +} +- (GRPCUnaryProtoCall *)getDataContractHistoryWithMessage:(GetDataContractHistoryRequest *)message responseHandler:(id)handler callOptions:(GRPCCallOptions *_Nullable)callOptions { + return [self RPCToMethod:@"getDataContractHistory" + message:message + responseHandler:handler + callOptions:callOptions + responseClass:[GetDataContractHistoryResponse class]]; +} + #pragma mark getDataContracts(GetDataContractsRequest) returns (GetDataContractsResponse) - (void)getDataContractsWithRequest:(GetDataContractsRequest *)request handler:(void(^)(GetDataContractsResponse *_Nullable response, NSError *_Nullable error))handler{ diff --git a/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py b/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py index 8bd204a702..e32b38a4ae 100644 --- a/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py +++ b/packages/dapi-grpc/clients/platform/v0/python/platform_pb2.py @@ -22,7 +22,7 @@ syntax='proto3', serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\x0eplatform.proto\x12\x19org.dash.platform.dapi.v0\x1a\x1egoogle/protobuf/wrappers.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"U\n\x05Proof\x12\x15\n\rgrovedb_proof\x18\x01 \x01(\x0c\x12\x13\n\x0bquorum_hash\x18\x02 \x01(\x0c\x12\x11\n\tsignature\x18\x03 \x01(\x0c\x12\r\n\x05round\x18\x04 \x01(\r\"o\n\x10ResponseMetadata\x12\x0e\n\x06height\x18\x01 \x01(\x04\x12 \n\x18\x63ore_chain_locked_height\x18\x02 \x01(\r\x12\x0f\n\x07time_ms\x18\x03 \x01(\x04\x12\x18\n\x10protocol_version\x18\x04 \x01(\r\"L\n\x1dStateTransitionBroadcastError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\";\n\x1f\x42roadcastStateTransitionRequest\x12\x18\n\x10state_transition\x18\x01 \x01(\x0c\"\"\n BroadcastStateTransitionResponse\"/\n\x12GetIdentityRequest\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\"\xa5\x01\n\x13GetIdentityResponse\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06result\"2\n\x14GetIdentitiesRequest\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\"\xdb\x03\n\x15GetIdentitiesResponse\x12Q\n\nidentities\x18\x01 \x01(\x0b\x32;.org.dash.platform.dapi.v0.GetIdentitiesResponse.IdentitiesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1e\n\rIdentityValue\x12\r\n\x05value\x18\x01 \x01(\x0c\x1ak\n\rIdentityEntry\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12M\n\x05value\x18\x02 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetIdentitiesResponse.IdentityValue\x1a\x66\n\nIdentities\x12X\n\x10identity_entries\x18\x01 \x03(\x0b\x32>.org.dash.platform.dapi.v0.GetIdentitiesResponse.IdentityEntryB\x08\n\x06result\"\xc9\x01\n\x1aGetIdentityBalanceResponse\x12/\n\x07\x62\x61lance\x18\x01 \x01(\x0b\x32\x1c.google.protobuf.UInt64ValueH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06result\"\x8d\x03\n%GetIdentityBalanceAndRevisionResponse\x12s\n\x14\x62\x61lance_and_revision\x18\x01 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.BalanceAndRevisionH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1as\n\x12\x42\x61lanceAndRevision\x12-\n\x07\x62\x61lance\x18\x01 \x01(\x0b\x32\x1c.google.protobuf.UInt64Value\x12.\n\x08revision\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt64ValueB\x08\n\x06result\"\xd1\x01\n\x0eKeyRequestType\x12\x36\n\x08\x61ll_keys\x18\x01 \x01(\x0b\x32\".org.dash.platform.dapi.v0.AllKeysH\x00\x12@\n\rspecific_keys\x18\x02 \x01(\x0b\x32\'.org.dash.platform.dapi.v0.SpecificKeysH\x00\x12:\n\nsearch_key\x18\x03 \x01(\x0b\x32$.org.dash.platform.dapi.v0.SearchKeyH\x00\x42\t\n\x07request\"\t\n\x07\x41llKeys\"\x1f\n\x0cSpecificKeys\x12\x0f\n\x07key_ids\x18\x01 \x03(\r\"\xb6\x01\n\tSearchKey\x12I\n\x0bpurpose_map\x18\x01 \x03(\x0b\x32\x34.org.dash.platform.dapi.v0.SearchKey.PurposeMapEntry\x1a^\n\x0fPurposeMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.org.dash.platform.dapi.v0.SecurityLevelMap:\x02\x38\x01\"\xbf\x02\n\x10SecurityLevelMap\x12]\n\x12security_level_map\x18\x01 \x03(\x0b\x32\x41.org.dash.platform.dapi.v0.SecurityLevelMap.SecurityLevelMapEntry\x1aw\n\x15SecurityLevelMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12M\n\x05value\x18\x02 \x01(\x0e\x32>.org.dash.platform.dapi.v0.SecurityLevelMap.KeyKindRequestType:\x02\x38\x01\"S\n\x12KeyKindRequestType\x12\x1f\n\x1b\x43URRENT_KEY_OF_KIND_REQUEST\x10\x00\x12\x1c\n\x18\x41LL_KEYS_OF_KIND_REQUEST\x10\x01\"\xd8\x01\n\x16GetIdentityKeysRequest\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12?\n\x0crequest_type\x18\x02 \x01(\x0b\x32).org.dash.platform.dapi.v0.KeyRequestType\x12+\n\x05limit\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05prove\x18\x05 \x01(\x08\"\xfa\x01\n\x17GetIdentityKeysResponse\x12G\n\x04keys\x18\x01 \x01(\x0b\x32\x37.org.dash.platform.dapi.v0.GetIdentityKeysResponse.KeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\x04Keys\x12\x12\n\nkeys_bytes\x18\x01 \x03(\x0c\x42\x08\n\x06result\"\xb2\x04\n\x18GetIdentitiesKeysRequest\x12\x14\n\x0cidentity_ids\x18\x01 \x03(\x0c\x12?\n\x0crequest_type\x18\x02 \x01(\x0b\x32).org.dash.platform.dapi.v0.KeyRequestType\x12+\n\x05limit\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05prove\x18\x05 \x01(\x08\x1a\xd4\x02\n\x10SecurityLevelMap\x12v\n\x12security_level_map\x18\x01 \x03(\x0b\x32Z.org.dash.platform.dapi.v0.GetIdentitiesKeysRequest.SecurityLevelMap.SecurityLevelMapEntry\x1a\x90\x01\n\x15SecurityLevelMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\x66\n\x05value\x18\x02 \x01(\x0e\x32W.org.dash.platform.dapi.v0.GetIdentitiesKeysRequest.SecurityLevelMap.KeyKindRequestType:\x02\x38\x01\"5\n\x12KeyKindRequestType\x12\x1f\n\x1b\x43URRENT_KEY_OF_KIND_REQUEST\x10\x00\"\xf4\x03\n\x19GetIdentitiesKeysResponse\x12\\\n\x0bpublic_keys\x18\x01 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetIdentitiesKeysResponse.PublicKeyEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\tPublicKey\x12\r\n\x05value\x18\x01 \x01(\x0c\x1al\n\x0ePublicKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12M\n\x05value\x18\x02 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetIdentitiesKeysResponse.PublicKey\x1as\n\x10PublicKeyEntries\x12_\n\x12public_key_entries\x18\x01 \x03(\x0b\x32\x43.org.dash.platform.dapi.v0.GetIdentitiesKeysResponse.PublicKeyEntryB\x08\n\x06result\"\xd7\x04\n\x10GetProofsRequest\x12O\n\nidentities\x18\x01 \x03(\x0b\x32;.org.dash.platform.dapi.v0.GetProofsRequest.IdentityRequest\x12N\n\tcontracts\x18\x02 \x03(\x0b\x32;.org.dash.platform.dapi.v0.GetProofsRequest.ContractRequest\x12N\n\tdocuments\x18\x03 \x03(\x0b\x32;.org.dash.platform.dapi.v0.GetProofsRequest.DocumentRequest\x1aw\n\x0f\x44ocumentRequest\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12#\n\x1b\x64ocument_type_keeps_history\x18\x03 \x01(\x08\x12\x13\n\x0b\x64ocument_id\x18\x04 \x01(\x0c\x1a\xb0\x01\n\x0fIdentityRequest\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12V\n\x0crequest_type\x18\x02 \x01(\x0e\x32@.org.dash.platform.dapi.v0.GetProofsRequest.IdentityRequest.Type\"0\n\x04Type\x12\x11\n\rFULL_IDENTITY\x10\x00\x12\x0b\n\x07\x42\x41LANCE\x10\x01\x12\x08\n\x04KEYS\x10\x02\x1a&\n\x0f\x43ontractRequest\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\"\x83\x01\n\x11GetProofsResponse\x12/\n\x05proof\x18\x01 \x01(\x0b\x32 .org.dash.platform.dapi.v0.Proof\x12=\n\x08metadata\x18\x02 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\"3\n\x16GetDataContractRequest\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\"\xae\x01\n\x17GetDataContractResponse\x12\x17\n\rdata_contract\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06result\"5\n\x17GetDataContractsRequest\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\"\x86\x04\n\x18GetDataContractsResponse\x12[\n\x0e\x64\x61ta_contracts\x18\x01 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\"\n\x11\x44\x61taContractValue\x12\r\n\x05value\x18\x01 \x01(\x0c\x1av\n\x11\x44\x61taContractEntry\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12T\n\x05value\x18\x02 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractValue\x1au\n\rDataContracts\x12\x64\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32\x45.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractEntryB\x08\n\x06result\"\xac\x01\n\x1dGetDataContractHistoryRequest\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\x12\n\x05limit\x18\x02 \x01(\rH\x00\x88\x01\x01\x12\x13\n\x06offset\x18\x03 \x01(\rH\x01\x88\x01\x01\x12\x1d\n\x10start_at_seconds\x18\x04 \x01(\x04H\x02\x88\x01\x01\x12\r\n\x05prove\x18\x05 \x01(\x08\x42\x08\n\x06_limitB\t\n\x07_offsetB\x13\n\x11_start_at_seconds\"\xc2\x04\n\x1eGetDataContractHistoryResponse\x12n\n\x15\x64\x61ta_contract_history\x18\x01 \x01(\x0b\x32M.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\"\n\x11\x44\x61taContractValue\x12\r\n\x05value\x18\x01 \x01(\x0c\x1a\x84\x01\n\x18\x44\x61taContractHistoryEntry\x12\x0c\n\x04\x64\x61te\x18\x01 \x01(\x04\x12Z\n\x05value\x18\x02 \x01(\x0b\x32K.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue\x1a\x88\x01\n\x13\x44\x61taContractHistory\x12q\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32R.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntryB\x08\n\x06result\"\xb9\x01\n\x13GetDocumentsRequest\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12\r\n\x05where\x18\x03 \x01(\x0c\x12\x10\n\x08order_by\x18\x04 \x01(\x0c\x12\r\n\x05limit\x18\x05 \x01(\r\x12\x15\n\x0bstart_after\x18\x06 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x07 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x08 \x01(\x08\x42\x07\n\x05start\"\x82\x02\n\x14GetDocumentsResponse\x12N\n\tdocuments\x18\x01 \x01(\x0b\x32\x39.org.dash.platform.dapi.v0.GetDocumentsResponse.DocumentsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1e\n\tDocuments\x12\x11\n\tdocuments\x18\x01 \x03(\x0c\x42\x08\n\x06result\"Q\n%GetIdentitiesByPublicKeyHashesRequest\x12\x19\n\x11public_key_hashes\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\"\xaa\x02\n&GetIdentitiesByPublicKeyHashesResponse\x12\x62\n\nidentities\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentitiesByPublicKeyHashesResponse.IdentitiesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a \n\nIdentities\x12\x12\n\nidentities\x18\x01 \x03(\x0c\x42\x08\n\x06result\"M\n#GetIdentityByPublicKeyHashesRequest\x12\x17\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\"\xb6\x01\n$GetIdentityByPublicKeyHashesResponse\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06result\"S\n#WaitForStateTransitionResultRequest\x12\x1d\n\x15state_transition_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\"\xed\x01\n$WaitForStateTransitionResultResponse\x12I\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x38.org.dash.platform.dapi.v0.StateTransitionBroadcastErrorH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06result\"P\n\x14\x43onsensusParamsBlock\x12\x11\n\tmax_bytes\x18\x01 \x01(\t\x12\x0f\n\x07max_gas\x18\x02 \x01(\t\x12\x14\n\x0ctime_iota_ms\x18\x03 \x01(\t\"b\n\x17\x43onsensusParamsEvidence\x12\x1a\n\x12max_age_num_blocks\x18\x01 \x01(\t\x12\x18\n\x10max_age_duration\x18\x02 \x01(\t\x12\x11\n\tmax_bytes\x18\x03 \x01(\t\":\n\x19GetConsensusParamsRequest\x12\x0e\n\x06height\x18\x01 \x01(\x03\x12\r\n\x05prove\x18\x02 \x01(\x08\"\xa2\x01\n\x1aGetConsensusParamsResponse\x12>\n\x05\x62lock\x18\x01 \x01(\x0b\x32/.org.dash.platform.dapi.v0.ConsensusParamsBlock\x12\x44\n\x08\x65vidence\x18\x02 \x01(\x0b\x32\x32.org.dash.platform.dapi.v0.ConsensusParamsEvidence2\xcb\x0e\n\x08Platform\x12\x93\x01\n\x18\x62roadcastStateTransition\x12:.org.dash.platform.dapi.v0.BroadcastStateTransitionRequest\x1a;.org.dash.platform.dapi.v0.BroadcastStateTransitionResponse\x12l\n\x0bgetIdentity\x12-.org.dash.platform.dapi.v0.GetIdentityRequest\x1a..org.dash.platform.dapi.v0.GetIdentityResponse\x12r\n\rgetIdentities\x12/.org.dash.platform.dapi.v0.GetIdentitiesRequest\x1a\x30.org.dash.platform.dapi.v0.GetIdentitiesResponse\x12x\n\x0fgetIdentityKeys\x12\x31.org.dash.platform.dapi.v0.GetIdentityKeysRequest\x1a\x32.org.dash.platform.dapi.v0.GetIdentityKeysResponse\x12z\n\x12getIdentityBalance\x12-.org.dash.platform.dapi.v0.GetIdentityRequest\x1a\x35.org.dash.platform.dapi.v0.GetIdentityBalanceResponse\x12\x90\x01\n\x1dgetIdentityBalanceAndRevision\x12-.org.dash.platform.dapi.v0.GetIdentityRequest\x1a@.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse\x12\x66\n\tgetProofs\x12+.org.dash.platform.dapi.v0.GetProofsRequest\x1a,.org.dash.platform.dapi.v0.GetProofsResponse\x12x\n\x0fgetDataContract\x12\x31.org.dash.platform.dapi.v0.GetDataContractRequest\x1a\x32.org.dash.platform.dapi.v0.GetDataContractResponse\x12{\n\x10getDataContracts\x12\x32.org.dash.platform.dapi.v0.GetDataContractsRequest\x1a\x33.org.dash.platform.dapi.v0.GetDataContractsResponse\x12o\n\x0cgetDocuments\x12..org.dash.platform.dapi.v0.GetDocumentsRequest\x1a/.org.dash.platform.dapi.v0.GetDocumentsResponse\x12\xa5\x01\n\x1egetIdentitiesByPublicKeyHashes\x12@.org.dash.platform.dapi.v0.GetIdentitiesByPublicKeyHashesRequest\x1a\x41.org.dash.platform.dapi.v0.GetIdentitiesByPublicKeyHashesResponse\x12\x9f\x01\n\x1cgetIdentityByPublicKeyHashes\x12>.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashesRequest\x1a?.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashesResponse\x12\x9f\x01\n\x1cwaitForStateTransitionResult\x12>.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest\x1a?.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse\x12\x81\x01\n\x12getConsensusParams\x12\x34.org.dash.platform.dapi.v0.GetConsensusParamsRequest\x1a\x35.org.dash.platform.dapi.v0.GetConsensusParamsResponseb\x06proto3' + serialized_pb=b'\n\x0eplatform.proto\x12\x19org.dash.platform.dapi.v0\x1a\x1egoogle/protobuf/wrappers.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"U\n\x05Proof\x12\x15\n\rgrovedb_proof\x18\x01 \x01(\x0c\x12\x13\n\x0bquorum_hash\x18\x02 \x01(\x0c\x12\x11\n\tsignature\x18\x03 \x01(\x0c\x12\r\n\x05round\x18\x04 \x01(\r\"o\n\x10ResponseMetadata\x12\x0e\n\x06height\x18\x01 \x01(\x04\x12 \n\x18\x63ore_chain_locked_height\x18\x02 \x01(\r\x12\x0f\n\x07time_ms\x18\x03 \x01(\x04\x12\x18\n\x10protocol_version\x18\x04 \x01(\r\"L\n\x1dStateTransitionBroadcastError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\r\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\";\n\x1f\x42roadcastStateTransitionRequest\x12\x18\n\x10state_transition\x18\x01 \x01(\x0c\"\"\n BroadcastStateTransitionResponse\"/\n\x12GetIdentityRequest\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\"\xa5\x01\n\x13GetIdentityResponse\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06result\"2\n\x14GetIdentitiesRequest\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\"\xdb\x03\n\x15GetIdentitiesResponse\x12Q\n\nidentities\x18\x01 \x01(\x0b\x32;.org.dash.platform.dapi.v0.GetIdentitiesResponse.IdentitiesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1e\n\rIdentityValue\x12\r\n\x05value\x18\x01 \x01(\x0c\x1ak\n\rIdentityEntry\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12M\n\x05value\x18\x02 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetIdentitiesResponse.IdentityValue\x1a\x66\n\nIdentities\x12X\n\x10identity_entries\x18\x01 \x03(\x0b\x32>.org.dash.platform.dapi.v0.GetIdentitiesResponse.IdentityEntryB\x08\n\x06result\"\xc9\x01\n\x1aGetIdentityBalanceResponse\x12/\n\x07\x62\x61lance\x18\x01 \x01(\x0b\x32\x1c.google.protobuf.UInt64ValueH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06result\"\x8d\x03\n%GetIdentityBalanceAndRevisionResponse\x12s\n\x14\x62\x61lance_and_revision\x18\x01 \x01(\x0b\x32S.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse.BalanceAndRevisionH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1as\n\x12\x42\x61lanceAndRevision\x12-\n\x07\x62\x61lance\x18\x01 \x01(\x0b\x32\x1c.google.protobuf.UInt64Value\x12.\n\x08revision\x18\x02 \x01(\x0b\x32\x1c.google.protobuf.UInt64ValueB\x08\n\x06result\"\xd1\x01\n\x0eKeyRequestType\x12\x36\n\x08\x61ll_keys\x18\x01 \x01(\x0b\x32\".org.dash.platform.dapi.v0.AllKeysH\x00\x12@\n\rspecific_keys\x18\x02 \x01(\x0b\x32\'.org.dash.platform.dapi.v0.SpecificKeysH\x00\x12:\n\nsearch_key\x18\x03 \x01(\x0b\x32$.org.dash.platform.dapi.v0.SearchKeyH\x00\x42\t\n\x07request\"\t\n\x07\x41llKeys\"\x1f\n\x0cSpecificKeys\x12\x0f\n\x07key_ids\x18\x01 \x03(\r\"\xb6\x01\n\tSearchKey\x12I\n\x0bpurpose_map\x18\x01 \x03(\x0b\x32\x34.org.dash.platform.dapi.v0.SearchKey.PurposeMapEntry\x1a^\n\x0fPurposeMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12:\n\x05value\x18\x02 \x01(\x0b\x32+.org.dash.platform.dapi.v0.SecurityLevelMap:\x02\x38\x01\"\xbf\x02\n\x10SecurityLevelMap\x12]\n\x12security_level_map\x18\x01 \x03(\x0b\x32\x41.org.dash.platform.dapi.v0.SecurityLevelMap.SecurityLevelMapEntry\x1aw\n\x15SecurityLevelMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12M\n\x05value\x18\x02 \x01(\x0e\x32>.org.dash.platform.dapi.v0.SecurityLevelMap.KeyKindRequestType:\x02\x38\x01\"S\n\x12KeyKindRequestType\x12\x1f\n\x1b\x43URRENT_KEY_OF_KIND_REQUEST\x10\x00\x12\x1c\n\x18\x41LL_KEYS_OF_KIND_REQUEST\x10\x01\"\xd8\x01\n\x16GetIdentityKeysRequest\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12?\n\x0crequest_type\x18\x02 \x01(\x0b\x32).org.dash.platform.dapi.v0.KeyRequestType\x12+\n\x05limit\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05prove\x18\x05 \x01(\x08\"\xfa\x01\n\x17GetIdentityKeysResponse\x12G\n\x04keys\x18\x01 \x01(\x0b\x32\x37.org.dash.platform.dapi.v0.GetIdentityKeysResponse.KeysH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\x04Keys\x12\x12\n\nkeys_bytes\x18\x01 \x03(\x0c\x42\x08\n\x06result\"\xb2\x04\n\x18GetIdentitiesKeysRequest\x12\x14\n\x0cidentity_ids\x18\x01 \x03(\x0c\x12?\n\x0crequest_type\x18\x02 \x01(\x0b\x32).org.dash.platform.dapi.v0.KeyRequestType\x12+\n\x05limit\x18\x03 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12,\n\x06offset\x18\x04 \x01(\x0b\x32\x1c.google.protobuf.UInt32Value\x12\r\n\x05prove\x18\x05 \x01(\x08\x1a\xd4\x02\n\x10SecurityLevelMap\x12v\n\x12security_level_map\x18\x01 \x03(\x0b\x32Z.org.dash.platform.dapi.v0.GetIdentitiesKeysRequest.SecurityLevelMap.SecurityLevelMapEntry\x1a\x90\x01\n\x15SecurityLevelMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\r\x12\x66\n\x05value\x18\x02 \x01(\x0e\x32W.org.dash.platform.dapi.v0.GetIdentitiesKeysRequest.SecurityLevelMap.KeyKindRequestType:\x02\x38\x01\"5\n\x12KeyKindRequestType\x12\x1f\n\x1b\x43URRENT_KEY_OF_KIND_REQUEST\x10\x00\"\xf4\x03\n\x19GetIdentitiesKeysResponse\x12\\\n\x0bpublic_keys\x18\x01 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetIdentitiesKeysResponse.PublicKeyEntriesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1a\n\tPublicKey\x12\r\n\x05value\x18\x01 \x01(\x0c\x1al\n\x0ePublicKeyEntry\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12M\n\x05value\x18\x02 \x01(\x0b\x32>.org.dash.platform.dapi.v0.GetIdentitiesKeysResponse.PublicKey\x1as\n\x10PublicKeyEntries\x12_\n\x12public_key_entries\x18\x01 \x03(\x0b\x32\x43.org.dash.platform.dapi.v0.GetIdentitiesKeysResponse.PublicKeyEntryB\x08\n\x06result\"\xd7\x04\n\x10GetProofsRequest\x12O\n\nidentities\x18\x01 \x03(\x0b\x32;.org.dash.platform.dapi.v0.GetProofsRequest.IdentityRequest\x12N\n\tcontracts\x18\x02 \x03(\x0b\x32;.org.dash.platform.dapi.v0.GetProofsRequest.ContractRequest\x12N\n\tdocuments\x18\x03 \x03(\x0b\x32;.org.dash.platform.dapi.v0.GetProofsRequest.DocumentRequest\x1aw\n\x0f\x44ocumentRequest\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12#\n\x1b\x64ocument_type_keeps_history\x18\x03 \x01(\x08\x12\x13\n\x0b\x64ocument_id\x18\x04 \x01(\x0c\x1a\xb0\x01\n\x0fIdentityRequest\x12\x13\n\x0bidentity_id\x18\x01 \x01(\x0c\x12V\n\x0crequest_type\x18\x02 \x01(\x0e\x32@.org.dash.platform.dapi.v0.GetProofsRequest.IdentityRequest.Type\"0\n\x04Type\x12\x11\n\rFULL_IDENTITY\x10\x00\x12\x0b\n\x07\x42\x41LANCE\x10\x01\x12\x08\n\x04KEYS\x10\x02\x1a&\n\x0f\x43ontractRequest\x12\x13\n\x0b\x63ontract_id\x18\x01 \x01(\x0c\"\x83\x01\n\x11GetProofsResponse\x12/\n\x05proof\x18\x01 \x01(\x0b\x32 .org.dash.platform.dapi.v0.Proof\x12=\n\x08metadata\x18\x02 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\"3\n\x16GetDataContractRequest\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\"\xae\x01\n\x17GetDataContractResponse\x12\x17\n\rdata_contract\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06result\"5\n\x17GetDataContractsRequest\x12\x0b\n\x03ids\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\"\x86\x04\n\x18GetDataContractsResponse\x12[\n\x0e\x64\x61ta_contracts\x18\x01 \x01(\x0b\x32\x41.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\"\n\x11\x44\x61taContractValue\x12\r\n\x05value\x18\x01 \x01(\x0c\x1av\n\x11\x44\x61taContractEntry\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12T\n\x05value\x18\x02 \x01(\x0b\x32\x45.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractValue\x1au\n\rDataContracts\x12\x64\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32\x45.org.dash.platform.dapi.v0.GetDataContractsResponse.DataContractEntryB\x08\n\x06result\"n\n\x1dGetDataContractHistoryRequest\x12\n\n\x02id\x18\x01 \x01(\x0c\x12\r\n\x05limit\x18\x02 \x01(\r\x12\x0e\n\x06offset\x18\x03 \x01(\r\x12\x13\n\x0bstart_at_ms\x18\x04 \x01(\x04\x12\r\n\x05prove\x18\x05 \x01(\x08\"\xd0\x03\n\x1eGetDataContractHistoryResponse\x12n\n\x15\x64\x61ta_contract_history\x18\x01 \x01(\x0b\x32M.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x37\n\x18\x44\x61taContractHistoryEntry\x12\x0c\n\x04\x64\x61te\x18\x01 \x01(\x04\x12\r\n\x05value\x18\x02 \x01(\x0c\x1a\x88\x01\n\x13\x44\x61taContractHistory\x12q\n\x15\x64\x61ta_contract_entries\x18\x01 \x03(\x0b\x32R.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntryB\x08\n\x06result\"\xb9\x01\n\x13GetDocumentsRequest\x12\x18\n\x10\x64\x61ta_contract_id\x18\x01 \x01(\x0c\x12\x15\n\rdocument_type\x18\x02 \x01(\t\x12\r\n\x05where\x18\x03 \x01(\x0c\x12\x10\n\x08order_by\x18\x04 \x01(\x0c\x12\r\n\x05limit\x18\x05 \x01(\r\x12\x15\n\x0bstart_after\x18\x06 \x01(\x0cH\x00\x12\x12\n\x08start_at\x18\x07 \x01(\x0cH\x00\x12\r\n\x05prove\x18\x08 \x01(\x08\x42\x07\n\x05start\"\x82\x02\n\x14GetDocumentsResponse\x12N\n\tdocuments\x18\x01 \x01(\x0b\x32\x39.org.dash.platform.dapi.v0.GetDocumentsResponse.DocumentsH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a\x1e\n\tDocuments\x12\x11\n\tdocuments\x18\x01 \x03(\x0c\x42\x08\n\x06result\"Q\n%GetIdentitiesByPublicKeyHashesRequest\x12\x19\n\x11public_key_hashes\x18\x01 \x03(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\"\xaa\x02\n&GetIdentitiesByPublicKeyHashesResponse\x12\x62\n\nidentities\x18\x01 \x01(\x0b\x32L.org.dash.platform.dapi.v0.GetIdentitiesByPublicKeyHashesResponse.IdentitiesH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadata\x1a \n\nIdentities\x12\x12\n\nidentities\x18\x01 \x03(\x0c\x42\x08\n\x06result\"M\n#GetIdentityByPublicKeyHashesRequest\x12\x17\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\"\xb6\x01\n$GetIdentityByPublicKeyHashesResponse\x12\x12\n\x08identity\x18\x01 \x01(\x0cH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06result\"S\n#WaitForStateTransitionResultRequest\x12\x1d\n\x15state_transition_hash\x18\x01 \x01(\x0c\x12\r\n\x05prove\x18\x02 \x01(\x08\"\xed\x01\n$WaitForStateTransitionResultResponse\x12I\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x38.org.dash.platform.dapi.v0.StateTransitionBroadcastErrorH\x00\x12\x31\n\x05proof\x18\x02 \x01(\x0b\x32 .org.dash.platform.dapi.v0.ProofH\x00\x12=\n\x08metadata\x18\x03 \x01(\x0b\x32+.org.dash.platform.dapi.v0.ResponseMetadataB\x08\n\x06result\"P\n\x14\x43onsensusParamsBlock\x12\x11\n\tmax_bytes\x18\x01 \x01(\t\x12\x0f\n\x07max_gas\x18\x02 \x01(\t\x12\x14\n\x0ctime_iota_ms\x18\x03 \x01(\t\"b\n\x17\x43onsensusParamsEvidence\x12\x1a\n\x12max_age_num_blocks\x18\x01 \x01(\t\x12\x18\n\x10max_age_duration\x18\x02 \x01(\t\x12\x11\n\tmax_bytes\x18\x03 \x01(\t\":\n\x19GetConsensusParamsRequest\x12\x0e\n\x06height\x18\x01 \x01(\x03\x12\r\n\x05prove\x18\x02 \x01(\x08\"\xa2\x01\n\x1aGetConsensusParamsResponse\x12>\n\x05\x62lock\x18\x01 \x01(\x0b\x32/.org.dash.platform.dapi.v0.ConsensusParamsBlock\x12\x44\n\x08\x65vidence\x18\x02 \x01(\x0b\x32\x32.org.dash.platform.dapi.v0.ConsensusParamsEvidence2\xdb\x0f\n\x08Platform\x12\x93\x01\n\x18\x62roadcastStateTransition\x12:.org.dash.platform.dapi.v0.BroadcastStateTransitionRequest\x1a;.org.dash.platform.dapi.v0.BroadcastStateTransitionResponse\x12l\n\x0bgetIdentity\x12-.org.dash.platform.dapi.v0.GetIdentityRequest\x1a..org.dash.platform.dapi.v0.GetIdentityResponse\x12r\n\rgetIdentities\x12/.org.dash.platform.dapi.v0.GetIdentitiesRequest\x1a\x30.org.dash.platform.dapi.v0.GetIdentitiesResponse\x12x\n\x0fgetIdentityKeys\x12\x31.org.dash.platform.dapi.v0.GetIdentityKeysRequest\x1a\x32.org.dash.platform.dapi.v0.GetIdentityKeysResponse\x12z\n\x12getIdentityBalance\x12-.org.dash.platform.dapi.v0.GetIdentityRequest\x1a\x35.org.dash.platform.dapi.v0.GetIdentityBalanceResponse\x12\x90\x01\n\x1dgetIdentityBalanceAndRevision\x12-.org.dash.platform.dapi.v0.GetIdentityRequest\x1a@.org.dash.platform.dapi.v0.GetIdentityBalanceAndRevisionResponse\x12\x66\n\tgetProofs\x12+.org.dash.platform.dapi.v0.GetProofsRequest\x1a,.org.dash.platform.dapi.v0.GetProofsResponse\x12x\n\x0fgetDataContract\x12\x31.org.dash.platform.dapi.v0.GetDataContractRequest\x1a\x32.org.dash.platform.dapi.v0.GetDataContractResponse\x12\x8d\x01\n\x16getDataContractHistory\x12\x38.org.dash.platform.dapi.v0.GetDataContractHistoryRequest\x1a\x39.org.dash.platform.dapi.v0.GetDataContractHistoryResponse\x12{\n\x10getDataContracts\x12\x32.org.dash.platform.dapi.v0.GetDataContractsRequest\x1a\x33.org.dash.platform.dapi.v0.GetDataContractsResponse\x12o\n\x0cgetDocuments\x12..org.dash.platform.dapi.v0.GetDocumentsRequest\x1a/.org.dash.platform.dapi.v0.GetDocumentsResponse\x12\xa5\x01\n\x1egetIdentitiesByPublicKeyHashes\x12@.org.dash.platform.dapi.v0.GetIdentitiesByPublicKeyHashesRequest\x1a\x41.org.dash.platform.dapi.v0.GetIdentitiesByPublicKeyHashesResponse\x12\x9f\x01\n\x1cgetIdentityByPublicKeyHashes\x12>.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashesRequest\x1a?.org.dash.platform.dapi.v0.GetIdentityByPublicKeyHashesResponse\x12\x9f\x01\n\x1cwaitForStateTransitionResult\x12>.org.dash.platform.dapi.v0.WaitForStateTransitionResultRequest\x1a?.org.dash.platform.dapi.v0.WaitForStateTransitionResultResponse\x12\x81\x01\n\x12getConsensusParams\x12\x34.org.dash.platform.dapi.v0.GetConsensusParamsRequest\x1a\x35.org.dash.platform.dapi.v0.GetConsensusParamsResponseb\x06proto3' , dependencies=[google_dot_protobuf_dot_wrappers__pb2.DESCRIPTOR,google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,]) @@ -1922,7 +1922,7 @@ is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( - name='start_at_seconds', full_name='org.dash.platform.dapi.v0.GetDataContractHistoryRequest.start_at_seconds', index=3, + name='start_at_ms', full_name='org.dash.platform.dapi.v0.GetDataContractHistoryRequest.start_at_ms', index=3, number=4, type=4, cpp_type=4, label=1, has_default_value=False, default_value=0, message_type=None, enum_type=None, containing_type=None, @@ -1946,58 +1946,12 @@ syntax='proto3', extension_ranges=[], oneofs=[ - _descriptor.OneofDescriptor( - name='_limit', full_name='org.dash.platform.dapi.v0.GetDataContractHistoryRequest._limit', - index=0, containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[]), - _descriptor.OneofDescriptor( - name='_offset', full_name='org.dash.platform.dapi.v0.GetDataContractHistoryRequest._offset', - index=1, containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[]), - _descriptor.OneofDescriptor( - name='_start_at_seconds', full_name='org.dash.platform.dapi.v0.GetDataContractHistoryRequest._start_at_seconds', - index=2, containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[]), ], - serialized_start=5712, - serialized_end=5884, + serialized_start=5711, + serialized_end=5821, ) -_GETDATACONTRACTHISTORYRESPONSE_DATACONTRACTVALUE = _descriptor.Descriptor( - name='DataContractValue', - full_name='org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue', - filename=None, - file=DESCRIPTOR, - containing_type=None, - create_key=_descriptor._internal_create_key, - fields=[ - _descriptor.FieldDescriptor( - name='value', full_name='org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.value', index=0, - number=1, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=b"", - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=5426, - serialized_end=5460, -) - _GETDATACONTRACTHISTORYRESPONSE_DATACONTRACTHISTORYENTRY = _descriptor.Descriptor( name='DataContractHistoryEntry', full_name='org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry', @@ -2015,8 +1969,8 @@ serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), _descriptor.FieldDescriptor( name='value', full_name='org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.value', index=1, - number=2, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), @@ -2032,8 +1986,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6184, - serialized_end=6316, + serialized_start=6084, + serialized_end=6139, ) _GETDATACONTRACTHISTORYRESPONSE_DATACONTRACTHISTORY = _descriptor.Descriptor( @@ -2063,8 +2017,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6319, - serialized_end=6455, + serialized_start=6142, + serialized_end=6278, ) _GETDATACONTRACTHISTORYRESPONSE = _descriptor.Descriptor( @@ -2099,7 +2053,7 @@ ], extensions=[ ], - nested_types=[_GETDATACONTRACTHISTORYRESPONSE_DATACONTRACTVALUE, _GETDATACONTRACTHISTORYRESPONSE_DATACONTRACTHISTORYENTRY, _GETDATACONTRACTHISTORYRESPONSE_DATACONTRACTHISTORY, ], + nested_types=[_GETDATACONTRACTHISTORYRESPONSE_DATACONTRACTHISTORYENTRY, _GETDATACONTRACTHISTORYRESPONSE_DATACONTRACTHISTORY, ], enum_types=[ ], serialized_options=None, @@ -2113,8 +2067,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=5887, - serialized_end=6465, + serialized_start=5824, + serialized_end=6288, ) @@ -2199,8 +2153,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=6468, - serialized_end=6653, + serialized_start=6291, + serialized_end=6476, ) @@ -2231,8 +2185,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6874, - serialized_end=6904, + serialized_start=6697, + serialized_end=6727, ) _GETDOCUMENTSRESPONSE = _descriptor.Descriptor( @@ -2281,8 +2235,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=6656, - serialized_end=6914, + serialized_start=6479, + serialized_end=6737, ) @@ -2320,8 +2274,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=6916, - serialized_end=6997, + serialized_start=6739, + serialized_end=6820, ) @@ -2352,8 +2306,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7256, - serialized_end=7288, + serialized_start=7079, + serialized_end=7111, ) _GETIDENTITIESBYPUBLICKEYHASHESRESPONSE = _descriptor.Descriptor( @@ -2402,8 +2356,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=7000, - serialized_end=7298, + serialized_start=6823, + serialized_end=7121, ) @@ -2441,8 +2395,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7300, - serialized_end=7377, + serialized_start=7123, + serialized_end=7200, ) @@ -2492,8 +2446,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=7380, - serialized_end=7562, + serialized_start=7203, + serialized_end=7385, ) @@ -2531,8 +2485,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7564, - serialized_end=7647, + serialized_start=7387, + serialized_end=7470, ) @@ -2582,8 +2536,8 @@ create_key=_descriptor._internal_create_key, fields=[]), ], - serialized_start=7650, - serialized_end=7887, + serialized_start=7473, + serialized_end=7710, ) @@ -2628,8 +2582,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7889, - serialized_end=7969, + serialized_start=7712, + serialized_end=7792, ) @@ -2674,8 +2628,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=7971, - serialized_end=8069, + serialized_start=7794, + serialized_end=7892, ) @@ -2713,8 +2667,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8071, - serialized_end=8129, + serialized_start=7894, + serialized_end=7952, ) @@ -2752,8 +2706,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=8132, - serialized_end=8294, + serialized_start=7955, + serialized_end=8117, ) _GETIDENTITYRESPONSE.fields_by_name['proof'].message_type = _PROOF @@ -2885,17 +2839,6 @@ _GETDATACONTRACTSRESPONSE.oneofs_by_name['result'].fields.append( _GETDATACONTRACTSRESPONSE.fields_by_name['proof']) _GETDATACONTRACTSRESPONSE.fields_by_name['proof'].containing_oneof = _GETDATACONTRACTSRESPONSE.oneofs_by_name['result'] -_GETDATACONTRACTHISTORYREQUEST.oneofs_by_name['_limit'].fields.append( - _GETDATACONTRACTHISTORYREQUEST.fields_by_name['limit']) -_GETDATACONTRACTHISTORYREQUEST.fields_by_name['limit'].containing_oneof = _GETDATACONTRACTHISTORYREQUEST.oneofs_by_name['_limit'] -_GETDATACONTRACTHISTORYREQUEST.oneofs_by_name['_offset'].fields.append( - _GETDATACONTRACTHISTORYREQUEST.fields_by_name['offset']) -_GETDATACONTRACTHISTORYREQUEST.fields_by_name['offset'].containing_oneof = _GETDATACONTRACTHISTORYREQUEST.oneofs_by_name['_offset'] -_GETDATACONTRACTHISTORYREQUEST.oneofs_by_name['_start_at_seconds'].fields.append( - _GETDATACONTRACTHISTORYREQUEST.fields_by_name['start_at_seconds']) -_GETDATACONTRACTHISTORYREQUEST.fields_by_name['start_at_seconds'].containing_oneof = _GETDATACONTRACTHISTORYREQUEST.oneofs_by_name['_start_at_seconds'] -_GETDATACONTRACTHISTORYRESPONSE_DATACONTRACTVALUE.containing_type = _GETDATACONTRACTHISTORYRESPONSE -_GETDATACONTRACTHISTORYRESPONSE_DATACONTRACTHISTORYENTRY.fields_by_name['value'].message_type = _GETDATACONTRACTHISTORYRESPONSE_DATACONTRACTVALUE _GETDATACONTRACTHISTORYRESPONSE_DATACONTRACTHISTORYENTRY.containing_type = _GETDATACONTRACTHISTORYRESPONSE _GETDATACONTRACTHISTORYRESPONSE_DATACONTRACTHISTORY.fields_by_name['data_contract_entries'].message_type = _GETDATACONTRACTHISTORYRESPONSE_DATACONTRACTHISTORYENTRY _GETDATACONTRACTHISTORYRESPONSE_DATACONTRACTHISTORY.containing_type = _GETDATACONTRACTHISTORYRESPONSE @@ -3330,13 +3273,6 @@ GetDataContractHistoryResponse = _reflection.GeneratedProtocolMessageType('GetDataContractHistoryResponse', (_message.Message,), { - 'DataContractValue' : _reflection.GeneratedProtocolMessageType('DataContractValue', (_message.Message,), { - 'DESCRIPTOR' : _GETDATACONTRACTHISTORYRESPONSE_DATACONTRACTVALUE, - '__module__' : 'platform_pb2' - # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue) - }) - , - 'DataContractHistoryEntry' : _reflection.GeneratedProtocolMessageType('DataContractHistoryEntry', (_message.Message,), { 'DESCRIPTOR' : _GETDATACONTRACTHISTORYRESPONSE_DATACONTRACTHISTORYENTRY, '__module__' : 'platform_pb2' @@ -3355,7 +3291,6 @@ # @@protoc_insertion_point(class_scope:org.dash.platform.dapi.v0.GetDataContractHistoryResponse) }) _sym_db.RegisterMessage(GetDataContractHistoryResponse) -_sym_db.RegisterMessage(GetDataContractHistoryResponse.DataContractValue) _sym_db.RegisterMessage(GetDataContractHistoryResponse.DataContractHistoryEntry) _sym_db.RegisterMessage(GetDataContractHistoryResponse.DataContractHistory) @@ -3471,8 +3406,8 @@ index=0, serialized_options=None, create_key=_descriptor._internal_create_key, - serialized_start=8297, - serialized_end=10164, + serialized_start=8120, + serialized_end=10131, methods=[ _descriptor.MethodDescriptor( name='broadcastStateTransition', @@ -3554,10 +3489,20 @@ serialized_options=None, create_key=_descriptor._internal_create_key, ), + _descriptor.MethodDescriptor( + name='getDataContractHistory', + full_name='org.dash.platform.dapi.v0.Platform.getDataContractHistory', + index=8, + containing_service=None, + input_type=_GETDATACONTRACTHISTORYREQUEST, + output_type=_GETDATACONTRACTHISTORYRESPONSE, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), _descriptor.MethodDescriptor( name='getDataContracts', full_name='org.dash.platform.dapi.v0.Platform.getDataContracts', - index=8, + index=9, containing_service=None, input_type=_GETDATACONTRACTSREQUEST, output_type=_GETDATACONTRACTSRESPONSE, @@ -3567,7 +3512,7 @@ _descriptor.MethodDescriptor( name='getDocuments', full_name='org.dash.platform.dapi.v0.Platform.getDocuments', - index=9, + index=10, containing_service=None, input_type=_GETDOCUMENTSREQUEST, output_type=_GETDOCUMENTSRESPONSE, @@ -3577,7 +3522,7 @@ _descriptor.MethodDescriptor( name='getIdentitiesByPublicKeyHashes', full_name='org.dash.platform.dapi.v0.Platform.getIdentitiesByPublicKeyHashes', - index=10, + index=11, containing_service=None, input_type=_GETIDENTITIESBYPUBLICKEYHASHESREQUEST, output_type=_GETIDENTITIESBYPUBLICKEYHASHESRESPONSE, @@ -3587,7 +3532,7 @@ _descriptor.MethodDescriptor( name='getIdentityByPublicKeyHashes', full_name='org.dash.platform.dapi.v0.Platform.getIdentityByPublicKeyHashes', - index=11, + index=12, containing_service=None, input_type=_GETIDENTITYBYPUBLICKEYHASHESREQUEST, output_type=_GETIDENTITYBYPUBLICKEYHASHESRESPONSE, @@ -3597,7 +3542,7 @@ _descriptor.MethodDescriptor( name='waitForStateTransitionResult', full_name='org.dash.platform.dapi.v0.Platform.waitForStateTransitionResult', - index=12, + index=13, containing_service=None, input_type=_WAITFORSTATETRANSITIONRESULTREQUEST, output_type=_WAITFORSTATETRANSITIONRESULTRESPONSE, @@ -3607,7 +3552,7 @@ _descriptor.MethodDescriptor( name='getConsensusParams', full_name='org.dash.platform.dapi.v0.Platform.getConsensusParams', - index=13, + index=14, containing_service=None, input_type=_GETCONSENSUSPARAMSREQUEST, output_type=_GETCONSENSUSPARAMSRESPONSE, diff --git a/packages/dapi-grpc/clients/platform/v0/python/platform_pb2_grpc.py b/packages/dapi-grpc/clients/platform/v0/python/platform_pb2_grpc.py index a2c2552244..1c64357d6e 100644 --- a/packages/dapi-grpc/clients/platform/v0/python/platform_pb2_grpc.py +++ b/packages/dapi-grpc/clients/platform/v0/python/platform_pb2_grpc.py @@ -54,6 +54,11 @@ def __init__(self, channel): request_serializer=platform__pb2.GetDataContractRequest.SerializeToString, response_deserializer=platform__pb2.GetDataContractResponse.FromString, ) + self.getDataContractHistory = channel.unary_unary( + '/org.dash.platform.dapi.v0.Platform/getDataContractHistory', + request_serializer=platform__pb2.GetDataContractHistoryRequest.SerializeToString, + response_deserializer=platform__pb2.GetDataContractHistoryResponse.FromString, + ) self.getDataContracts = channel.unary_unary( '/org.dash.platform.dapi.v0.Platform/getDataContracts', request_serializer=platform__pb2.GetDataContractsRequest.SerializeToString, @@ -138,6 +143,12 @@ def getDataContract(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') + def getDataContractHistory(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + def getDataContracts(self, request, context): """Missing associated documentation comment in .proto file.""" context.set_code(grpc.StatusCode.UNIMPLEMENTED) @@ -217,6 +228,11 @@ def add_PlatformServicer_to_server(servicer, server): request_deserializer=platform__pb2.GetDataContractRequest.FromString, response_serializer=platform__pb2.GetDataContractResponse.SerializeToString, ), + 'getDataContractHistory': grpc.unary_unary_rpc_method_handler( + servicer.getDataContractHistory, + request_deserializer=platform__pb2.GetDataContractHistoryRequest.FromString, + response_serializer=platform__pb2.GetDataContractHistoryResponse.SerializeToString, + ), 'getDataContracts': grpc.unary_unary_rpc_method_handler( servicer.getDataContracts, request_deserializer=platform__pb2.GetDataContractsRequest.FromString, @@ -393,6 +409,23 @@ def getDataContract(request, options, channel_credentials, insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + @staticmethod + def getDataContractHistory(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/org.dash.platform.dapi.v0.Platform/getDataContractHistory', + platform__pb2.GetDataContractHistoryRequest.SerializeToString, + platform__pb2.GetDataContractHistoryResponse.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + @staticmethod def getDataContracts(request, target, diff --git a/packages/dapi-grpc/clients/platform/v0/web/PlatformPromiseClient.js b/packages/dapi-grpc/clients/platform/v0/web/PlatformPromiseClient.js index 46700f2722..8894ee87e9 100644 --- a/packages/dapi-grpc/clients/platform/v0/web/PlatformPromiseClient.js +++ b/packages/dapi-grpc/clients/platform/v0/web/PlatformPromiseClient.js @@ -56,6 +56,21 @@ class PlatformPromiseClient { ); } + /** + * + * @param {!GetDataContractHistoryRequest} getDataContractHistoryRequest + * @param {?Object} metadata + * @returns {Promise} + */ + getDataContractHistory(getDataContractHistoryRequest, metadata = {}) { + return promisify( + this.client.getDataContractHistory.bind(this.client), + )( + getDataContractHistoryRequest, + metadata, + ); + } + /** * * @param {!GetDocumentsRequest} getDocumentsRequest diff --git a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.d.ts b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.d.ts index 749494d20b..8dcadb9d88 100644 --- a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.d.ts +++ b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.d.ts @@ -1252,20 +1252,14 @@ export class GetDataContractHistoryRequest extends jspb.Message { getId_asB64(): string; setId(value: Uint8Array | string): void; - hasLimit(): boolean; - clearLimit(): void; getLimit(): number; setLimit(value: number): void; - hasOffset(): boolean; - clearOffset(): void; getOffset(): number; setOffset(value: number): void; - hasStartAtSeconds(): boolean; - clearStartAtSeconds(): void; - getStartAtSeconds(): number; - setStartAtSeconds(value: number): void; + getStartAtMs(): number; + setStartAtMs(value: number): void; getProve(): boolean; setProve(value: boolean): void; @@ -1285,7 +1279,7 @@ export namespace GetDataContractHistoryRequest { id: Uint8Array | string, limit: number, offset: number, - startAtSeconds: number, + startAtMs: number, prove: boolean, } } @@ -1324,36 +1318,14 @@ export namespace GetDataContractHistoryResponse { metadata?: ResponseMetadata.AsObject, } - export class DataContractValue extends jspb.Message { - getValue(): Uint8Array | string; - getValue_asU8(): Uint8Array; - getValue_asB64(): string; - setValue(value: Uint8Array | string): void; - - serializeBinary(): Uint8Array; - toObject(includeInstance?: boolean): DataContractValue.AsObject; - static toObject(includeInstance: boolean, msg: DataContractValue): DataContractValue.AsObject; - static extensions: {[key: number]: jspb.ExtensionFieldInfo}; - static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; - static serializeBinaryToWriter(message: DataContractValue, writer: jspb.BinaryWriter): void; - static deserializeBinary(bytes: Uint8Array): DataContractValue; - static deserializeBinaryFromReader(message: DataContractValue, reader: jspb.BinaryReader): DataContractValue; - } - - export namespace DataContractValue { - export type AsObject = { - value: Uint8Array | string, - } - } - export class DataContractHistoryEntry extends jspb.Message { getDate(): number; setDate(value: number): void; - hasValue(): boolean; - clearValue(): void; - getValue(): GetDataContractHistoryResponse.DataContractValue | undefined; - setValue(value?: GetDataContractHistoryResponse.DataContractValue): void; + getValue(): Uint8Array | string; + getValue_asU8(): Uint8Array; + getValue_asB64(): string; + setValue(value: Uint8Array | string): void; serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): DataContractHistoryEntry.AsObject; @@ -1368,7 +1340,7 @@ export namespace GetDataContractHistoryResponse { export namespace DataContractHistoryEntry { export type AsObject = { date: number, - value?: GetDataContractHistoryResponse.DataContractValue.AsObject, + value: Uint8Array | string, } } diff --git a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js index d1ce0d56c6..a570e7dbc6 100644 --- a/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js +++ b/packages/dapi-grpc/clients/platform/v0/web/platform_pb.js @@ -32,7 +32,6 @@ goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistory', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry', null, { proto }); -goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.ResultCase', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractRequest', null, { proto }); goog.exportSymbol('proto.org.dash.platform.dapi.v0.GetDataContractResponse', null, { proto }); @@ -1002,27 +1001,6 @@ if (goog.DEBUG && !COMPILED) { */ proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.displayName = 'proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse'; } -/** - * 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.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue = function(opt_data) { - jspb.Message.initialize(this, opt_data, 0, -1, null, null); -}; -goog.inherits(proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue, jspb.Message); -if (goog.DEBUG && !COMPILED) { - /** - * @public - * @override - */ - proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.displayName = 'proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue'; -} /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -10112,7 +10090,7 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.toObject = functio id: msg.getId_asB64(), limit: jspb.Message.getFieldWithDefault(msg, 2, 0), offset: jspb.Message.getFieldWithDefault(msg, 3, 0), - startAtSeconds: jspb.Message.getFieldWithDefault(msg, 4, 0), + startAtMs: jspb.Message.getFieldWithDefault(msg, 4, 0), prove: jspb.Message.getBooleanFieldWithDefault(msg, 5, false) }; @@ -10164,7 +10142,7 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.deserializeBinaryF break; case 4: var value = /** @type {number} */ (reader.readUint64()); - msg.setStartAtSeconds(value); + msg.setStartAtMs(value); break; case 5: var value = /** @type {boolean} */ (reader.readBool()); @@ -10206,22 +10184,22 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.serializeBinaryToW f ); } - f = /** @type {number} */ (jspb.Message.getField(message, 2)); - if (f != null) { + f = message.getLimit(); + if (f !== 0) { writer.writeUint32( 2, f ); } - f = /** @type {number} */ (jspb.Message.getField(message, 3)); - if (f != null) { + f = message.getOffset(); + if (f !== 0) { writer.writeUint32( 3, f ); } - f = /** @type {number} */ (jspb.Message.getField(message, 4)); - if (f != null) { + f = message.getStartAtMs(); + if (f !== 0) { writer.writeUint64( 4, f @@ -10293,25 +10271,7 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.getLimit * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest} returns this */ proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.setLimit = function(value) { - return jspb.Message.setField(this, 2, value); -}; - - -/** - * Clears the field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest} returns this - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.clearLimit = function() { - return jspb.Message.setField(this, 2, undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.hasLimit = function() { - return jspb.Message.getField(this, 2) != null; + return jspb.Message.setProto3IntField(this, 2, value); }; @@ -10329,33 +10289,15 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.getOffse * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest} returns this */ proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.setOffset = function(value) { - return jspb.Message.setField(this, 3, value); -}; - - -/** - * Clears the field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest} returns this - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.clearOffset = function() { - return jspb.Message.setField(this, 3, undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.hasOffset = function() { - return jspb.Message.getField(this, 3) != null; + return jspb.Message.setProto3IntField(this, 3, value); }; /** - * optional uint64 start_at_seconds = 4; + * optional uint64 start_at_ms = 4; * @return {number} */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.getStartAtSeconds = function() { +proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.getStartAtMs = function() { return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 4, 0)); }; @@ -10364,26 +10306,8 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.getStart * @param {number} value * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest} returns this */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.setStartAtSeconds = function(value) { - return jspb.Message.setField(this, 4, value); -}; - - -/** - * Clears the field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest} returns this - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.clearStartAtSeconds = function() { - return jspb.Message.setField(this, 4, undefined); -}; - - -/** - * Returns whether this field is set. - * @return {boolean} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.hasStartAtSeconds = function() { - return jspb.Message.getField(this, 4) != null; +proto.org.dash.platform.dapi.v0.GetDataContractHistoryRequest.prototype.setStartAtMs = function(value) { + return jspb.Message.setProto3IntField(this, 4, value); }; @@ -10576,160 +10500,6 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.serializeBinaryTo -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.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.prototype.toObject = function(opt_includeInstance) { - return proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.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.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} msg The msg instance to transform. - * @return {!Object} - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.toObject = function(includeInstance, msg) { - var f, obj = { - value: msg.getValue_asB64() - }; - - if (includeInstance) { - obj.$jspbMessageInstance = msg; - } - return obj; -}; -} - - -/** - * Deserializes binary data (in protobuf wire format). - * @param {jspb.ByteSource} bytes The bytes to deserialize. - * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.deserializeBinary = function(bytes) { - var reader = new jspb.BinaryReader(bytes); - var msg = new proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue; - return proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.deserializeBinaryFromReader(msg, reader); -}; - - -/** - * Deserializes binary data (in protobuf wire format) from the - * given reader into the given message object. - * @param {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} msg The message object to deserialize into. - * @param {!jspb.BinaryReader} reader The BinaryReader to use. - * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.deserializeBinaryFromReader = function(msg, reader) { - while (reader.nextField()) { - if (reader.isEndGroup()) { - break; - } - var field = reader.getFieldNumber(); - switch (field) { - case 1: - var value = /** @type {!Uint8Array} */ (reader.readBytes()); - msg.setValue(value); - break; - default: - reader.skipField(); - break; - } - } - return msg; -}; - - -/** - * Serializes the message to binary data (in protobuf wire format). - * @return {!Uint8Array} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.prototype.serializeBinary = function() { - var writer = new jspb.BinaryWriter(); - proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.serializeBinaryToWriter(this, writer); - return writer.getResultBuffer(); -}; - - -/** - * Serializes the given message to binary data (in protobuf wire - * format), writing to the given BinaryWriter. - * @param {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} message - * @param {!jspb.BinaryWriter} writer - * @suppress {unusedLocalVariables} f is only used for nested messages - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.serializeBinaryToWriter = function(message, writer) { - var f = undefined; - f = message.getValue_asU8(); - if (f.length > 0) { - writer.writeBytes( - 1, - f - ); - } -}; - - -/** - * optional bytes value = 1; - * @return {string} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.prototype.getValue = function() { - return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); -}; - - -/** - * optional bytes value = 1; - * This is a type-conversion wrapper around `getValue()` - * @return {string} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.prototype.getValue_asB64 = function() { - return /** @type {string} */ (jspb.Message.bytesAsB64( - this.getValue())); -}; - - -/** - * optional bytes value = 1; - * Note that Uint8Array is not supported on all browsers. - * @see http://caniuse.com/Uint8Array - * This is a type-conversion wrapper around `getValue()` - * @return {!Uint8Array} - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.prototype.getValue_asU8 = function() { - return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( - this.getValue())); -}; - - -/** - * @param {!(string|Uint8Array)} value - * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} returns this - */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.prototype.setValue = function(value) { - return jspb.Message.setProto3BytesField(this, 1, value); -}; - - - - - if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto. @@ -10760,7 +10530,7 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHisto proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.toObject = function(includeInstance, msg) { var f, obj = { date: jspb.Message.getFieldWithDefault(msg, 1, 0), - value: (f = msg.getValue()) && proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.toObject(includeInstance, f) + value: msg.getValue_asB64() }; if (includeInstance) { @@ -10802,8 +10572,7 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHisto msg.setDate(value); break; case 2: - var value = new proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue; - reader.readMessage(value,proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.deserializeBinaryFromReader); + var value = /** @type {!Uint8Array} */ (reader.readBytes()); msg.setValue(value); break; default: @@ -10842,12 +10611,11 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHisto f ); } - f = message.getValue(); - if (f != null) { - writer.writeMessage( + f = message.getValue_asU8(); + if (f.length > 0) { + writer.writeBytes( 2, - f, - proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue.serializeBinaryToWriter + f ); } }; @@ -10872,39 +10640,44 @@ proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHisto /** - * optional DataContractValue value = 2; - * @return {?proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} + * optional bytes value = 2; + * @return {string} */ proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.prototype.getValue = function() { - return /** @type{?proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue} */ ( - jspb.Message.getWrapperField(this, proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue, 2)); + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); }; /** - * @param {?proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractValue|undefined} value - * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry} returns this -*/ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.prototype.setValue = function(value) { - return jspb.Message.setWrapperField(this, 2, value); + * optional bytes value = 2; + * This is a type-conversion wrapper around `getValue()` + * @return {string} + */ +proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.prototype.getValue_asB64 = function() { + return /** @type {string} */ (jspb.Message.bytesAsB64( + this.getValue())); }; /** - * Clears the message field making it undefined. - * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry} returns this + * optional bytes value = 2; + * Note that Uint8Array is not supported on all browsers. + * @see http://caniuse.com/Uint8Array + * This is a type-conversion wrapper around `getValue()` + * @return {!Uint8Array} */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.prototype.clearValue = function() { - return this.setValue(undefined); +proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.prototype.getValue_asU8 = function() { + return /** @type {!Uint8Array} */ (jspb.Message.bytesAsU8( + this.getValue())); }; /** - * Returns whether this field is set. - * @return {boolean} + * @param {!(string|Uint8Array)} value + * @return {!proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry} returns this */ -proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.prototype.hasValue = function() { - return jspb.Message.getField(this, 2) != null; +proto.org.dash.platform.dapi.v0.GetDataContractHistoryResponse.DataContractHistoryEntry.prototype.setValue = function(value) { + return jspb.Message.setProto3BytesField(this, 2, value); }; diff --git a/packages/dapi-grpc/clients/platform/v0/web/platform_pb_service.d.ts b/packages/dapi-grpc/clients/platform/v0/web/platform_pb_service.d.ts index cdb3b20b6f..0c93826af4 100644 --- a/packages/dapi-grpc/clients/platform/v0/web/platform_pb_service.d.ts +++ b/packages/dapi-grpc/clients/platform/v0/web/platform_pb_service.d.ts @@ -76,6 +76,15 @@ type PlatformgetDataContract = { readonly responseType: typeof platform_pb.GetDataContractResponse; }; +type PlatformgetDataContractHistory = { + readonly methodName: string; + readonly service: typeof Platform; + readonly requestStream: false; + readonly responseStream: false; + readonly requestType: typeof platform_pb.GetDataContractHistoryRequest; + readonly responseType: typeof platform_pb.GetDataContractHistoryResponse; +}; + type PlatformgetDataContracts = { readonly methodName: string; readonly service: typeof Platform; @@ -140,6 +149,7 @@ export class Platform { static readonly getIdentityBalanceAndRevision: PlatformgetIdentityBalanceAndRevision; static readonly getProofs: PlatformgetProofs; static readonly getDataContract: PlatformgetDataContract; + static readonly getDataContractHistory: PlatformgetDataContractHistory; static readonly getDataContracts: PlatformgetDataContracts; static readonly getDocuments: PlatformgetDocuments; static readonly getIdentitiesByPublicKeyHashes: PlatformgetIdentitiesByPublicKeyHashes; @@ -252,6 +262,15 @@ export class PlatformClient { requestMessage: platform_pb.GetDataContractRequest, callback: (error: ServiceError|null, responseMessage: platform_pb.GetDataContractResponse|null) => void ): UnaryResponse; + getDataContractHistory( + requestMessage: platform_pb.GetDataContractHistoryRequest, + metadata: grpc.Metadata, + callback: (error: ServiceError|null, responseMessage: platform_pb.GetDataContractHistoryResponse|null) => void + ): UnaryResponse; + getDataContractHistory( + requestMessage: platform_pb.GetDataContractHistoryRequest, + callback: (error: ServiceError|null, responseMessage: platform_pb.GetDataContractHistoryResponse|null) => void + ): UnaryResponse; getDataContracts( requestMessage: platform_pb.GetDataContractsRequest, metadata: grpc.Metadata, diff --git a/packages/dapi-grpc/clients/platform/v0/web/platform_pb_service.js b/packages/dapi-grpc/clients/platform/v0/web/platform_pb_service.js index 1aac5e1c6b..bc65effa76 100644 --- a/packages/dapi-grpc/clients/platform/v0/web/platform_pb_service.js +++ b/packages/dapi-grpc/clients/platform/v0/web/platform_pb_service.js @@ -82,6 +82,15 @@ Platform.getDataContract = { responseType: platform_pb.GetDataContractResponse }; +Platform.getDataContractHistory = { + methodName: "getDataContractHistory", + service: Platform, + requestStream: false, + responseStream: false, + requestType: platform_pb.GetDataContractHistoryRequest, + responseType: platform_pb.GetDataContractHistoryResponse +}; + Platform.getDataContracts = { methodName: "getDataContracts", service: Platform, @@ -391,6 +400,37 @@ PlatformClient.prototype.getDataContract = function getDataContract(requestMessa }; }; +PlatformClient.prototype.getDataContractHistory = function getDataContractHistory(requestMessage, metadata, callback) { + if (arguments.length === 2) { + callback = arguments[1]; + } + var client = grpc.unary(Platform.getDataContractHistory, { + request: requestMessage, + host: this.serviceHost, + metadata: metadata, + transport: this.options.transport, + debug: this.options.debug, + onEnd: function (response) { + if (callback) { + if (response.status !== grpc.Code.OK) { + var err = new Error(response.statusMessage); + err.code = response.status; + err.metadata = response.trailers; + callback(err, null); + } else { + callback(null, response.message); + } + } + } + }); + return { + cancel: function () { + callback = null; + client.close(); + } + }; +}; + PlatformClient.prototype.getDataContracts = function getDataContracts(requestMessage, metadata, callback) { if (arguments.length === 2) { callback = arguments[1]; diff --git a/packages/dapi-grpc/protos/platform/v0/platform.proto b/packages/dapi-grpc/protos/platform/v0/platform.proto index b7351c02e6..d5953b78a9 100644 --- a/packages/dapi-grpc/protos/platform/v0/platform.proto +++ b/packages/dapi-grpc/protos/platform/v0/platform.proto @@ -17,6 +17,7 @@ service Platform { returns (GetIdentityBalanceAndRevisionResponse); rpc getProofs (GetProofsRequest) returns (GetProofsResponse); rpc getDataContract (GetDataContractRequest) returns (GetDataContractResponse); + rpc getDataContractHistory (GetDataContractHistoryRequest) returns (GetDataContractHistoryResponse); rpc getDataContracts (GetDataContractsRequest) returns (GetDataContractsResponse); rpc getDocuments (GetDocumentsRequest) returns (GetDocumentsResponse); rpc getIdentitiesByPublicKeyHashes (GetIdentitiesByPublicKeyHashesRequest) returns (GetIdentitiesByPublicKeyHashesResponse); @@ -269,20 +270,16 @@ message GetDataContractsResponse { message GetDataContractHistoryRequest { bytes id = 1; - optional uint32 limit = 2; - optional uint32 offset = 3; - optional uint64 start_at_seconds = 4; + uint32 limit = 2; + uint32 offset = 3; + uint64 start_at_ms = 4; bool prove = 5; } message GetDataContractHistoryResponse { - message DataContractValue { - bytes value = 1; - } - message DataContractHistoryEntry { uint64 date = 1; - DataContractValue value = 2; + bytes value = 2; } message DataContractHistory { diff --git a/packages/dapi/lib/externalApis/drive/DriveClient.js b/packages/dapi/lib/externalApis/drive/DriveClient.js index 8653cefe84..bf585f1cfa 100644 --- a/packages/dapi/lib/externalApis/drive/DriveClient.js +++ b/packages/dapi/lib/externalApis/drive/DriveClient.js @@ -64,6 +64,20 @@ class DriveClient { ); } + /** + * Fetch serialized data contract + * + * @param {GetDataContractHistoryRequest} request + * + * @return {Promise} + */ + async fetchDataContractHistory(request) { + return this.request( + '/dataContractHistory', + request.serializeBinary(), + ); + } + /** * Fetch serialized documents * diff --git a/packages/dapi/lib/grpcServer/handlers/platform/getDataContractHistoryHandlerFactory.js b/packages/dapi/lib/grpcServer/handlers/platform/getDataContractHistoryHandlerFactory.js new file mode 100644 index 0000000000..c9527ff518 --- /dev/null +++ b/packages/dapi/lib/grpcServer/handlers/platform/getDataContractHistoryHandlerFactory.js @@ -0,0 +1,43 @@ +const { + server: { + error: { + InvalidArgumentGrpcError, + }, + }, +} = require('@dashevo/grpc-common'); + +const { + v0: { + GetDataContractHistoryResponse, + }, +} = require('@dashevo/dapi-grpc'); + +/** + * @param {DriveClient} driveClient + * + * @returns {getDataContractHistoryHandler} + */ +function getDataContractHistoryHandlerFactory(driveClient) { + /** + * @typedef getDataContractHistoryHandler + * + * @param {Object} call + * + * @return {Promise} + */ + async function getDataContractHistoryHandler(call) { + const { request } = call; + + if (request.getId() === null) { + throw new InvalidArgumentGrpcError('id is not specified'); + } + + const dataContractHistoryResponseBuffer = await driveClient.fetchDataContractHistory(request); + + return GetDataContractHistoryResponse.deserializeBinary(dataContractHistoryResponseBuffer); + } + + return getDataContractHistoryHandler; +} + +module.exports = getDataContractHistoryHandlerFactory; diff --git a/packages/dapi/lib/grpcServer/handlers/platform/platformHandlersFactory.js b/packages/dapi/lib/grpcServer/handlers/platform/platformHandlersFactory.js index 668f8f2286..b993922416 100644 --- a/packages/dapi/lib/grpcServer/handlers/platform/platformHandlersFactory.js +++ b/packages/dapi/lib/grpcServer/handlers/platform/platformHandlersFactory.js @@ -18,6 +18,7 @@ const { BroadcastStateTransitionRequest, GetIdentityRequest, GetDataContractRequest, + GetDataContractHistoryRequest, GetDocumentsRequest, GetIdentitiesByPublicKeyHashesRequest, WaitForStateTransitionResultRequest, @@ -37,6 +38,8 @@ const { WaitForStateTransitionResultResponse: PBJSWaitForStateTransitionResultResponse, GetConsensusParamsRequest: PBJSGetConsensusParamsRequest, GetConsensusParamsResponse: PBJSGetConsensusParamsResponse, + GetDataContractHistoryRequest: PBJSGetDataContractHistoryRequest, + GetDataContractHistoryResponse: PBJSGetDataContractHistoryResponse, }, }, } = require('@dashevo/dapi-grpc'); @@ -57,6 +60,9 @@ const getDocumentsHandlerFactory = require( const getDataContractHandlerFactory = require( './getDataContractHandlerFactory', ); +const getDataContractHistoryHandlerFactory = require( + './getDataContractHistoryHandlerFactory', +); const getIdentitiesByPublicKeyHashesHandlerFactory = require( './getIdentitiesByPublicKeyHashesHandlerFactory', ); @@ -155,6 +161,22 @@ function platformHandlersFactory( wrapInErrorHandler(getDataContractHandler), ); + // getDataContractHistory + const getDataContractHistoryHandler = getDataContractHistoryHandlerFactory( + driveClient, + ); + + const wrappedGetDataContractHistory = jsonToProtobufHandlerWrapper( + jsonToProtobufFactory( + GetDataContractHistoryRequest, + PBJSGetDataContractHistoryRequest, + ), + protobufToJsonFactory( + PBJSGetDataContractHistoryResponse, + ), + wrapInErrorHandler(getDataContractHistoryHandler), + ); + // getIdentitiesByPublicKeyHashes const getIdentitiesByPublicKeyHashesHandler = getIdentitiesByPublicKeyHashesHandlerFactory( driveClient, @@ -222,6 +244,7 @@ function platformHandlersFactory( getIdentity: wrappedGetIdentity, getDocuments: wrappedGetDocuments, getDataContract: wrappedGetDataContract, + getDataContractHistory: wrappedGetDataContractHistory, getIdentitiesByPublicKeyHashes: wrappedGetIdentitiesByPublicKeyHashes, waitForStateTransitionResult: wrappedWaitForStateTransitionResult, getConsensusParams: wrappedGetConsensusParams, diff --git a/packages/js-dapi-client/lib/methods/platform/PlatformMethodsFacade.js b/packages/js-dapi-client/lib/methods/platform/PlatformMethodsFacade.js index b523b46980..cd4328e11a 100644 --- a/packages/js-dapi-client/lib/methods/platform/PlatformMethodsFacade.js +++ b/packages/js-dapi-client/lib/methods/platform/PlatformMethodsFacade.js @@ -1,5 +1,6 @@ const broadcastStateTransitionFactory = require('./broadcastStateTransition/broadcastStateTransitionFactory'); const getDataContractFactory = require('./getDataContract/getDataContractFactory'); +const getDataContractHistoryFactory = require('./getDataContractHistory/getDataContractHistoryFactory'); const getDocumentsFactory = require('./getDocuments/getDocumentsFactory'); const getIdentityFactory = require('./getIdentity/getIdentityFactory'); const getIdentitiesByPublicKeyHashesFactory = require('./getIdentitiesByPublicKeyHashes/getIdentitiesByPublicKeyHashesFactory'); @@ -13,6 +14,7 @@ class PlatformMethodsFacade { constructor(grpcTransport) { this.broadcastStateTransition = broadcastStateTransitionFactory(grpcTransport); this.getDataContract = getDataContractFactory(grpcTransport); + this.getDataContractHistory = getDataContractHistoryFactory(grpcTransport); this.getDocuments = getDocumentsFactory(grpcTransport); this.getIdentity = getIdentityFactory(grpcTransport); this.getIdentitiesByPublicKeyHashes = getIdentitiesByPublicKeyHashesFactory(grpcTransport); diff --git a/packages/js-dapi-client/lib/methods/platform/getDataContractHistory/GetDataContractHistoryResponse.js b/packages/js-dapi-client/lib/methods/platform/getDataContractHistory/GetDataContractHistoryResponse.js new file mode 100644 index 0000000000..1fba537ec5 --- /dev/null +++ b/packages/js-dapi-client/lib/methods/platform/getDataContractHistory/GetDataContractHistoryResponse.js @@ -0,0 +1,55 @@ +const AbstractResponse = require('../response/AbstractResponse'); +const InvalidResponseError = require('../response/errors/InvalidResponseError'); + +class GetDataContractHistoryResponse extends AbstractResponse { + /** + * @param {object.} dataContractHistory + * @param {Metadata} metadata + * @param {Proof} [proof] + */ + constructor(dataContractHistory, metadata, proof = undefined) { + super(metadata, proof); + + this.dataContractHistory = dataContractHistory; + } + + /** + * @returns {object.} + */ + getDataContractHistory() { + return this.dataContractHistory; + } + + /** + * @param proto + * @returns {GetDataContractHistoryResponse} + */ + static createFromProto(proto) { + // History is something that we need to call a method to get a list of entries on + const dataContractHistory = proto.getDataContractHistory(); + const { metadata, proof } = AbstractResponse.createMetadataAndProofFromProto(proto); + + if (!dataContractHistory && !proof) { + throw new InvalidResponseError('DataContract is not defined'); + } + + const history = {}; + + if (dataContractHistory) { + const dataContractHistoryEntries = dataContractHistory.getDataContractEntriesList(); + + // eslint-disable-next-line no-restricted-syntax + for (const historyEntry of dataContractHistoryEntries) { + history[historyEntry.getDate()] = historyEntry.getValue(); + } + } + + return new GetDataContractHistoryResponse( + history, + metadata, + proof, + ); + } +} + +module.exports = GetDataContractHistoryResponse; diff --git a/packages/js-dapi-client/lib/methods/platform/getDataContractHistory/getDataContractHistoryFactory.js b/packages/js-dapi-client/lib/methods/platform/getDataContractHistory/getDataContractHistoryFactory.js new file mode 100644 index 0000000000..815b4cbc98 --- /dev/null +++ b/packages/js-dapi-client/lib/methods/platform/getDataContractHistory/getDataContractHistoryFactory.js @@ -0,0 +1,81 @@ +const { + v0: { + PlatformPromiseClient, + GetDataContractHistoryRequest, + }, +} = require('@dashevo/dapi-grpc'); + +const GetDataContractHistoryResponse = require('./GetDataContractHistoryResponse'); +const InvalidResponseError = require('../response/errors/InvalidResponseError'); + +/** + * @param {GrpcTransport} grpcTransport + * @returns {getDataContractHistory} + */ +function getDataContractHistoryFactory(grpcTransport) { + /** + * Fetch Data Contract by id + * + * @typedef {getDataContractHistory} + * @param {Buffer} contractId + * @param {number} [startAtMs] + * @param {number} [limit] + * @param {number} [offset] + * @param {DAPIClientOptions & {prove: boolean}} [options] + * @returns {Promise} + */ + async function getDataContractHistory( + contractId, + startAtMs = 0, + limit = 10, + offset = 0, + options = {}, + ) { + const getDataContractHistoryRequest = new GetDataContractHistoryRequest(); + + // need to convert objects inherited from Buffer to pure buffer as google protobuf + // doesn't support extended buffers + // https://github.com/protocolbuffers/protobuf/blob/master/js/binary/utils.js#L1049 + if (Buffer.isBuffer(contractId)) { + // eslint-disable-next-line no-param-reassign + contractId = Buffer.from(contractId); + } + + getDataContractHistoryRequest.setId(contractId); + getDataContractHistoryRequest.setStartAtMs(startAtMs); + getDataContractHistoryRequest.setLimit(limit); + getDataContractHistoryRequest.setOffset(offset); + getDataContractHistoryRequest.setProve(!!options.prove); + + let lastError; + + // TODO: simple retry before the dapi versioning is properly implemented + for (let i = 0; i < 3; i += 1) { + try { + // eslint-disable-next-line no-await-in-loop + const getDataContractHistoryResponse = await grpcTransport.request( + PlatformPromiseClient, + 'getDataContractHistory', + getDataContractHistoryRequest, + options, + ); + + return GetDataContractHistoryResponse.createFromProto(getDataContractHistoryResponse); + } catch (e) { + if (e instanceof InvalidResponseError) { + lastError = e; + } else { + throw e; + } + } + } + + // If we made it past the cycle it means that the retry didn't work, + // and we're throwing the last error encountered + throw lastError; + } + + return getDataContractHistory; +} + +module.exports = getDataContractHistoryFactory; diff --git a/packages/js-dapi-client/test/unit/methods/platform/getDataContractHistory/GetDataContractHistoryResponse.spec.js b/packages/js-dapi-client/test/unit/methods/platform/getDataContractHistory/GetDataContractHistoryResponse.spec.js new file mode 100644 index 0000000000..a0f36fd74c --- /dev/null +++ b/packages/js-dapi-client/test/unit/methods/platform/getDataContractHistory/GetDataContractHistoryResponse.spec.js @@ -0,0 +1,198 @@ +const getDataContractFixture = require('@dashevo/dpp/lib/test/fixtures/getDataContractFixture'); +const { + v0: { + GetDataContractHistoryResponse, + ResponseMetadata, + Proof: ProofResponse, + }, +} = require('@dashevo/dapi-grpc'); + +const GetDataContractHistoryResponseClass = require('../../../../../lib/methods/platform/getDataContractHistory/GetDataContractHistoryResponse'); +const getMetadataFixture = require('../../../../../lib/test/fixtures/getMetadataFixture'); +const getProofFixture = require('../../../../../lib/test/fixtures/getProofFixture'); +const InvalidResponseError = require('../../../../../lib/methods/platform/response/errors/InvalidResponseError'); +const Proof = require('../../../../../lib/methods/platform/response/Proof'); +const Metadata = require('../../../../../lib/methods/platform/response/Metadata'); + +describe('GetDataContractHistoryResponse', () => { + let getDataContractHistoryResponse; + let metadataFixture; + let dataContractFixture; + let proofFixture; + let dataContractHistoryFixture; + + beforeEach(() => { + metadataFixture = getMetadataFixture(); + dataContractFixture = getDataContractFixture(); + dataContractHistoryFixture = { + 2000: dataContractFixture.toBuffer(), + 3000: dataContractFixture.toBuffer(), + }; + proofFixture = getProofFixture(); + + getDataContractHistoryResponse = new GetDataContractHistoryResponseClass( + dataContractHistoryFixture, + new Metadata(metadataFixture), + ); + }); + + it('should return data contract history', () => { + const dataContract = getDataContractHistoryResponse.getDataContractHistory(); + const proof = getDataContractHistoryResponse.getProof(); + + expect(dataContract).to.deep.equal(dataContractHistoryFixture); + expect(proof).to.equal(undefined); + }); + + it('should return proof', () => { + getDataContractHistoryResponse = new GetDataContractHistoryResponseClass( + {}, + new Metadata(metadataFixture), + new Proof(proofFixture), + ); + + const dataContract = getDataContractHistoryResponse.getDataContractHistory(); + const proof = getDataContractHistoryResponse.getProof(); + + expect(dataContract).to.deep.equal({}); + expect(proof).to.be.an.instanceOf(Proof); + expect(proof.getGrovedbProof()).to.deep.equal(proofFixture.merkleProof); + expect(proof.getQuorumHash()).to.deep.equal(proofFixture.quorumHash); + expect(proof.getSignature()).to.deep.equal(proofFixture.signature); + }); + + it('should create an instance from proto', () => { + const { + DataContractHistory, + DataContractHistoryEntry, + } = GetDataContractHistoryResponse; + + const dataContractHistoryEntryProto = new DataContractHistoryEntry(); + dataContractHistoryEntryProto.setDate(1000); + dataContractHistoryEntryProto.setValue(dataContractFixture.toBuffer()); + + const dataContractHistoryEntryProto2 = new DataContractHistoryEntry(); + dataContractHistoryEntryProto2.setDate(2000); + dataContractHistoryEntryProto2.setValue(dataContractFixture.toBuffer()); + + const dataContractHistoryProto = new DataContractHistory(); + dataContractHistoryProto.setDataContractEntriesList([ + dataContractHistoryEntryProto, + dataContractHistoryEntryProto2, + ]); + + // Each entry has date and value, and value also has a value? + + const proto = new GetDataContractHistoryResponse(); + proto.setDataContractHistory(dataContractHistoryProto); + + const metadata = new ResponseMetadata(); + metadata.setHeight(metadataFixture.height); + metadata.setCoreChainLockedHeight(metadataFixture.coreChainLockedHeight); + + proto.setMetadata(metadata); + + getDataContractHistoryResponse = GetDataContractHistoryResponseClass.createFromProto(proto); + + expect(getDataContractHistoryResponse).to.be.an.instanceOf(GetDataContractHistoryResponseClass); + expect(getDataContractHistoryResponse.getDataContractHistory()).to.deep.equal({ + 1000: dataContractFixture.toBuffer(), + 2000: dataContractFixture.toBuffer(), + }); + + expect(getDataContractHistoryResponse.getMetadata()) + .to.be.an.instanceOf(Metadata); + expect(getDataContractHistoryResponse.getMetadata().getHeight()) + .to.equal(metadataFixture.height); + expect(getDataContractHistoryResponse.getMetadata().getCoreChainLockedHeight()) + .to.equal(metadataFixture.coreChainLockedHeight); + + expect(getDataContractHistoryResponse.getProof()).to.equal(undefined); + }); + + it('should create an instance with proof from proto', () => { + const proofProto = new ProofResponse(); + + proofProto.setQuorumHash(proofFixture.quorumHash); + proofProto.setSignature(proofFixture.signature); + proofProto.setGrovedbProof(proofFixture.merkleProof); + + const proto = new GetDataContractHistoryResponse(); + + proto.setDataContractHistory(undefined); + proto.setProof(proofProto); + + const metadata = new ResponseMetadata(); + metadata.setHeight(metadataFixture.height); + metadata.setCoreChainLockedHeight(metadataFixture.coreChainLockedHeight); + + proto.setMetadata(metadata); + + getDataContractHistoryResponse = GetDataContractHistoryResponseClass.createFromProto(proto); + expect(getDataContractHistoryResponse).to.be.an.instanceOf(GetDataContractHistoryResponseClass); + expect(getDataContractHistoryResponse.getDataContractHistory()).to.deep.equal({}); + + expect(getDataContractHistoryResponse.getMetadata()) + .to.be.an.instanceOf(Metadata); + expect(getDataContractHistoryResponse.getMetadata().getHeight()) + .to.equal(metadataFixture.height); + expect(getDataContractHistoryResponse.getMetadata().getCoreChainLockedHeight()) + .to.equal(metadataFixture.coreChainLockedHeight); + + const proof = getDataContractHistoryResponse.getProof(); + + expect(proof).to.be.an.instanceOf(Proof); + expect(proof.getGrovedbProof()).to.deep.equal(proofFixture.merkleProof); + expect(proof.getQuorumHash()).to.deep.equal(proofFixture.quorumHash); + expect(proof.getSignature()).to.deep.equal(proofFixture.signature); + }); + + it('should throw InvalidResponseError if Metadata is not defined', () => { + const { + DataContractHistory, + DataContractHistoryEntry, + } = GetDataContractHistoryResponse; + + const dataContractHistoryEntryProto = new DataContractHistoryEntry(); + dataContractHistoryEntryProto.setDate(1000); + dataContractHistoryEntryProto.setValue(dataContractFixture.toBuffer()); + + const dataContractHistoryEntryProto2 = new DataContractHistoryEntry(); + dataContractHistoryEntryProto2.setDate(2000); + dataContractHistoryEntryProto2.setValue(dataContractFixture.toBuffer()); + + const dataContractHistoryProto = new DataContractHistory(); + dataContractHistoryProto.setDataContractEntriesList([ + dataContractHistoryEntryProto, + dataContractHistoryEntryProto2, + ]); + + const proto = new GetDataContractHistoryResponse(); + proto.setDataContractHistory(dataContractHistoryProto); + + try { + getDataContractHistoryResponse = GetDataContractHistoryResponseClass.createFromProto(proto); + + expect.fail('should throw InvalidResponseError'); + } catch (e) { + expect(e).to.be.an.instanceOf(InvalidResponseError); + } + }); + + it('should throw InvalidResponseError if DataContractHistory is not defined', () => { + const proto = new GetDataContractHistoryResponse(); + const metadata = new ResponseMetadata(); + metadata.setHeight(metadataFixture.height); + metadata.setCoreChainLockedHeight(metadataFixture.coreChainLockedHeight); + + proto.setMetadata(metadata); + + try { + getDataContractHistoryResponse = GetDataContractHistoryResponseClass.createFromProto(proto); + + expect.fail('should throw InvalidResponseError'); + } catch (e) { + expect(e).to.be.an.instanceOf(InvalidResponseError); + } + }); +}); diff --git a/packages/js-dapi-client/test/unit/methods/platform/getDataContractHistory/getDataContractHistoryFactory.spec.js b/packages/js-dapi-client/test/unit/methods/platform/getDataContractHistory/getDataContractHistoryFactory.spec.js new file mode 100644 index 0000000000..3f4dace9da --- /dev/null +++ b/packages/js-dapi-client/test/unit/methods/platform/getDataContractHistory/getDataContractHistoryFactory.spec.js @@ -0,0 +1,179 @@ +const { + v0: { + PlatformPromiseClient, + GetDataContractHistoryRequest, + GetDataContractHistoryResponse, + ResponseMetadata, + Proof, + }, +} = require('@dashevo/dapi-grpc'); + +const { + v0: { + GetDataContractHistoryResponse: { + DataContractHistory, + DataContractHistoryEntry, + }, + }, +} = require('@dashevo/dapi-grpc'); + +const getDataContractFixture = require('@dashevo/dpp/lib/test/fixtures/getDataContractFixture'); + +const getDataContractHistoryFactory = require('../../../../../lib/methods/platform/getDataContractHistory/getDataContractHistoryFactory'); +const getMetadataFixture = require('../../../../../lib/test/fixtures/getMetadataFixture'); +const getProofFixture = require('../../../../../lib/test/fixtures/getProofFixture'); +const ProofClass = require('../../../../../lib/methods/platform/response/Proof'); + +describe('getDataContractHistoryFactory', () => { + let grpcTransportMock; + let getDataContractHistory; + let options; + let response; + let dataContractFixture; + let dataContractHistoryFixture; + let metadataFixture; + let proofFixture; + let proof; + + beforeEach(function beforeEach() { + dataContractFixture = getDataContractFixture(); + dataContractHistoryFixture = { + 1000: dataContractFixture.toBuffer(), + 2000: dataContractFixture.toBuffer(), + }; + + const dataContractHistoryEntryProto = new DataContractHistoryEntry(); + dataContractHistoryEntryProto.setDate(1000); + dataContractHistoryEntryProto.setValue(dataContractFixture.toBuffer()); + + const dataContractHistoryEntryProto2 = new DataContractHistoryEntry(); + dataContractHistoryEntryProto2.setDate(2000); + dataContractHistoryEntryProto2.setValue(dataContractFixture.toBuffer()); + + const dataContractHistoryProto = new DataContractHistory(); + dataContractHistoryProto.setDataContractEntriesList([ + dataContractHistoryEntryProto, + dataContractHistoryEntryProto2, + ]); + + response = new GetDataContractHistoryResponse(); + response.setDataContractHistory(dataContractHistoryProto); + + metadataFixture = getMetadataFixture(); + proofFixture = getProofFixture(); + + const metadata = new ResponseMetadata(); + metadata.setHeight(metadataFixture.height); + metadata.setCoreChainLockedHeight(metadataFixture.coreChainLockedHeight); + metadata.setTimeMs(metadataFixture.timeMs); + metadata.setProtocolVersion(metadataFixture.protocolVersion); + + response.setMetadata(metadata); + + grpcTransportMock = { + request: this.sinon.stub().resolves(response), + }; + + options = { + timeout: 1000, + }; + + getDataContractHistory = getDataContractHistoryFactory(grpcTransportMock); + + proof = new Proof(); + + proof.setQuorumHash(proofFixture.quorumHash); + proof.setSignature(proofFixture.signature); + proof.setGrovedbProof(proofFixture.merkleProof); + proof.setRound(proofFixture.round); + }); + + it('should return data contract history', async () => { + const contractId = dataContractFixture.getId().toBuffer(); + const result = await getDataContractHistory(contractId, 0, 10, 0, options); + + const request = new GetDataContractHistoryRequest(); + request.setId(contractId); + request.setLimit(10); + request.setOffset(0); + request.setStartAtMs(0); + request.setProve(false); + + expect(grpcTransportMock.request.getCall(0).args).to.have.deep.members([ + PlatformPromiseClient, + 'getDataContractHistory', + request, + options, + ]); + expect(result.getDataContractHistory()).to.deep.equal(dataContractHistoryFixture); + expect(result.getProof()).to.equal(undefined); + expect(result.getMetadata()).to.deep.equal(metadataFixture); + expect(result.getMetadata().getHeight()).to.equal(metadataFixture.height); + expect(result.getMetadata().getCoreChainLockedHeight()).to.equal( + metadataFixture.coreChainLockedHeight, + ); + }); + + it('should return proof', async () => { + options.prove = true; + response.setProof(proof); + response.setDataContractHistory(undefined); + + const contractId = dataContractFixture.getId().toBuffer(); + const result = await getDataContractHistory(contractId, 0, 10, 0, options); + + const request = new GetDataContractHistoryRequest(); + request.setId(contractId); + request.setLimit(10); + request.setOffset(0); + request.setStartAtMs(0); + request.setProve(true); + + expect(grpcTransportMock.request.getCall(0).args).to.have.deep.members([ + PlatformPromiseClient, + 'getDataContractHistory', + request, + options, + ]); + + expect(result.getDataContractHistory()).to.deep.equal({}); + expect(result.getProof()).to.be.an.instanceOf(ProofClass); + expect(result.getProof().getGrovedbProof()).to.deep.equal(proofFixture.merkleProof); + expect(result.getProof().getQuorumHash()).to.deep.equal(proofFixture.quorumHash); + expect(result.getProof().getSignature()).to.deep.equal(proofFixture.signature); + expect(result.getProof().getRound()).to.deep.equal(proofFixture.round); + expect(result.getMetadata()).to.deep.equal(metadataFixture); + expect(result.getMetadata().getHeight()).to.equal(metadataFixture.height); + expect(result.getMetadata().getCoreChainLockedHeight()).to.equal( + metadataFixture.coreChainLockedHeight, + ); + }); + + it('should throw unknown error', async () => { + const error = new Error('Unknown found'); + const contractId = dataContractFixture.getId(); + + grpcTransportMock.request.throws(error); + + const request = new GetDataContractHistoryRequest(); + request.setId(contractId.toBuffer()); + request.setLimit(10); + request.setOffset(0); + request.setStartAtMs(0); + request.setProve(false); + + try { + await getDataContractHistory(contractId, 0, 10, 0, options); + + expect.fail('should throw unknown error'); + } catch (e) { + expect(e).to.deep.equal(error); + expect(grpcTransportMock.request).to.be.calledOnceWithExactly( + PlatformPromiseClient, + 'getDataContractHistory', + request, + options, + ); + } + }); +}); diff --git a/packages/js-dash-sdk/src/SDK/Client/Platform/Fetcher/Fetcher.ts b/packages/js-dash-sdk/src/SDK/Client/Platform/Fetcher/Fetcher.ts index 68679ed6d3..dccb83e80b 100644 --- a/packages/js-dash-sdk/src/SDK/Client/Platform/Fetcher/Fetcher.ts +++ b/packages/js-dash-sdk/src/SDK/Client/Platform/Fetcher/Fetcher.ts @@ -1,12 +1,12 @@ import DAPIClient from '@dashevo/dapi-client'; import { Identifier } from '@dashevo/wasm-dpp/dist'; -import { - GetDataContractResponse, - GetIdentityResponse, -} from '@dashevo/dapi-grpc/clients/platform/v0/web/platform_pb'; +import { GetDataContractResponse, GetIdentityResponse } from '@dashevo/dapi-grpc/clients/platform/v0/web/platform_pb'; import NotFoundError from '@dashevo/dapi-client/lib/transport/GrpcTransport/errors/NotFoundError'; import { GetDocumentsResponse } from '@dashevo/dapi-client/lib/methods/platform/getDocuments/GetDocumentsResponse'; +import { + GetDataContractHistoryResponse, +} from '@dashevo/dapi-client/lib/methods/platform/getDataContractHistory/GetDataContractHistoryResponse'; import withRetry from './withRetry'; import { QueryOptions } from '../types'; @@ -137,6 +137,27 @@ class Fetcher { return withRetry(query, retryAttempts, this.delayMulMs); } + /** + * Fetches data contract by it's ID + * @param id + * @param startAMs + * @param limit + * @param offset + */ + public async fetchDataContractHistory( + id: Identifier, startAMs: number, limit: number, offset: number, + ): Promise { + // Define query + const query = async (): Promise => await this + .dapiClient.platform.getDataContractHistory(id, startAMs, limit, offset); + + // Define retry attempts. + // In case we acknowledged this identifier, we want to retry to mitigate + // state transition propagation lag. Otherwise, we want to try only once. + const retryAttempts = this.hasIdentifier(id) ? this.maxAttempts : 1; + return withRetry(query, retryAttempts, this.delayMulMs); + } + /** * Fetches documents by data contract id and type * @param {Identifier} contractId - data contract ID diff --git a/packages/js-dash-sdk/src/SDK/Client/Platform/Platform.ts b/packages/js-dash-sdk/src/SDK/Client/Platform/Platform.ts index 98f62da217..00ed0260fd 100644 --- a/packages/js-dash-sdk/src/SDK/Client/Platform/Platform.ts +++ b/packages/js-dash-sdk/src/SDK/Client/Platform/Platform.ts @@ -18,6 +18,7 @@ import publishContract from './methods/contracts/publish'; import updateContract from './methods/contracts/update'; import createContract from './methods/contracts/create'; import getContract from './methods/contracts/get'; +import getContractHistory from './methods/contracts/history'; import getIdentity from './methods/identities/get'; import registerIdentity from './methods/identities/register'; @@ -95,6 +96,7 @@ interface DataContracts { publish: Function, create: Function, get: Function, + history: Function, } /** @@ -169,6 +171,7 @@ export class Platform { update: updateContract.bind(this), create: createContract.bind(this), get: getContract.bind(this), + history: getContractHistory.bind(this), }; this.names = { register: registerName.bind(this), diff --git a/packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/history.spec.ts b/packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/history.spec.ts new file mode 100644 index 0000000000..acf9ae6867 --- /dev/null +++ b/packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/history.spec.ts @@ -0,0 +1,111 @@ +import { expect } from 'chai'; + +import loadDpp from '@dashevo/wasm-dpp'; + +import getDataContractFixture from '@dashevo/wasm-dpp/lib/test/fixtures/getDataContractFixture'; + +import getResponseMetadataFixture from '../../../../../test/fixtures/getResponseMetadataFixture'; +import history from './history'; +import identitiesFixtures from '../../../../../../tests/fixtures/identities.json'; +import 'mocha'; +import { ClientApps } from '../../../ClientApps'; + +const GetDataContractHistoryResponse = require('@dashevo/dapi-client/lib/methods/platform/getDataContractHistory/GetDataContractHistoryResponse'); +const NotFoundError = require('@dashevo/dapi-client/lib/transport/GrpcTransport/errors/NotFoundError'); + +let client; +let fetcher; +let askedFromDapi; +let initialize; +let metadataFixture; +let dataContractFixture; + +const factory = { + createFromBuffer: () => dataContractFixture, +}; + +const dpp = { + dataContract: factory, + getProtocolVersion: () => 42, +}; + +const logger = { + debug: () => {}, + silly: () => {}, +}; + +let apps; + +describe('Client - Platform - Contracts - .history()', () => { + before(async function before() { + await loadDpp(); + + dataContractFixture = await getDataContractFixture(); + metadataFixture = getResponseMetadataFixture(); + + apps = new ClientApps({ + ratePlatform: { + contractId: dataContractFixture.getId(), + }, + }); + + askedFromDapi = 0; + const fetchDataContractHistory = async (id) => { + const fixtureIdentifier = dataContractFixture.getId(); + askedFromDapi += 1; + + if (id.equals(fixtureIdentifier)) { + return new GetDataContractHistoryResponse( + { 1000: dataContractFixture.toBuffer() }, + metadataFixture, + ); + } + + throw new NotFoundError(); + }; + + fetcher = { + fetchDataContractHistory, + }; + + client = { + getApps(): ClientApps { + return apps; + }, + }; + + initialize = this.sinon.stub(); + }); + + describe('get a contract from string', () => { + it('should get from DAPIClient if there is none locally', async () => { + const contractHistory = await history.call({ + // @ts-ignore + apps, dpp, client, initialize, logger, fetcher, + }, dataContractFixture.getId(), 0, 10, 0); + const contract = contractHistory[1000]; + expect(contract.toJSON()).to.deep.equal(dataContractFixture.toJSON()); + expect(askedFromDapi).to.equal(1); + }); + + it('should get from local when already fetched once', async () => { + const contractHistory = await history.call({ + // @ts-ignore + apps, dpp, client, initialize, logger, fetcher, + }, dataContractFixture.getId(), 0, 10, 0); + const contract = contractHistory[1000]; + expect(contract.toJSON()).to.deep.equal(dataContractFixture.toJSON()); + expect(askedFromDapi).to.equal(2); + }); + }); + + describe('other conditions', () => { + it('should deal when contract do not exist', async () => { + const contract = await history.call({ + // @ts-ignore + apps, dpp, client, initialize, logger, fetcher, + }, identitiesFixtures.bob.id, 0, 10, 0); + expect(contract).to.equal(null); + }); + }); +}); diff --git a/packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/history.ts b/packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/history.ts new file mode 100644 index 0000000000..4116396706 --- /dev/null +++ b/packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/history.ts @@ -0,0 +1,61 @@ +// @ts-ignore +import { DataContract, Identifier } from '@dashevo/wasm-dpp'; +import { + GetDataContractHistoryResponse, +} from '@dashevo/dapi-client/lib/methods/platform/getDataContractHistory/GetDataContractHistoryResponse'; +import { Platform } from '../../Platform'; + +const NotFoundError = require('@dashevo/dapi-client/lib/transport/GrpcTransport/errors/NotFoundError'); + +declare type ContractIdentifier = string | Identifier; + +/** + * Get contracts from the platform + * + * @param {ContractIdentifier} identifier - identifier of the contract to fetch + * @param startAtMs + * @param limit + * @param offset + * @returns contracts + */ +export async function history( + this: Platform, + identifier: ContractIdentifier, + startAtMs: number, + limit: number, + offset: number, +): Promise { + this.logger.debug(`[Contracts#history] Get Data Contract History for "${identifier}"`); + await this.initialize(); + + const contractId : Identifier = Identifier.from(identifier); + + let dataContractHistoryResponse: GetDataContractHistoryResponse; + try { + dataContractHistoryResponse = await this.fetcher.fetchDataContractHistory( + contractId, startAtMs, limit, offset, + ); + this.logger.silly(`[Contracts#history] Fetched Data Contract History for "${identifier}"`); + } catch (e) { + if (e instanceof NotFoundError) { + return null; + } + + throw e; + } + + const rawContractHistory = dataContractHistoryResponse.getDataContractHistory(); + const contractHistory: { [key: number]: DataContract } = {}; + + // eslint-disable-next-line no-restricted-syntax + for (const [date, contractBytes] of Object.entries(rawContractHistory)) { + contractHistory[date] = await this.dpp.dataContract + .createFromBuffer(contractBytes as Uint8Array); + } + + this.logger.debug(`[Contracts#history] Obtained Data Contract history for "${identifier}"`); + + return contractHistory; +} + +export default history; diff --git a/packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/update.ts b/packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/update.ts index 78fb15e0f8..f32e8c84de 100644 --- a/packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/update.ts +++ b/packages/js-dash-sdk/src/SDK/Client/Platform/methods/contracts/update.ts @@ -21,9 +21,7 @@ export default async function update( const { dpp } = this; // Clone contract - const updatedDataContract = await dpp.dataContract.createFromObject( - dataContract.toObject(), - ); + const updatedDataContract = dataContract.clone(); updatedDataContract.incrementVersion(); diff --git a/packages/platform-test-suite/lib/test/fixtures/getDataContractFixture.js b/packages/platform-test-suite/lib/test/fixtures/getDataContractFixture.js index f8bb284ac7..9e2978e315 100644 --- a/packages/platform-test-suite/lib/test/fixtures/getDataContractFixture.js +++ b/packages/platform-test-suite/lib/test/fixtures/getDataContractFixture.js @@ -140,5 +140,13 @@ module.exports = async function getDataContractFixture( entropyGenerator, ); - return factory.create(ownerId, documents); + const config = { + canBeDeleted: false, + readonly: false, + keepsHistory: true, + documentsKeepHistoryContractDefault: false, + documentsMutableContractDefault: true, + }; + + return factory.create(ownerId, documents, config); }; diff --git a/packages/platform-test-suite/test/functional/platform/DataContract.spec.js b/packages/platform-test-suite/test/functional/platform/DataContract.spec.js index 9a2c3c095e..7d33c6394b 100644 --- a/packages/platform-test-suite/test/functional/platform/DataContract.spec.js +++ b/packages/platform-test-suite/test/functional/platform/DataContract.spec.js @@ -26,9 +26,11 @@ describe('Platform', () => { before(async () => { dataContractFixture = await getDataContractFixture(); - client = await createClientWithFundedWallet(350000); + client = await createClientWithFundedWallet(35000000); - identity = await client.platform.identities.register(300000); + // Looks like updating the contact and keeping history requires about + // 7 million credits in fees. Investigate this further. + identity = await client.platform.identities.register(30000000); }); after(async () => { @@ -134,6 +136,17 @@ describe('Platform', () => { const newDocumentType = 'myAwesomeDocument'; + // binary contract representation doesn't have a contract config in it, + // and we set default value on deserialization, so we need to set it + // here to avoid the error, as original contract has a non-default + // value here + fetchedDataContract.setConfig({ + canBeDeleted: false, + readonly: false, + keepsHistory: true, + documentsKeepHistoryContractDefault: false, + documentsMutableContractDefault: true, + }); fetchedDataContract.setDocumentSchema(newDocumentType, { type: 'object', indices: [ @@ -204,6 +217,27 @@ describe('Platform', () => { lastName: 'myLastName', }, ); + + const contractHistory = await client.platform.contracts.history( + dataContractFixture.getId(), 0, 10, 0, + ); + + // By default, history is not really sorted, since it's a map + const historyPairs = Object.entries(contractHistory); + historyPairs.sort((a, b) => a[0] - b[0]); + + expect(historyPairs).to.have.lengthOf(2); + + const [originalContractDate, originalContract] = Object.entries(contractHistory)[0]; + expect(originalContract.toObject()).to.be.deep.equal(dataContractFixture.toObject()); + + const [updatedContractDate, updatedContract] = Object.entries(contractHistory)[1]; + // Version is updated separately inside SDK on a cloned contract, so we need to update it + // here manually to compare + fetchedDataContract.incrementVersion(); + expect(updatedContract.toObject()).to.be.deep.equal(fetchedDataContract.toObject()); + + expect(Number(updatedContractDate)).to.be.greaterThan(Number(originalContractDate)); }); }); }); diff --git a/packages/platform-test-suite/test/functional/platform/Identity.spec.js b/packages/platform-test-suite/test/functional/platform/Identity.spec.js index b3659ca10b..4a9b221449 100644 --- a/packages/platform-test-suite/test/functional/platform/Identity.spec.js +++ b/packages/platform-test-suite/test/functional/platform/Identity.spec.js @@ -324,8 +324,6 @@ describe('Platform', () => { before(async () => { dataContractFixture = await getDataContractFixture(identity.getId()); - console.log(dataContractFixture); - await client.platform.contracts.publish(dataContractFixture, identity); // Additional wait time to mitigate testnet latency diff --git a/packages/rs-dpp/src/data_contract/data_contract_factory.rs b/packages/rs-dpp/src/data_contract/data_contract_factory.rs index 11bc61abf0..0db87ee533 100644 --- a/packages/rs-dpp/src/data_contract/data_contract_factory.rs +++ b/packages/rs-dpp/src/data_contract/data_contract_factory.rs @@ -235,18 +235,13 @@ impl DataContractFactory { &self, data_contract: DataContract, ) -> Result { - let raw_object = BTreeMap::from([ - ( - st_prop::PROTOCOL_VERSION.to_string(), - Value::U32(self.protocol_version), - ), - ( - st_prop::DATA_CONTRACT.to_string(), - data_contract.try_into()?, - ), - ]); - - DataContractUpdateTransition::from_value_map(raw_object) + Ok(DataContractUpdateTransition { + protocol_version: self.protocol_version, + transition_type: StateTransitionType::DataContractUpdate, + signature_public_key_id: 0, + signature: Default::default(), + data_contract, + }) } } diff --git a/packages/rs-dpp/src/data_contract/state_transition/data_contract_create_transition/mod.rs b/packages/rs-dpp/src/data_contract/state_transition/data_contract_create_transition/mod.rs index 54eb1d049c..0869dd85e0 100644 --- a/packages/rs-dpp/src/data_contract/state_transition/data_contract_create_transition/mod.rs +++ b/packages/rs-dpp/src/data_contract/state_transition/data_contract_create_transition/mod.rs @@ -422,4 +422,26 @@ mod test { assert!(!data.state_transition.is_document_state_transition()); assert!(!data.state_transition.is_identity_state_transition()); } + + mod platform_serializable { + use crate::data_contract::state_transition::data_contract_create_transition::DataContractCreateTransition; + use crate::serialization_traits::{PlatformDeserializable, PlatformSerializable}; + + #[test] + fn should_serialize_config() { + let mut data = super::get_test_data(); + data.state_transition.data_contract.config.keeps_history = true; + let state_transition_bytes = data + .state_transition + .serialize() + .expect("state transition should be serialized"); + + assert!(data.state_transition.data_contract.config.keeps_history); + + let restored = DataContractCreateTransition::deserialize(&state_transition_bytes) + .expect("state transition should be deserialized"); + + assert!(restored.data_contract.config.keeps_history); + } + } } diff --git a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/document_transition/document_create_transition_action.rs b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/document_transition/document_create_transition_action.rs index 4426d22114..6583ee152b 100644 --- a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/document_transition/document_create_transition_action.rs +++ b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/document_transition/document_create_transition_action.rs @@ -93,8 +93,8 @@ impl Document { owner_id, properties: data.clone(), revision: document_type.initial_revision(), - created_at: created_at.clone(), - updated_at: updated_at.clone(), + created_at: *created_at, + updated_at: *updated_at, }) } diff --git a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/document_transition/document_replace_transition_action.rs b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/document_transition/document_replace_transition_action.rs index 3a78706759..d063bd900d 100644 --- a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/document_transition/document_replace_transition_action.rs +++ b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/document_transition/document_replace_transition_action.rs @@ -74,8 +74,8 @@ impl Document { owner_id, properties: data.clone(), revision: Some(*revision), - created_at: created_at.clone(), - updated_at: updated_at.clone(), + created_at: *created_at, + updated_at: *updated_at, }) } diff --git a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/state/validate_documents_batch_transition_state.rs b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/state/validate_documents_batch_transition_state.rs index 87b4141a36..82e7f116e8 100644 --- a/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/state/validate_documents_batch_transition_state.rs +++ b/packages/rs-dpp/src/document/state_transition/documents_batch_transition/validation/state/validate_documents_batch_transition_state.rs @@ -303,7 +303,7 @@ fn validate_transition( return Ok(result); }; - let validation_result = check_if_timestamps_are_equal(transition, &original_document); + let validation_result = check_if_timestamps_are_equal(transition, original_document); result.merge(validation_result); let validation_result = check_ownership(transition, original_document, owner_id); diff --git a/packages/rs-dpp/src/errors/consensus/codes.rs b/packages/rs-dpp/src/errors/consensus/codes.rs index aedc6a4b51..cf37447ca1 100644 --- a/packages/rs-dpp/src/errors/consensus/codes.rs +++ b/packages/rs-dpp/src/errors/consensus/codes.rs @@ -141,6 +141,7 @@ impl ErrorWithCode for StateError { Self::DataContractIsReadonlyError { .. } => 4026, Self::DataTriggerError(ref e) => e.code(), Self::DataTriggerActionError(ref e) => e.code(), + Self::DataContractConfigUpdateError { .. } => 4027, // Document Self::DocumentAlreadyPresentError { .. } => 4004, diff --git a/packages/rs-dpp/src/errors/consensus/state/data_contract/data_contract_config_update_error.rs b/packages/rs-dpp/src/errors/consensus/state/data_contract/data_contract_config_update_error.rs new file mode 100644 index 0000000000..e57c32979c --- /dev/null +++ b/packages/rs-dpp/src/errors/consensus/state/data_contract/data_contract_config_update_error.rs @@ -0,0 +1,40 @@ +use crate::consensus::state::state_error::StateError; +use crate::consensus::ConsensusError; +use bincode::{Decode, Encode}; +use platform_value::Identifier; +use serde::{Deserialize, Serialize}; +use thiserror::Error; + +#[derive(Error, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Encode, Decode)] +#[error("Can't update Data Contract {data_contract_id} config: {additional_message}")] +pub struct DataContractConfigUpdateError { + /* + + DO NOT CHANGE ORDER OF FIELDS WITHOUT INTRODUCING OF NEW VERSION + + */ + data_contract_id: Identifier, + additional_message: String, +} + +impl DataContractConfigUpdateError { + pub fn new(data_contract_id: Identifier, additional_message: impl Into) -> Self { + Self { + data_contract_id, + additional_message: additional_message.into(), + } + } + + pub fn data_contract_id(&self) -> &Identifier { + &self.data_contract_id + } + pub fn additional_message(&self) -> &str { + &self.additional_message + } +} + +impl From for ConsensusError { + fn from(err: DataContractConfigUpdateError) -> Self { + Self::StateError(StateError::DataContractConfigUpdateError(err)) + } +} diff --git a/packages/rs-dpp/src/errors/consensus/state/data_contract/mod.rs b/packages/rs-dpp/src/errors/consensus/state/data_contract/mod.rs index 3492d24b27..fe67475ed8 100644 --- a/packages/rs-dpp/src/errors/consensus/state/data_contract/mod.rs +++ b/packages/rs-dpp/src/errors/consensus/state/data_contract/mod.rs @@ -1,2 +1,3 @@ pub mod data_contract_already_present_error; +pub mod data_contract_config_update_error; pub mod data_contract_is_readonly_error; diff --git a/packages/rs-dpp/src/errors/consensus/state/state_error.rs b/packages/rs-dpp/src/errors/consensus/state/state_error.rs index 6a91957254..0a5b6a3db9 100644 --- a/packages/rs-dpp/src/errors/consensus/state/state_error.rs +++ b/packages/rs-dpp/src/errors/consensus/state/state_error.rs @@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize}; use thiserror::Error; use crate::consensus::state::data_contract::data_contract_already_present_error::DataContractAlreadyPresentError; +use crate::consensus::state::data_contract::data_contract_config_update_error::DataContractConfigUpdateError; use crate::consensus::state::data_contract::data_contract_is_readonly_error::DataContractIsReadonlyError; use crate::consensus::state::data_trigger::data_trigger_error::{ DataTriggerActionError, DataTriggerError, @@ -107,6 +108,9 @@ pub enum StateError { #[error(transparent)] DataContractIsReadonlyError(DataContractIsReadonlyError), + + #[error(transparent)] + DataContractConfigUpdateError(DataContractConfigUpdateError), } impl From for ConsensusError { diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs index 8dfc788926..65783ee2a4 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs @@ -135,6 +135,7 @@ mod tests { use super::*; use dpp::assert_state_consensus_errors; + use dpp::consensus::state::state_error::StateError; use dpp::consensus::state::state_error::StateError::DataContractIsReadonlyError; use dpp::errors::consensus::ConsensusError; @@ -207,7 +208,6 @@ mod tests { data_contract.config.keeps_history = true; data_contract.config.readonly = false; - // TODO: check that keep_history actually works apply_contract( &platform, &data_contract, @@ -311,5 +311,85 @@ mod tests { assert_eq!(contract_history.len(), 1); assert_eq!(keys[0], 2000); } + + #[test] + fn should_fail_if_trying_to_update_config() { + let TestData { + raw_state_transition: _, + mut data_contract, + platform, + } = setup_test(); + + data_contract.config.keeps_history = true; + data_contract.config.readonly = false; + + apply_contract( + &platform, + &data_contract, + BlockInfo { + time_ms: 1000, + height: 100, + core_height: 10, + epoch: Default::default(), + }, + ); + + let updated_document = json!({ + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "newProp": { + "type": "integer", + "minimum": 0 + } + }, + "required": [ + "$createdAt" + ], + "additionalProperties": false + }); + + data_contract.increment_version(); + data_contract + .set_document_schema("niceDocument".into(), updated_document) + .expect("to be able to set document schema"); + + // It should be not possible to modify this + data_contract.config.keeps_history = false; + + // TODO: add a data contract stop transition + let state_transition = DataContractUpdateTransition { + protocol_version: LATEST_VERSION, + data_contract: data_contract.clone(), + signature: BinaryData::new(vec![0; 65]), + signature_public_key_id: 0, + transition_type: StateTransitionType::DataContractUpdate, + }; + + let platform_ref = PlatformRef { + drive: &platform.drive, + state: &platform.state.read().unwrap(), + config: &platform.config, + core_rpc: &platform.core_rpc, + }; + + let result = state_transition + .validate_state(&platform_ref, None) + .expect("state transition to be validated"); + + assert!(!result.is_valid()); + let errors = assert_state_consensus_errors!( + result, + StateError::DataContractConfigUpdateError, + 1 + ); + let error = errors.get(0).expect("to have an error"); + assert_eq!( + error.additional_message(), + "contract can not change whether it keeps history: changing from true to false" + ); + } } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/state/v0/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/state/v0/mod.rs index 03188b23de..58f3f3ddcb 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/state/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/state/v0/mod.rs @@ -5,10 +5,14 @@ use crate::rpc::core::CoreRPCLike; use dpp::consensus::basic::data_contract::InvalidDataContractVersionError; use dpp::consensus::basic::document::DataContractNotPresentError; use dpp::consensus::basic::BasicError; +use dpp::consensus::state::data_contract::data_contract_config_update_error::DataContractConfigUpdateError; use dpp::consensus::state::data_contract::data_contract_is_readonly_error::DataContractIsReadonlyError; +use dpp::consensus::ConsensusError; +use dpp::data_contract::contract_config::ContractConfig; use dpp::data_contract::state_transition::data_contract_update_transition::validation::basic::any_schema_changes; use dpp::data_contract::state_transition::data_contract_update_transition::DataContractUpdateTransitionAction; use dpp::document::document_transition::document_base_transition::JsonValue; +use dpp::identifier::Identifier; use dpp::prelude::ConsensusValidationResult; use dpp::{ consensus::basic::data_contract::{ @@ -45,6 +49,57 @@ pub(crate) trait StateTransitionStateValidationV0 { ) -> Result, Error>; } +fn validate_config_update( + old_config: &ContractConfig, + new_config: &ContractConfig, + contract_id: Identifier, +) -> Result<(), ConsensusError> { + if old_config.readonly { + return Err(DataContractIsReadonlyError::new(contract_id).into()); + } + + if new_config.readonly { + return Err(DataContractConfigUpdateError::new( + contract_id, + "contract can not be changed to readonly", + ) + .into()); + } + + if new_config.keeps_history != old_config.keeps_history { + return Err(DataContractConfigUpdateError::new( + contract_id, + format!( + "contract can not change whether it keeps history: changing from {} to {}", + old_config.keeps_history, new_config.keeps_history + ), + ) + .into()); + } + + if new_config.documents_keep_history_contract_default + != old_config.documents_keep_history_contract_default + { + return Err(DataContractConfigUpdateError::new( + contract_id, + "contract can not change the default of whether documents keeps history", + ) + .into()); + } + + if new_config.documents_mutable_contract_default + != old_config.documents_mutable_contract_default + { + return Err(DataContractConfigUpdateError::new( + contract_id, + "contract can not change the default of whether documents are mutable", + ) + .into()); + } + + Ok(()) +} + impl StateTransitionStateValidationV0 for DataContractUpdateTransition { fn validate_state_v0( &self, @@ -79,6 +134,15 @@ impl StateTransitionStateValidationV0 for DataContractUpdateTransition { )) } + if let Err(e) = validate_config_update( + &existing_data_contract.config, + &self.data_contract.config, + self.data_contract.id.0 .0.into(), + ) { + validation_result.add_error(e); + return Ok(validation_result); + } + let mut existing_data_contract_object = existing_data_contract.to_object()?; let new_data_contract_object = self.data_contract.to_object()?; diff --git a/packages/rs-drive-abci/src/platform_types/query/v0/mod.rs b/packages/rs-drive-abci/src/platform_types/query/v0/mod.rs index 5bab06e886..b204b16bdb 100644 --- a/packages/rs-drive-abci/src/platform_types/query/v0/mod.rs +++ b/packages/rs-drive-abci/src/platform_types/query/v0/mod.rs @@ -448,7 +448,7 @@ impl Platform { id, limit, offset, - start_at_seconds, + start_at_ms, prove, } = check_validation_result_with_data!(GetDataContractHistoryRequest::decode( query_data @@ -456,33 +456,25 @@ impl Platform { let contract_id: Identifier = check_validation_result_with_data!(id.try_into()); // TODO: make a cast safe - let limit = limit - .map(|limit| { - u16::try_from(limit).map_err(|_| { - Error::Drive(drive::error::Error::Contract(ContractError::Overflow( - "can't fit u16 limit from the supplied value", - ))) - }) - }) - .transpose()?; - let offset = offset - .map(|offset| { - u16::try_from(offset).map_err(|_| { - Error::Drive(drive::error::Error::Contract(ContractError::Overflow( - "can't fit u16 offset from the supplied value", - ))) - }) - }) - .transpose()?; + let limit = u16::try_from(limit).map_err(|_| { + Error::Drive(drive::error::Error::Contract(ContractError::Overflow( + "can't fit u16 limit from the supplied value", + ))) + })?; + let offset = u16::try_from(offset).map_err(|_| { + Error::Drive(drive::error::Error::Contract(ContractError::Overflow( + "can't fit u16 offset from the supplied value", + ))) + })?; let response_data = if prove { let proof = check_validation_result_with_data!(self.drive.prove_contract_history( contract_id.to_buffer(), None, - start_at_seconds.unwrap_or_default(), - limit, - offset + start_at_ms, + Some(limit), + Some(offset) )); GetDataContractHistoryResponse { metadata: Some(metadata), @@ -499,9 +491,9 @@ impl Platform { check_validation_result_with_data!(self.drive.fetch_contract_with_history( contract_id.to_buffer(), None, - start_at_seconds.unwrap_or_default(), - limit, - offset + start_at_ms, + Some(limit), + Some(offset) )); let contract_historical_entries = check_validation_result_with_data!(contracts @@ -512,12 +504,7 @@ impl Platform { >( get_data_contract_history_response::DataContractHistoryEntry { date: date_in_seconds, - // TODO: figure out why this is optional - value: Some( - get_data_contract_history_response::DataContractValue { - value: data_contract.serialize()? - } - ) + value: data_contract.serialize()? } )) .collect()); @@ -860,9 +847,9 @@ mod test { fn default_request() -> GetDataContractHistoryRequest { GetDataContractHistoryRequest { id: vec![1; 32], - limit: Some(10), - offset: Some(0), - start_at_seconds: None, + limit: 10, + offset: 0, + start_at_ms: 0, prove: false, } } @@ -1001,16 +988,16 @@ mod test { let first_entry = history_entries.pop().unwrap(); assert_eq!(first_entry.date, 1000); - let first_entry_data_contract = first_entry.value.expect("To have data contract"); + let first_entry_data_contract = first_entry.value; let first_data_contract_update = - DataContract::deserialize_no_limit(&first_entry_data_contract.value) + DataContract::deserialize_no_limit(&first_entry_data_contract) .expect("To decode data contract"); assert_eq!(first_data_contract_update, original_data_contract); assert_eq!(second_entry.date, 2000); - let second_entry_data_contract = second_entry.value.expect("To have data contract"); + let second_entry_data_contract = second_entry.value; let second_data_contract_update = - DataContract::deserialize_no_limit(&second_entry_data_contract.value) + DataContract::deserialize_no_limit(&second_entry_data_contract) .expect("To decode data contract"); let updated_doc = second_data_contract_update @@ -1079,7 +1066,7 @@ mod test { let (_root_hash, contract_history) = Drive::verify_contract_history( &contract_proof.grovedb_proof, original_data_contract.id.to_buffer(), - request.start_at_seconds(), + request.start_at_ms, Some(10), Some(0), ) @@ -1125,7 +1112,7 @@ mod test { let request = GetDataContractHistoryRequest { id: original_data_contract.id.to_vec(), - limit: Some(100000), + limit: 100000, ..default_request() }; let request_data = request.encode_to_vec(); @@ -1159,7 +1146,7 @@ mod test { let request = GetDataContractHistoryRequest { id: original_data_contract.id.to_vec(), - offset: Some(100000), + offset: 100000, ..default_request() }; let request_data = request.encode_to_vec(); diff --git a/packages/rs-drive/src/drive/contract/mod.rs b/packages/rs-drive/src/drive/contract/mod.rs index 881619ddef..3681f0beea 100644 --- a/packages/rs-drive/src/drive/contract/mod.rs +++ b/packages/rs-drive/src/drive/contract/mod.rs @@ -1225,7 +1225,7 @@ impl Drive { /// /// * `transaction` - A transaction that requests the contract. /// - /// * `start_at_date` - A `u64` representing the timestamp in Unix Epoch format from which to + /// * `start_at_ms` - A `u64` representing the timestamp in Unix Epoch format from which to /// start fetching the contract's history. /// /// * `limit` - An `Option` that sets the maximum number of contract history entries @@ -1254,14 +1254,14 @@ impl Drive { &self, contract_id: [u8; 32], transaction: TransactionArg, - start_at_date: u64, + start_at_ms: u64, limit: Option, offset: Option, ) -> Result, Error> { let mut ops = Vec::new(); let path_query = - Self::fetch_contract_history_query(contract_id, start_at_date, limit, offset)?; + Self::fetch_contract_history_query(contract_id, start_at_ms, limit, offset)?; let (results, _cost) = self.grove_get_path_query( &path_query, diff --git a/packages/rs-drive/src/drive/contract/queries.rs b/packages/rs-drive/src/drive/contract/queries.rs index 24dd9eb34a..522a120b6b 100644 --- a/packages/rs-drive/src/drive/contract/queries.rs +++ b/packages/rs-drive/src/drive/contract/queries.rs @@ -93,7 +93,7 @@ impl Drive { /// This function returns an error if the limit is out of the allowed range. pub fn fetch_contract_history_query( contract_id: [u8; 32], - start_at_date: u64, + start_at_ms: u64, limit: Option, offset: Option, ) -> Result { @@ -106,7 +106,7 @@ impl Drive { let query = Query::new_single_query_item_with_direction( QueryItem::RangeAfter(std::ops::RangeFrom { - start: encode_u64(start_at_date), + start: encode_u64(start_at_ms), }), false, ); diff --git a/packages/wasm-dpp/lib/test/fixtures/getDataContractFixture.js b/packages/wasm-dpp/lib/test/fixtures/getDataContractFixture.js index b7ec499a74..ad1b72e904 100644 --- a/packages/wasm-dpp/lib/test/fixtures/getDataContractFixture.js +++ b/packages/wasm-dpp/lib/test/fixtures/getDataContractFixture.js @@ -262,5 +262,13 @@ module.exports = async function getDataContractFixture(ownerId = randomOwnerId) entropyGenerator, ); - return factory.create(ownerId, documents); + const config = { + canBeDeleted: false, + readonly: false, + keepsHistory: true, + documentsKeepHistoryContractDefault: false, + documentsMutableContractDefault: true, + }; + + return factory.create(ownerId, documents, config); }; diff --git a/packages/wasm-dpp/src/data_contract/data_contract.rs b/packages/wasm-dpp/src/data_contract/data_contract.rs index 2b170f5a47..751174ac4c 100644 --- a/packages/wasm-dpp/src/data_contract/data_contract.rs +++ b/packages/wasm-dpp/src/data_contract/data_contract.rs @@ -327,6 +327,18 @@ impl DataContractWasm { Ok(object) } + #[wasm_bindgen(js_name=getConfig)] + pub fn config(&self) -> Result { + Ok(serde_wasm_bindgen::to_value(&self.inner.config)?) + } + + #[wasm_bindgen(js_name=setConfig)] + pub fn set_config(&mut self, config: JsValue) -> Result<(), JsValue> { + let res = serde_wasm_bindgen::from_value(config); + self.inner.config = res.unwrap(); + Ok(()) + } + #[wasm_bindgen(js_name=toJSON)] pub fn to_json(&self) -> Result { let json = self.inner.to_json().with_js_error()?; diff --git a/packages/wasm-dpp/src/data_contract/state_transition/data_contract_create_transition/mod.rs b/packages/wasm-dpp/src/data_contract/state_transition/data_contract_create_transition/mod.rs index fde0429948..c0a51c64c4 100644 --- a/packages/wasm-dpp/src/data_contract/state_transition/data_contract_create_transition/mod.rs +++ b/packages/wasm-dpp/src/data_contract/state_transition/data_contract_create_transition/mod.rs @@ -8,7 +8,7 @@ pub use validation::*; use dpp::consensus::signature::SignatureError; use dpp::consensus::ConsensusError; -use dpp::serialization_traits::PlatformSerializable; +use dpp::serialization_traits::{PlatformDeserializable, PlatformSerializable}; use dpp::state_transition::StateTransition; use dpp::{ data_contract::state_transition::data_contract_create_transition::DataContractCreateTransition, @@ -77,6 +77,13 @@ impl DataContractCreateTransitionWasm { self.0.data_contract.clone().into() } + #[wasm_bindgen(js_name=setDataContractConfig)] + pub fn set_data_contract_config(&mut self, config: JsValue) -> Result<(), JsValue> { + let res = serde_wasm_bindgen::from_value(config); + self.0.data_contract.config = res.unwrap(); + Ok(()) + } + #[wasm_bindgen(js_name=getProtocolVersion)] pub fn get_protocol_version(&self) -> u32 { self.0.protocol_version @@ -116,6 +123,16 @@ impl DataContractCreateTransitionWasm { Ok(Buffer::from_bytes(&bytes)) } + #[wasm_bindgen(js_name=fromBuffer)] + pub fn from_buffer(buffer: Vec) -> Result { + let state_transition: StateTransition = + PlatformDeserializable::deserialize(&buffer).with_js_error()?; + match state_transition { + StateTransition::DataContractCreate(dct) => Ok(dct.into()), + _ => Err(JsValue::from_str("Invalid state transition type")), + } + } + #[wasm_bindgen(js_name=getModifiedDataIds)] pub fn get_modified_data_ids(&self) -> Vec { self.0 diff --git a/packages/wasm-dpp/src/data_contract/state_transition/data_contract_update_transition/mod.rs b/packages/wasm-dpp/src/data_contract/state_transition/data_contract_update_transition/mod.rs index 15c7696b1d..d396ca07b1 100644 --- a/packages/wasm-dpp/src/data_contract/state_transition/data_contract_update_transition/mod.rs +++ b/packages/wasm-dpp/src/data_contract/state_transition/data_contract_update_transition/mod.rs @@ -7,7 +7,7 @@ pub use apply::*; pub use validation::*; use dpp::consensus::ConsensusError; -use dpp::serialization_traits::PlatformSerializable; +use dpp::serialization_traits::{PlatformDeserializable, PlatformSerializable}; use dpp::state_transition::StateTransition; use dpp::{ consensus::signature::SignatureError, @@ -79,6 +79,13 @@ impl DataContractUpdateTransitionWasm { self.0.data_contract.clone().into() } + #[wasm_bindgen(js_name=setDataContractConfig)] + pub fn set_data_contract_config(&mut self, config: JsValue) -> Result<(), JsValue> { + let res = serde_wasm_bindgen::from_value(config); + self.0.data_contract.config = res.unwrap(); + Ok(()) + } + #[wasm_bindgen(js_name=getProtocolVersion)] pub fn get_protocol_version(&self) -> u32 { self.0.protocol_version @@ -113,6 +120,16 @@ impl DataContractUpdateTransitionWasm { Ok(Buffer::from_bytes(&bytes)) } + #[wasm_bindgen(js_name=fromBuffer)] + pub fn from_buffer(buffer: Vec) -> Result { + let state_transition: StateTransition = + PlatformDeserializable::deserialize(&buffer).with_js_error()?; + match state_transition { + StateTransition::DataContractUpdate(dct) => Ok(dct.into()), + _ => Err(JsValue::from_str("Invalid state transition type")), + } + } + #[wasm_bindgen(js_name=getModifiedDataIds)] pub fn get_modified_data_ids(&self) -> Vec { self.0 diff --git a/packages/wasm-dpp/src/data_contract_factory/data_contract_factory.rs b/packages/wasm-dpp/src/data_contract_factory/data_contract_factory.rs index c6f15f94c9..ff72c29fe1 100644 --- a/packages/wasm-dpp/src/data_contract_factory/data_contract_factory.rs +++ b/packages/wasm-dpp/src/data_contract_factory/data_contract_factory.rs @@ -14,7 +14,7 @@ use dpp::{ use wasm_bindgen::prelude::*; use crate::entropy_generator::ExternalEntropyGenerator; -use crate::utils::WithJsError; +use crate::utils::{ToSerdeJSONExt, WithJsError}; use crate::{ data_contract::errors::InvalidDataContractError, @@ -106,15 +106,24 @@ impl DataContractFactoryWasm { &self, owner_id: Vec, documents: JsValue, + config: JsValue, ) -> Result { let documents_object: platform_value::Value = with_js_error!(serde_wasm_bindgen::from_value(documents))?; + + let contract_config = if config.is_object() && !config.is_falsy() { + let raw_config = config.with_serde_to_json_value()?; + Some(serde_json::from_value(raw_config).with_js_error()?) + } else { + None + }; + let identifier = Identifier::from_bytes(&owner_id) .map_err(ProtocolError::ValueError) .with_js_error()?; //todo: contract config self.0 - .create(identifier, documents_object, None, None) + .create(identifier, documents_object, contract_config, None) .map(Into::into) .with_js_error() } diff --git a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs index 8d2fb5597d..a107a447ef 100644 --- a/packages/wasm-dpp/src/errors/consensus/consensus_error.rs +++ b/packages/wasm-dpp/src/errors/consensus/consensus_error.rs @@ -75,7 +75,8 @@ use crate::errors::consensus::state::data_contract::data_trigger::{ DataTriggerConditionErrorWasm, DataTriggerExecutionErrorWasm, }; use crate::errors::consensus::state::data_contract::{ - DataContractAlreadyPresentErrorWasm, DataContractIsReadonlyErrorWasm, + DataContractAlreadyPresentErrorWasm, DataContractConfigUpdateErrorWasm, + DataContractIsReadonlyErrorWasm, }; use crate::errors::consensus::state::document::{ DocumentAlreadyPresentErrorWasm, DocumentNotFoundErrorWasm, DocumentOwnerIdMismatchErrorWasm, @@ -207,6 +208,9 @@ pub fn from_state_error(state_error: &StateError) -> JsValue { StateError::DataContractIsReadonlyError(e) => { DataContractIsReadonlyErrorWasm::from(e).into() } + StateError::DataContractConfigUpdateError(e) => { + DataContractConfigUpdateErrorWasm::from(e).into() + } } } diff --git a/packages/wasm-dpp/src/errors/consensus/state/data_contract/data_contract_config_update_error.rs b/packages/wasm-dpp/src/errors/consensus/state/data_contract/data_contract_config_update_error.rs new file mode 100644 index 0000000000..86ceda168e --- /dev/null +++ b/packages/wasm-dpp/src/errors/consensus/state/data_contract/data_contract_config_update_error.rs @@ -0,0 +1,53 @@ +use crate::buffer::Buffer; +use crate::identifier::IdentifierWrapper; +use dpp::consensus::codes::ErrorWithCode; +use dpp::consensus::state::data_contract::data_contract_config_update_error::DataContractConfigUpdateError; +use dpp::consensus::ConsensusError; + +use dpp::serialization_traits::PlatformSerializable; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen(js_name=DataContractConfigUpdateError)] +pub struct DataContractConfigUpdateErrorWasm { + inner: DataContractConfigUpdateError, +} + +impl From<&DataContractConfigUpdateError> for DataContractConfigUpdateErrorWasm { + fn from(e: &DataContractConfigUpdateError) -> Self { + Self { inner: e.clone() } + } +} + +#[wasm_bindgen(js_class=DataContractConfigUpdateError)] +impl DataContractConfigUpdateErrorWasm { + #[wasm_bindgen(constructor)] + pub fn new(data_contract_id: IdentifierWrapper, message: String) -> Self { + Self { + inner: DataContractConfigUpdateError::new(data_contract_id.into(), message), + } + } + + #[wasm_bindgen(js_name=getDataContractId)] + pub fn data_contract_id(&self) -> IdentifierWrapper { + self.inner.data_contract_id().to_owned().into() + } + + #[wasm_bindgen(js_name=getCode)] + pub fn get_code(&self) -> u32 { + ConsensusError::from(self.inner.clone()).code() + } + + #[wasm_bindgen(getter)] + pub fn message(&self) -> String { + self.inner.to_string() + } + + #[wasm_bindgen(js_name=serialize)] + pub fn serialize(&self) -> Result { + let bytes = ConsensusError::from(self.inner.clone()) + .serialize() + .map_err(JsError::from)?; + + Ok(Buffer::from_bytes(bytes.as_slice())) + } +} diff --git a/packages/wasm-dpp/src/errors/consensus/state/data_contract/mod.rs b/packages/wasm-dpp/src/errors/consensus/state/data_contract/mod.rs index 4360316c6e..931a83b4b2 100644 --- a/packages/wasm-dpp/src/errors/consensus/state/data_contract/mod.rs +++ b/packages/wasm-dpp/src/errors/consensus/state/data_contract/mod.rs @@ -1,6 +1,8 @@ mod data_contract_already_present_error; +mod data_contract_config_update_error; mod data_contract_is_readonly_error; pub mod data_trigger; pub use data_contract_already_present_error::*; +pub use data_contract_config_update_error::*; pub use data_contract_is_readonly_error::*; diff --git a/packages/wasm-dpp/test/unit/dataContract/DataContract.spec.js b/packages/wasm-dpp/test/unit/dataContract/DataContract.spec.js index 37a5dbb2f8..9e549c2c5f 100644 --- a/packages/wasm-dpp/test/unit/dataContract/DataContract.spec.js +++ b/packages/wasm-dpp/test/unit/dataContract/DataContract.spec.js @@ -335,4 +335,22 @@ describe('DataContract', () => { expect(dataContract.getMetadata().toObject()).to.deep.equal(otherMetadataToObject); }); }); + + describe('#setConfig', () => { + it('should set config', () => { + const config = { + canBeDeleted: true, + readonly: true, + keepsHistory: true, + documentsKeepHistoryContractDefault: true, + documentsMutableContractDefault: true, + }; + + dataContract.setConfig(config); + + const restoredConfig = dataContract.getConfig(); + + expect(config).to.deep.equal(restoredConfig); + }); + }); }); diff --git a/packages/wasm-dpp/test/unit/dataContract/DataContractFactory.spec.js b/packages/wasm-dpp/test/unit/dataContract/DataContractFactory.spec.js index c1953c1b42..f9a9399dff 100644 --- a/packages/wasm-dpp/test/unit/dataContract/DataContractFactory.spec.js +++ b/packages/wasm-dpp/test/unit/dataContract/DataContractFactory.spec.js @@ -46,6 +46,26 @@ describe('DataContractFactory', () => { expect(result).excluding('$id').to.deep.equal(rawDataContract); }); + + it('should pass config', () => { + const config = { + canBeDeleted: false, + readonly: false, + keepsHistory: true, + documentsKeepHistoryContractDefault: false, + documentsMutableContractDefault: true, + }; + const contract = factory.create( + dataContract.getOwnerId(), + rawDataContract.documents, + config, + ); + + const result = contract.toObject(); + + expect(contract.getConfig()).to.be.deep.equal(config); + expect(result).excluding('$id').to.deep.equal(rawDataContract); + }); }); describe('createFromObject', () => { diff --git a/packages/wasm-dpp/test/unit/dataContract/stateTransition/DataContractCreateTransition/DataContractCreateTransition.spec.js b/packages/wasm-dpp/test/unit/dataContract/stateTransition/DataContractCreateTransition/DataContractCreateTransition.spec.js index b1fcb4ed9a..09da056e10 100644 --- a/packages/wasm-dpp/test/unit/dataContract/stateTransition/DataContractCreateTransition/DataContractCreateTransition.spec.js +++ b/packages/wasm-dpp/test/unit/dataContract/stateTransition/DataContractCreateTransition/DataContractCreateTransition.spec.js @@ -68,6 +68,16 @@ describe('DataContractCreateTransition', () => { expect(result).to.be.instanceOf(Buffer); expect(result).to.have.lengthOf(2271); }); + + it('should be able to restore contract config from bytes', () => { + const config = stateTransition.getDataContract().getConfig(); + config.keepsHistory = true; + stateTransition.setDataContractConfig(config); + expect(stateTransition.getDataContract().getConfig().keepsHistory).to.be.true(); + const buffer = stateTransition.toBuffer(); + const restoredSt = DataContractCreateTransition.fromBuffer(buffer); + expect(restoredSt.getDataContract().getConfig().keepsHistory).to.be.true(); + }); }); describe('#getOwnerId', () => { diff --git a/packages/wasm-dpp/test/unit/dataContract/stateTransition/DataContractUpdateTransition/DataContractUpdateTransition.spec.js b/packages/wasm-dpp/test/unit/dataContract/stateTransition/DataContractUpdateTransition/DataContractUpdateTransition.spec.js index b019e1e428..fa2fbd73b4 100644 --- a/packages/wasm-dpp/test/unit/dataContract/stateTransition/DataContractUpdateTransition/DataContractUpdateTransition.spec.js +++ b/packages/wasm-dpp/test/unit/dataContract/stateTransition/DataContractUpdateTransition/DataContractUpdateTransition.spec.js @@ -68,6 +68,16 @@ describe('DataContractUpdateTransition', () => { expect(result).to.be.instanceOf(Buffer); expect(result).to.have.lengthOf(2239); }); + + it('should be able to restore contract config from bytes', () => { + const config = stateTransition.getDataContract().getConfig(); + config.keepsHistory = true; + stateTransition.setDataContractConfig(config); + expect(stateTransition.getDataContract().getConfig().keepsHistory).to.be.true(); + const buffer = stateTransition.toBuffer(); + const restoredSt = DataContractUpdateTransition.fromBuffer(buffer); + expect(restoredSt.getDataContract().getConfig().keepsHistory).to.be.true(); + }); }); describe.skip('#hash', () => { From a0ad96eca4eca3c80da7277a54a6576bb6ec2d0c Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Fri, 7 Jul 2023 22:49:51 +0700 Subject: [PATCH 03/19] chore: update lock file --- Cargo.lock | 152 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 135 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 90796d46bf..cd0b3cd2be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -100,7 +100,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -110,7 +110,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -815,6 +815,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.4" @@ -1411,7 +1421,7 @@ checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1981,7 +1991,7 @@ checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi 0.3.1", "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1999,7 +2009,7 @@ dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2386,7 +2396,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2626,6 +2636,12 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + [[package]] name = "os_str_bytes" version = "6.5.1" @@ -2851,7 +2867,7 @@ dependencies = [ "libc", "log", "pin-project-lite", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -3329,7 +3345,7 @@ dependencies = [ "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -3344,6 +3360,18 @@ dependencies = [ "sct", ] +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + [[package]] name = "rustls-pemfile" version = "1.0.2" @@ -3384,6 +3412,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schannel" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +dependencies = [ + "windows-sys 0.42.0", +] + [[package]] name = "scheduled-thread-pool" version = "0.2.7" @@ -3436,6 +3473,29 @@ dependencies = [ "cc", ] +[[package]] +name = "security-framework" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "1.0.17" @@ -3797,7 +3857,7 @@ dependencies = [ "fastrand", "redox_syscall", "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -4013,7 +4073,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -4119,6 +4179,7 @@ dependencies = [ "percent-encoding", "pin-project", "prost", + "rustls-native-certs", "rustls-pemfile", "tokio", "tokio-rustls", @@ -4628,6 +4689,21 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -4643,51 +4719,93 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.0" From 7550d14f617a87dcaee69a4dba1027b4eb5f2bd5 Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Tue, 27 Jun 2023 09:05:23 +0500 Subject: [PATCH 04/19] fix(dashmate)!: helper default port was bound to Windows print port (#1194) --- packages/dashmate/configs/migrations.js | 9 +++++++++ packages/dashmate/configs/system/base.js | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/dashmate/configs/migrations.js b/packages/dashmate/configs/migrations.js index 62836cb13b..9bd4907842 100644 --- a/packages/dashmate/configs/migrations.js +++ b/packages/dashmate/configs/migrations.js @@ -574,4 +574,13 @@ module.exports = { }); return configFile; }, + '0.24.12': (configFile) => { + Object.entries(configFile.configs) + .forEach(([, config]) => { + // Update ports + config.platform.dashmate.helper.api.port = systemConfigs.base.platform + .dashmate.helper.api.port; + }); + return configFile; + }, }; diff --git a/packages/dashmate/configs/system/base.js b/packages/dashmate/configs/system/base.js index 48c570dd9f..aef4302510 100644 --- a/packages/dashmate/configs/system/base.js +++ b/packages/dashmate/configs/system/base.js @@ -252,7 +252,7 @@ module.exports = { }, api: { enable: false, - port: 9000, + port: 9100, }, }, }, From 9cca904f1061e9b16ff9b695ce3aee14a7ddc711 Mon Sep 17 00:00:00 2001 From: Igor Markin Date: Tue, 27 Jun 2023 05:35:53 +0100 Subject: [PATCH 05/19] refactor: unwanted usage of x11-hash-js (#1191) --- .pnp.cjs | 4 +- packages/dash-spv/.mocharc.yml | 4 + packages/dash-spv/lib/spvchain.js | 307 +++++++----------- packages/dash-spv/lib/test/.eslintrc | 9 + packages/dash-spv/lib/test/bootstrap.js | 19 ++ packages/dash-spv/lib/x11.js | 27 ++ packages/dash-spv/package.json | 6 +- packages/dash-spv/test/index.js | 32 +- packages/dash-spv/test/spvchain.js | 54 ++- .../BlockHeadersProvider.js | 30 +- .../BlockHeadersProvider.spec.js | 5 +- .../BlockHeadersProvider.spec.js | 13 +- .../src/test/mocks/TransportMock.js | 1 + .../src/types/Account/Account.spec.js | 7 + .../src/types/Account/_initializeAccount.js | 5 +- .../Workers/BlockHeadersSyncWorker.spec.js | 4 +- yarn.lock | 2 + 17 files changed, 295 insertions(+), 234 deletions(-) create mode 100644 packages/dash-spv/.mocharc.yml create mode 100644 packages/dash-spv/lib/test/.eslintrc create mode 100644 packages/dash-spv/lib/test/bootstrap.js create mode 100644 packages/dash-spv/lib/x11.js diff --git a/.pnp.cjs b/.pnp.cjs index e87ec22e70..fb425e79fa 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -2501,7 +2501,9 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["levelup", "npm:4.4.0"],\ ["memdown", "npm:5.1.0"],\ ["mocha", "npm:9.2.2"],\ - ["should", "npm:13.2.3"]\ + ["should", "npm:13.2.3"],\ + ["sinon", "npm:11.1.2"],\ + ["wasm-x11-hash", "npm:0.0.2"]\ ],\ "linkType": "SOFT"\ }]\ diff --git a/packages/dash-spv/.mocharc.yml b/packages/dash-spv/.mocharc.yml new file mode 100644 index 0000000000..4b2c6eac54 --- /dev/null +++ b/packages/dash-spv/.mocharc.yml @@ -0,0 +1,4 @@ +exit: true +timeout: 3000 +file: + - ./lib/test/bootstrap.js diff --git a/packages/dash-spv/lib/spvchain.js b/packages/dash-spv/lib/spvchain.js index dfb38386a8..167c1fecd8 100644 --- a/packages/dash-spv/lib/spvchain.js +++ b/packages/dash-spv/lib/spvchain.js @@ -1,26 +1,50 @@ +const X11 = require('./x11'); + const config = require('../config/config'); const Consensus = require('./consensus'); const utils = require('./utils'); const SPVError = require('./errors/SPVError'); -const SpvChain = class { - // TODO: move chainType and confirms to `options` - constructor(chainType, confirms = 100, startBlock, startBlockHeight) { - this.confirmsBeforeFinal = confirms; +const CHAIN_TYPE_NETWORKS = { + testnet: 'testnet', + devnet: 'devnet', + local: 'regtest', + regtest: 'regtest', + lowdiff: 'regtest', + livenet: 'mainnet', + mainnet: 'mainnet', +}; - this.reset(startBlockHeight); - this.init(chainType, startBlock); +const createGenesis = (chainType) => { + switch (chainType) { + case 'testnet': return config.getTestnetGenesis(); + case 'devnet': return config.getDevnetGenesis(); + case 'local': + case 'regtest': return config.getRegtestGenesis(); + case 'livenet': + case 'mainnet': return config.getLivenetGenesis(); + case 'lowdiff': return config.getLowDiffGenesis(); + default: throw new SPVError(`Unsupported chain type ${chainType}`); + } +}; - this.hashesByHeight = new Map([[this.startBlockHeight, this.root.hash]]); +const SpvChain = class { + constructor(chainType, confirms = 100) { + this.confirmsBeforeFinal = confirms; + this.network = CHAIN_TYPE_NETWORKS[chainType]; + if (!this.network) { + throw new SPVError(`Unsupported chain type "${chainType}"`); + } + this.genesis = createGenesis(chainType); - this.heightByHash = new Map([[this.root.hash, this.startBlockHeight]]); + this.reset(); + } - // TODO: legacy - remove this - this.orphanBlocks = []; + static async wasmX11Ready() { + return X11.load(); } - reset(fromBlockHeight = 0) { - this.root = null; + reset() { this.allBranches = [[]]; this.orphanChunks = []; this.prunedHeaders = []; @@ -28,71 +52,52 @@ const SpvChain = class { this.hashesByHeight = new Map(); this.heightByHash = new Map(); this.orphansHashes = new Set(); - this.startBlockHeight = fromBlockHeight < 0 ? 0 : fromBlockHeight; + // Height of the first header in the chain. + // 0 - if we are synchronizing from genesis + // > 0 if part of the chain is pruned and we are synchronizing from checkpoint where + this.startBlockHeight = null; + + // Head of pending first header. + // Used in situations where we don't know root in advance + this.pendingStartBlockHeight = null; } - init(chainType, startBlock) { - switch (chainType) { - case 'testnet': - this.network = 'testnet'; - if (startBlock) { - this.root = startBlock; - break; - } - this.root = config.getTestnetGenesis(); - break; - case 'devnet': - this.network = 'devnet'; - if (startBlock) { - this.root = startBlock; - break; - } - this.root = config.getDevnetGenesis(); - break; - case 'local': - case 'regtest': - this.network = 'regtest'; - if (startBlock) { - this.root = startBlock; - break; - } - this.root = config.getRegtestGenesis(); - break; - case 'livenet': - this.network = 'mainnet'; - if (startBlock) { - this.root = startBlock; - break; - } - this.root = config.getLivenetGenesis(); - break; - case 'mainnet': - this.network = 'mainnet'; - if (startBlock) { - this.root = startBlock; - break; - } - this.root = config.getLivenetGenesis(); - break; - case 'lowdiff': - this.network = 'regtest'; - if (startBlock) { - this.root = startBlock; - break; - } - this.root = config.getLowDiffGenesis(); - break; - default: - if (startBlock) { - this.root = startBlock; - this.network = 'mainnet'; - } else { - throw new SPVError('Unhandled chaintype or startBlock not provided'); - } - break; + /** + * Initializes chain with a start block and height + * - When no arguments provided, chain is initialized from genesis block + * - If startBlock is provided, height must be provided as well + * @param {BlockHeader} [startBlock] + * @param {number} [height] + */ + initialize(startBlock, height) { + if (!X11.ready()) { + throw new SPVError('X11 wasm not ready, call wasmX11Ready() first'); + } + + if (this.startBlockHeight !== null) { + throw new SPVError('Chain already initialized'); + } + + if (startBlock && typeof height === 'number') { + // eslint-disable-next-line + startBlock = utils.normalizeHeader(startBlock); + } else if (!startBlock && typeof height !== 'number') { + // eslint-disable-next-line + startBlock = this.genesis; + // eslint-disable-next-line + height = 0; + } else { + throw new SPVError('Initialization error, please provide both startBlock and height'); } - // this.root.children = []; - this.setAllBranches(); + + this.startBlockHeight = height; + this.hashesByHeight = new Map([[height, startBlock.hash]]); + this.heightByHash = new Map([[startBlock.hash, height]]); + this.setAllBranches(startBlock); + } + + initialized() { + return this.startBlockHeight !== null || this.pendingStartBlockHeight !== null; } validate() { @@ -146,30 +151,15 @@ const SpvChain = class { } /** @private */ - findConnection(newHeader) { - const stack = [this.root]; - while (stack.length > 0) { - const node = stack.pop(); - if (node.hash === utils.getCorrectedHash(newHeader.prevHash)) { - return node; - } - // node.children.forEach((c) => { stack.push(c); }); + setAllBranches(node, branch = []) { + if (!node) { + throw new SPVError('Root node for a branch is not defined'); } - return null; - } - /** @private */ - setAllBranches(node = this.root, branch = []) { this.allBranches = []; branch.push(node); - // node.children.forEach((c) => { - // this.setAllBranches(c, Array.from(branch)); - // }); - - // if (node.children.length === 0) { this.allBranches.push(branch); - // } } /** @private */ @@ -200,17 +190,6 @@ const SpvChain = class { return this.heightByHash.has(hash) || this.orphansHashes.has(hash); } - /** @private */ - // orphanReconnect() { - // for (let i = 0; i < this.orphanBlocks.length; i += 1) { - // const connectionTip = this.findConnection(this.orphanBlocks[i]); - // if (connectionTip) { - // connectionTip.children.push(this.orphanBlocks[i]); - // this.orphanBlocks.splice(i, 1); - // } - // } - // } - /** @private */ orphanChunksReconnect() { // TODO: consider optimizing with map of { [chunkHeadHash]: chunkIndex } @@ -233,28 +212,11 @@ const SpvChain = class { } } - /** @private */ - // TODO: remove - // getOrphans() { - // return this.orphanBlocks; - // } - /** @private */ getOrphanChunks() { return this.orphanChunks; } - /** @private */ - // processValidHeader(header) { - // const connection = this.findConnection(header); - // if (connection) { - // // connection.children.push(header); - // this.orphanReconnect(); - // } else { - // this.orphanBlocks.push(header); - // } - // } - /** @private * validates a dashcore.BlockHeader object * @@ -281,16 +243,9 @@ const SpvChain = class { if (utils.getCorrectedHash(header.prevHash) !== previousHeader.hash) { return false; } - // if (!header.children) { - // header.children = []; - // } - // if (!previousHeader.children) { - // previousHeader.children = []; - // } - // previousHeader.children.push(header); + return true; } - /* eslint-enable no-param-reassign */ /** * Returns the longest chain of headers @@ -337,44 +292,6 @@ const SpvChain = class { return this.getLongestChain().filter((h) => h.hash === hash)[0]; } - /** - * Gets specified amount of headers in the confirmed chain - * @param n - * @return Object[] - */ - getLastHeaders(n) { - const longestChain = this.getLongestChain(); - let headers = longestChain.slice(-n); - - if (headers.length < n) { - const remaining = n - headers.length; - headers = [...this.prunedHeaders.slice(-remaining), ...headers]; - } - - return headers; - } - - /** - * adds a valid header to the tip of the longest spv chain. - * If it cannot be connected to the tip it gets temporarily - * added to an orphan array for possible later reconnection - * - * @param {Object[]|string[]|buffer[]} header - * @return {boolean} - */ - // addHeader(header) { - // const headerNormalised = utils.normalizeHeader(header); - // - // if (this.isValid(headerNormalised, this.getLongestChain())) { - // // headerNormalised.children = []; - // this.processValidHeader(headerNormalised); - // this.setAllBranches(); - // this.checkPruneBlocks(); - // return true; - // } - // return false; - // } - /** * adds an array of valid headers to the longest spv chain. * If they cannot be connected to last tip they get temporarily @@ -385,39 +302,45 @@ const SpvChain = class { * @return {BlockHeader[]} */ addHeaders(headers, batchHeadHeight = 0) { - let headHeight = batchHeadHeight; - const normalizedHeaders = headers.map((h) => utils.normalizeHeader(h)); - - const tip = this.getTipHeader(); - // Handle 1 block intersection of batches - if (tip && tip.hash === normalizedHeaders[0].hash) { - normalizedHeaders.splice(0, 1); - // Patch head height value after splice - headHeight += 1; + if (!X11.ready()) { + throw new SPVError('X11 wasm not ready, call wasmX11Ready() first'); } - if (normalizedHeaders.length === 0) { - // The batch already in the chain, do nothing - return []; + if (!this.initialized()) { + throw new SPVError('Chain not initialized, either call initialize() or set pendingStartBlockHeight'); } - const firstHeader = normalizedHeaders[0]; - const connectsToTip = tip && SpvChain.isParentChild(firstHeader, tip); + const normalizedHeaders = headers.map((h) => utils.normalizeHeader(h)); - // - // Reorg detection - // Get prev header hash - const prevHash = utils.getCorrectedHash(firstHeader.prevHash); - const prevHeaderHeight = this.heightByHash.get(prevHash); + let isOrphan = false; - // Test on initial wallet load - if (prevHeaderHeight && prevHeaderHeight > 0 && prevHeaderHeight !== headHeight - 1) { - console.log('SPVCHAIN: Reorg detected.'); - console.log(`------->: Batch head ${firstHeader.hash} at height ${headHeight} has parent at height ${prevHeaderHeight}`); - } + // Chain is initialized, root block, and it's height are known + if (this.pendingStartBlockHeight === null) { + const tip = this.getTipHeader(); + // Handle 1 block intersection of batches + if (tip.hash === normalizedHeaders[0].hash) { + normalizedHeaders.splice(0, 1); + } - const isOrphan = tip ? !connectsToTip - : headHeight !== this.startBlockHeight; + if (normalizedHeaders.length === 0) { + // The batch already in the chain, do nothing + return []; + } + + const firstHeader = normalizedHeaders[0]; + + isOrphan = !SpvChain.isParentChild(firstHeader, tip); + } else if (batchHeadHeight === this.pendingStartBlockHeight) { + // Header at pendingStartBlockHeight is found, initialize chain + this.startBlockHeight = this.pendingStartBlockHeight; + this.pendingStartBlockHeight = null; + isOrphan = false; + } else if (batchHeadHeight > this.pendingStartBlockHeight) { + // Orphan chunk has arrived + isOrphan = true; + } else { + throw new SPVError(`Batch at invalid height arrived: ${batchHeadHeight}, expected > ${this.pendingStartBlockHeight}`); + } const allValid = normalizedHeaders.reduce( (acc, header, index, array) => { diff --git a/packages/dash-spv/lib/test/.eslintrc b/packages/dash-spv/lib/test/.eslintrc new file mode 100644 index 0000000000..4c2b11fe81 --- /dev/null +++ b/packages/dash-spv/lib/test/.eslintrc @@ -0,0 +1,9 @@ +{ + "env": { + "node": true, + "mocha": true + }, + "rules": { + "import/no-extraneous-dependencies": "off" + } +} diff --git a/packages/dash-spv/lib/test/bootstrap.js b/packages/dash-spv/lib/test/bootstrap.js new file mode 100644 index 0000000000..53142f9ec2 --- /dev/null +++ b/packages/dash-spv/lib/test/bootstrap.js @@ -0,0 +1,19 @@ +const sinon = require('sinon'); + +beforeEach(function beforeEach() { + if (!this.sinon) { + this.sinon = sinon.createSandbox(); + } else { + this.sinon.restore(); + } +}); + +before(function before() { + if (!this.sinon) { + this.sinon = sinon.createSandbox(); + } +}); + +afterEach(function afterEach() { + this.sinon.restore(); +}); diff --git a/packages/dash-spv/lib/x11.js b/packages/dash-spv/lib/x11.js new file mode 100644 index 0000000000..d85e555bad --- /dev/null +++ b/packages/dash-spv/lib/x11.js @@ -0,0 +1,27 @@ +const { configure: configureDashcore } = require('@dashevo/dashcore-lib'); +const X11 = require('wasm-x11-hash'); + +let x11Promise = null; +let x11Ready = false; + +const load = async () => { + if (!x11Promise) { + x11Promise = X11().then( + (x11Hash) => { + configureDashcore({ + x11hash: x11Hash, + }); + x11Ready = true; + }, + ); + } + + return x11Promise; +}; + +const ready = () => x11Ready; + +module.exports = { + ready, + load, +}; diff --git a/packages/dash-spv/package.json b/packages/dash-spv/package.json index 636511f860..4660fa7fb9 100644 --- a/packages/dash-spv/package.json +++ b/packages/dash-spv/package.json @@ -16,7 +16,8 @@ "@dashevo/dash-util": "^2.0.3", "@dashevo/dashcore-lib": "~0.20.9", "levelup": "^4.4.0", - "memdown": "^5.1.0" + "memdown": "^5.1.0", + "wasm-x11-hash": "~0.0.2" }, "devDependencies": { "chai": "^4.3.4", @@ -24,6 +25,7 @@ "eslint-config-airbnb-base": "^14.2.1", "eslint-plugin-import": "^2.24.2", "mocha": "^9.1.2", - "should": "^13.2.3" + "should": "^13.2.3", + "sinon": "^11.1.2" } } diff --git a/packages/dash-spv/test/index.js b/packages/dash-spv/test/index.js index e937184e5e..4b67c838fa 100644 --- a/packages/dash-spv/test/index.js +++ b/packages/dash-spv/test/index.js @@ -16,8 +16,10 @@ let merkleBlock = null; let merkleBlock2 = null; describe('SPV-DASH (forks & re-orgs) deserialized headers', () => { - before(() => { + before(async () => { chain = new Blockchain('testnet'); + await Blockchain.wasmX11Ready(); + chain.initialize(); }); it('should get 26 testnet headers', () => { @@ -83,8 +85,9 @@ describe('SPV-DASH (forks & re-orgs) deserialized headers', () => { }); describe('SPV-DASH (forks & re-orgs) serialized raw headers for mainnet', () => { - before(() => { - chain = new Blockchain('mainnet', 10000, utils.normalizeHeader(mainnet[0])); + before(async () => { + chain = new Blockchain('mainnet', 10000); + chain.initialize(utils.normalizeHeader(mainnet[0]), 1); }); it('should get 2000 mainnet headers', () => { @@ -127,8 +130,9 @@ describe('SPV-DASH (forks & re-orgs) serialized raw headers for mainnet', () => }); describe('SPV-DASH (addHeaders) add many headers for testnet', () => { - before(() => { - chain = new Blockchain('testnet', 10000, utils.normalizeHeader(testnet[0])); + before(async () => { + chain = new Blockchain('testnet', 10000); + chain.initialize(utils.normalizeHeader(testnet[0]), 1); }); it('should add the 1st 250 testnet headers', () => { @@ -146,7 +150,8 @@ describe('SPV-DASH (addHeaders) add many headers for testnet', () => { }); it('should add the 1st 250 testnet2 headers', () => { - chain = new Blockchain('testnet', 10000, utils.normalizeHeader(testnet2[0])); + chain = new Blockchain('testnet', 10000); + chain.initialize(utils.normalizeHeader(testnet2[0]), 1); chain.addHeaders(testnet2.slice(1, 250)); chain.getOrphanChunks().length.should.equal(0); chain.getAllBranches().length.should.equal(1); @@ -161,7 +166,8 @@ describe('SPV-DASH (addHeaders) add many headers for testnet', () => { }); it('should add the 1st 250 testnet3 headers', () => { - chain = new Blockchain('testnet', 10000, utils.normalizeHeader(testnet3[0])); + chain = new Blockchain('testnet', 10000); + chain.initialize(utils.normalizeHeader(testnet3[0]), 1); chain.addHeaders(testnet3.slice(1, 250)); chain.getOrphanChunks().length.should.equal(0); chain.getAllBranches().length.should.equal(1); @@ -199,7 +205,8 @@ describe('SPV-DASH (addHeaders) add many headers for testnet', () => { describe('SPV-DASH (addHeaders) add testnet headers out of order', () => { before(() => { - chain = new Blockchain('testnet', 10000, utils.normalizeHeader(testnet[0])); + chain = new Blockchain('testnet', 10000); + chain.initialize(utils.normalizeHeader(testnet[0]), 1); }); it('should add the 1st 100 testnet headers', () => { @@ -242,7 +249,8 @@ describe('SPV-DASH (addHeaders) add testnet headers out of order', () => { describe('SPV-DASH (addHeaders) add many headers for mainnet', () => { before(() => { - chain = new Blockchain('mainnet', 10000, utils.normalizeHeader(mainnet[0])); + chain = new Blockchain('mainnet', 10000); + chain.initialize(utils.normalizeHeader(mainnet[0]), 1); }); it('should add the 1st 500 mainnet headers', () => { @@ -290,7 +298,8 @@ describe('SPV-DASH (addHeaders) add many headers for mainnet', () => { describe('SPV-DASH (addHeaders) add mainnet headers out of order', () => { before(() => { - chain = new Blockchain('mainnet', 10000, utils.normalizeHeader(mainnet[0])); + chain = new Blockchain('mainnet', 10000); + chain.initialize(utils.normalizeHeader(mainnet[0]), 1); }); it('should add the 1st 100 mainnet headers', () => { @@ -377,7 +386,8 @@ describe('MerkleProofs', () => { describe('Transaction validation', () => { before(() => { - chain = new Blockchain('testnet', 10000, utils.normalizeHeader(testnet[0])); + chain = new Blockchain('testnet', 10000); + chain.initialize(utils.normalizeHeader(testnet[0]), 1); chain.addHeaders(testnet.slice(1, 500)); }); diff --git a/packages/dash-spv/test/spvchain.js b/packages/dash-spv/test/spvchain.js index 7e6c93b2e6..58a7716c91 100644 --- a/packages/dash-spv/test/spvchain.js +++ b/packages/dash-spv/test/spvchain.js @@ -1,19 +1,65 @@ const { expect } = require('chai'); +const X11 = require('../lib/x11'); const { SpvChain } = require('../index'); - const { testnet } = require('./data/rawHeaders'); describe('SPVChain', () => { let spvChain; - beforeEach(() => { + beforeEach(async () => { spvChain = new SpvChain('testnet', 100); + await SpvChain.wasmX11Ready(); + }); + + describe('#initialize', () => { + it('should throw an error if wasmX11 is not initialized', function it() { + this.sinon.stub(X11, 'ready').returns(false); + expect(() => spvChain.initialize()) + .to.throw('X11 wasm not ready, call wasmX11Ready() first'); + }); + + it('should throw an error if chain is already initialized', async () => { + spvChain.initialize(testnet[0], 10000); + expect(() => spvChain.initialize()) + .to.throw('Chain already initialized'); + }); + + it('should initialize chain with genesis header', async () => { + spvChain.initialize(); + expect(spvChain.startBlockHeight).to.be.equal(0); + expect(spvChain.getLongestChain()) + .to.be.deep.equal([spvChain.genesis]); + }); + + it('should not allow initializing from arbitrary block without height', () => { + expect(() => spvChain.initialize(testnet[0])) + .to.throw('Initialization error, please provide both startBlock and height'); + }); + + it('should initialize from arbitrary block', () => { + spvChain.initialize(testnet[0], 10000); + expect(spvChain.startBlockHeight).to.be.equal(10000); + expect(spvChain.getLongestChain()[0].toBuffer().toString('hex')) + .to.be.equal(testnet[0]); + }); }); describe('#addHeaders', () => { - it('should assemble headers chain if headers arriving out of order', () => { + it('should throw an error if wasmX11 is not initialized', function it() { + this.sinon.stub(X11, 'ready').returns(false); + expect(() => spvChain.addHeaders(testnet.slice(400))) + .to.throw('X11 wasm not ready, call wasmX11Ready() first'); + }); + + it('should throw an error if chain is not initialized', async () => { + expect(() => spvChain.addHeaders(testnet.slice(400))) + .to.throw('Chain not initialized, either call initialize() or set pendingStartBlockHeight'); + }); + + it('should assemble headers chain if headers arriving out of order', async () => { expect(true).to.equal(true); - spvChain.reset(10000); + + spvChain.initialize(testnet[0], 10000); spvChain.addHeaders(testnet.slice(400), 10400); expect(spvChain.getOrphanChunks()).to.have.length(1); diff --git a/packages/js-dapi-client/lib/BlockHeadersProvider/BlockHeadersProvider.js b/packages/js-dapi-client/lib/BlockHeadersProvider/BlockHeadersProvider.js index 459bc939eb..44229f8bcf 100644 --- a/packages/js-dapi-client/lib/BlockHeadersProvider/BlockHeadersProvider.js +++ b/packages/js-dapi-client/lib/BlockHeadersProvider/BlockHeadersProvider.js @@ -1,6 +1,4 @@ const EventEmitter = require('events'); -const { configure: configureDashcore } = require('@dashevo/dashcore-lib'); -const X11 = require('wasm-x11-hash'); const { SpvChain, SPVError } = require('@dashevo/dash-spv'); const BlockHeadersReader = require('./BlockHeadersReader'); @@ -51,7 +49,6 @@ class BlockHeadersProvider extends EventEmitter { this.spvChain = new SpvChain(this.options.network, 100); this.state = STATES.IDLE; - this.wasmX11Ready = false; this.errorHandler = this.errorHandler.bind(this); this.headersHandler = this.headersHandler.bind(this); @@ -79,13 +76,7 @@ class BlockHeadersProvider extends EventEmitter { * @private */ async init() { - if (!this.wasmX11Ready) { - const x11Hash = await X11(); - configureDashcore({ - x11hash: x11Hash, - }); - this.wasmX11Ready = true; - } + await SpvChain.wasmX11Ready(); if (!this.blockHeadersReader) { this.blockHeadersReader = new BlockHeadersReader( @@ -113,12 +104,18 @@ class BlockHeadersProvider extends EventEmitter { * Initializes SPV chain with a list of headers and a known lastSyncedHeaderHeight * * @param headers - * @param lastSyncedHeaderHeight + * @param firstHeaderHeight */ - initializeWith(headers, lastSyncedHeaderHeight) { - const firstHeaderHeight = lastSyncedHeaderHeight - headers.length + 1; - this.spvChain.reset(firstHeaderHeight); - this.spvChain.addHeaders(headers, firstHeaderHeight); + async initializeChainWith(headers, firstHeaderHeight) { + await SpvChain.wasmX11Ready(); + + if (headers.length === 0) { + // If there are no headers, initialize chain from genesis + this.spvChain.initialize(); + } else { + this.spvChain.initialize(headers[0], firstHeaderHeight); + this.spvChain.addHeaders(headers); + } } /** @@ -130,7 +127,8 @@ class BlockHeadersProvider extends EventEmitter { ensureChainRoot(height) { // Flush spv chain in case header at specified height was not found if (!this.spvChain.hashesByHeight.has(height - 1)) { - this.spvChain.reset(height); + this.spvChain.reset(); + this.spvChain.pendingStartBlockHeight = height; } } diff --git a/packages/js-dapi-client/test/integration/BlockHeadersProvider/BlockHeadersProvider.spec.js b/packages/js-dapi-client/test/integration/BlockHeadersProvider/BlockHeadersProvider.spec.js index 423b8f4855..cc731c751a 100644 --- a/packages/js-dapi-client/test/integration/BlockHeadersProvider/BlockHeadersProvider.spec.js +++ b/packages/js-dapi-client/test/integration/BlockHeadersProvider/BlockHeadersProvider.spec.js @@ -11,7 +11,7 @@ describe('BlockHeadersProvider - integration', function describe() { let historicalStreams = []; let continuousStream; - const createBlockHeadersProvider = (sinon, opts = {}) => { + const createBlockHeadersProvider = async (sinon, opts = {}) => { historicalStreams = []; continuousStream = null; @@ -39,6 +39,7 @@ describe('BlockHeadersProvider - integration', function describe() { count: 0, }), ); + await blockHeadersProvider.initializeChainWith([], 0); }; // Start from height bigger than the first block @@ -59,7 +60,7 @@ describe('BlockHeadersProvider - integration', function describe() { before(async function () { headers = await mockHeadersChain('testnet', numHeaders); - createBlockHeadersProvider(this.sinon, { + await createBlockHeadersProvider(this.sinon, { targetBatchSize: historicalBatchSize, }); }); diff --git a/packages/js-dapi-client/test/unit/BlockHeadersProvider/BlockHeadersProvider.spec.js b/packages/js-dapi-client/test/unit/BlockHeadersProvider/BlockHeadersProvider.spec.js index c4961ee2bd..533653210d 100644 --- a/packages/js-dapi-client/test/unit/BlockHeadersProvider/BlockHeadersProvider.spec.js +++ b/packages/js-dapi-client/test/unit/BlockHeadersProvider/BlockHeadersProvider.spec.js @@ -10,15 +10,20 @@ const getHeadersFixture = require('../../../lib/test/fixtures/getHeadersFixture' describe('BlockHeadersProvider - unit', () => { let blockHeadersProvider; let headers; + let spvChain; beforeEach(function () { blockHeadersProvider = new BlockHeadersProvider(); - blockHeadersProvider.setSpvChain({ + spvChain = { addHeaders: this.sinon.stub().callsFake((newHeaders) => newHeaders), hashesByHeight: new Map([[0, '0x000000001']]), reset: this.sinon.spy(), validate: this.sinon.spy(), - }); + wasmX11Ready: this.sinon.stub().returns(true), + initialized: this.sinon.stub().returns(true), + initialize: this.sinon.stub(), + }; + blockHeadersProvider.setSpvChain(spvChain); const blockHeadersReader = new EventEmitter(); blockHeadersReader.readHistorical = this.sinon.spy(); @@ -140,7 +145,9 @@ describe('BlockHeadersProvider - unit', () => { it('should reset SPV chain in case header at specified height is missing', async () => { blockHeadersProvider.ensureChainRoot(2); expect(blockHeadersProvider.spvChain.reset) - .to.have.been.calledOnceWith(2); + .to.have.been.calledOnce(); + expect(blockHeadersProvider.spvChain.pendingStartBlockHeight) + .to.equal(2); }); }); diff --git a/packages/wallet-lib/src/test/mocks/TransportMock.js b/packages/wallet-lib/src/test/mocks/TransportMock.js index 7bd267dd16..a91b84b94a 100644 --- a/packages/wallet-lib/src/test/mocks/TransportMock.js +++ b/packages/wallet-lib/src/test/mocks/TransportMock.js @@ -31,6 +31,7 @@ class TransportMock extends EventEmitter { provider.stop = sinonSandbox.stub().callsFake(() => { provider.emit('STOPPED'); }); + provider.initializeChainWith = sinonSandbox.spy(); provider.readHistorical = sinonSandbox.spy(); provider.startContinuousSync = sinonSandbox.spy(); provider.spvChain = { diff --git a/packages/wallet-lib/src/types/Account/Account.spec.js b/packages/wallet-lib/src/types/Account/Account.spec.js index 1e0f01d915..8d56e1943f 100644 --- a/packages/wallet-lib/src/types/Account/Account.spec.js +++ b/packages/wallet-lib/src/types/Account/Account.spec.js @@ -44,6 +44,13 @@ describe('Account - class', function suite() { this.accounts = []; this.network = Dashcore.Networks.testnet; this.storage = new Storage(); + this.transport = { + client: { + blockHeadersProvider: { + initializeChainWith: () => {} + } + } + } })()); mocks.wallet.storage.application.network = mocks.wallet.network; mocks.wallet.storage.currentNetwork = mocks.wallet.network.toString() diff --git a/packages/wallet-lib/src/types/Account/_initializeAccount.js b/packages/wallet-lib/src/types/Account/_initializeAccount.js index 835ac5a18b..3a034f21e6 100644 --- a/packages/wallet-lib/src/types/Account/_initializeAccount.js +++ b/packages/wallet-lib/src/types/Account/_initializeAccount.js @@ -16,9 +16,10 @@ async function _initializeAccount(account, userUnsafePlugins) { // Add block headers from storage into the SPV chain if there are any const chainStore = self.storage.getDefaultChainStore(); const { blockHeaders, lastSyncedHeaderHeight } = chainStore.state; - if (!self.offlineMode && blockHeaders.length > 0) { + if (!self.offlineMode) { const { blockHeadersProvider } = self.transport.client; - blockHeadersProvider.initializeWith(blockHeaders, lastSyncedHeaderHeight); + const firstHeaderHeight = lastSyncedHeaderHeight - blockHeaders.length + 1; + await blockHeadersProvider.initializeChainWith(blockHeaders, firstHeaderHeight); } // We run faster in offlineMode to speed up the process when less happens. diff --git a/packages/wallet-lib/tests/integration/plugins/Workers/BlockHeadersSyncWorker.spec.js b/packages/wallet-lib/tests/integration/plugins/Workers/BlockHeadersSyncWorker.spec.js index 0d90dacc8f..a64b2e06a4 100644 --- a/packages/wallet-lib/tests/integration/plugins/Workers/BlockHeadersSyncWorker.spec.js +++ b/packages/wallet-lib/tests/integration/plugins/Workers/BlockHeadersSyncWorker.spec.js @@ -51,6 +51,7 @@ describe('BlockHeadersSyncWorker - integration', () => { continuousStream, TOTAL_HEADERS_PER_STREAM, ); + await blockHeadersProvider.initializeChainWith([], 0); const storage = await mockStorage({ withAdapter, }); @@ -86,7 +87,7 @@ describe('BlockHeadersSyncWorker - integration', () => { // Only first batch from the first stream that attaches to genesis block gets verified // The rest marked as orphaned because some batches are missing // and there's no connection yet between them - it('should process first batch of from first stream and consider remaining batches as orphaned', async () => { + it('should process first batch from first stream and consider remaining batches as orphaned', async () => { const chainStore = blockHeadersSyncWorker.storage.getDefaultChainStore(); // Wait for the stream to start @@ -265,6 +266,7 @@ describe('BlockHeadersSyncWorker - integration', () => { // Reset spv chain blockHeadersProvider.spvChain.reset(); + await blockHeadersProvider.initializeChainWith([], 0); blockHeadersProvider.spvChain .addHeaders(storage.getDefaultChainStore().state.blockHeaders); diff --git a/yarn.lock b/yarn.lock index cd81c99f01..6d114d67d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1495,6 +1495,8 @@ __metadata: memdown: ^5.1.0 mocha: ^9.1.2 should: ^13.2.3 + sinon: ^11.1.2 + wasm-x11-hash: ~0.0.2 languageName: unknown linkType: soft From 4f1e2f497d06f126543d01d930c676c4890f9792 Mon Sep 17 00:00:00 2001 From: strophy <32928115+strophy@users.noreply.github.com> Date: Tue, 27 Jun 2023 17:12:09 +1000 Subject: [PATCH 06/19] feat(dashmate): configure tenderdash pprof (#1201) Co-authored-by: Ivan Shumkov --- packages/dashmate/configs/migrations.js | 10 ++++++++++ .../dashmate/configs/schema/configJsonSchema.js | 15 ++++++++++++++- packages/dashmate/configs/system/base.js | 4 ++++ packages/dashmate/docker-compose.platform.yml | 1 + .../tasks/setup/setupLocalPresetTaskFactory.js | 1 + .../platform/drive/tenderdash/config.toml.dot | 2 +- 6 files changed, 31 insertions(+), 2 deletions(-) diff --git a/packages/dashmate/configs/migrations.js b/packages/dashmate/configs/migrations.js index 9bd4907842..eaba47b35d 100644 --- a/packages/dashmate/configs/migrations.js +++ b/packages/dashmate/configs/migrations.js @@ -575,11 +575,21 @@ module.exports = { return configFile; }, '0.24.12': (configFile) => { + let i = 0; Object.entries(configFile.configs) .forEach(([, config]) => { // Update ports config.platform.dashmate.helper.api.port = systemConfigs.base.platform .dashmate.helper.api.port; + + if (config.group === 'local') { + config.set('platform.drive.tenderdash.pprof.port', systemConfigs.base.platform + .drive.tenderdash.pprof + (i * 100)); + i++; + } else { + config.platform.drive.tenderdash.pprof = systemConfigs.base.platform + .drive.tenderdash.pprof; + } }); return configFile; }, diff --git a/packages/dashmate/configs/schema/configJsonSchema.js b/packages/dashmate/configs/schema/configJsonSchema.js index 26fc80ad3b..fa464b8135 100644 --- a/packages/dashmate/configs/schema/configJsonSchema.js +++ b/packages/dashmate/configs/schema/configJsonSchema.js @@ -511,6 +511,19 @@ module.exports = { required: ['port'], additionalProperties: false, }, + pprof: { + type: 'object', + properties: { + enabled: { + type: 'boolean', + }, + port: { + $ref: '#/definitions/port', + }, + }, + required: ['enabled', 'port'], + additionalProperties: false, + }, node: { type: 'object', properties: { @@ -530,7 +543,7 @@ module.exports = { type: 'object', }, }, - required: ['docker', 'p2p', 'rpc', 'consensus', 'node', 'moniker', 'genesis'], + required: ['docker', 'p2p', 'rpc', 'pprof', 'consensus', 'node', 'moniker', 'genesis'], additionalProperties: false, }, }, diff --git a/packages/dashmate/configs/system/base.js b/packages/dashmate/configs/system/base.js index aef4302510..bb484a055a 100644 --- a/packages/dashmate/configs/system/base.js +++ b/packages/dashmate/configs/system/base.js @@ -165,6 +165,10 @@ module.exports = { rpc: { port: 26657, }, + pprof: { + enabled: false, + port: 6060, + }, consensus: { createEmptyBlocks: true, createEmptyBlocksInterval: '3m', diff --git a/packages/dashmate/docker-compose.platform.yml b/packages/dashmate/docker-compose.platform.yml index 1f722ec6fb..b2d08673f8 100644 --- a/packages/dashmate/docker-compose.platform.yml +++ b/packages/dashmate/docker-compose.platform.yml @@ -40,6 +40,7 @@ services: ports: - ${PLATFORM_DRIVE_TENDERDASH_P2P_PORT:?err}:${PLATFORM_DRIVE_TENDERDASH_P2P_PORT:?err} # P2P - 127.0.0.1:${PLATFORM_DRIVE_TENDERDASH_RPC_PORT:?err}:${PLATFORM_DRIVE_TENDERDASH_RPC_PORT:?err} # RPC + - 127.0.0.1:${PLATFORM_DRIVE_TENDERDASH_PPROF_PORT:?err}:${PLATFORM_DRIVE_TENDERDASH_PPROF_PORT:?err} # pprof volumes: - drive_tenderdash:/tenderdash - ${DASHMATE_HOME_DIR:?err}/${CONFIG_NAME:?err}/platform/drive/tenderdash:/tenderdash/config:ro diff --git a/packages/dashmate/src/listr/tasks/setup/setupLocalPresetTaskFactory.js b/packages/dashmate/src/listr/tasks/setup/setupLocalPresetTaskFactory.js index 272b4235b4..2538de97af 100644 --- a/packages/dashmate/src/listr/tasks/setup/setupLocalPresetTaskFactory.js +++ b/packages/dashmate/src/listr/tasks/setup/setupLocalPresetTaskFactory.js @@ -216,6 +216,7 @@ function setupLocalPresetTaskFactory( config.set('platform.dapi.envoy.http.port', config.get('platform.dapi.envoy.http.port') + (i * 100)); config.set('platform.drive.tenderdash.p2p.port', config.get('platform.drive.tenderdash.p2p.port') + (i * 100)); config.set('platform.drive.tenderdash.rpc.port', config.get('platform.drive.tenderdash.rpc.port') + (i * 100)); + config.set('platform.drive.tenderdash.pprof.port', config.get('platform.drive.tenderdash.pprof.port') + (i * 100)); config.set('platform.drive.tenderdash.moniker', config.name); // Setup logs diff --git a/packages/dashmate/templates/platform/drive/tenderdash/config.toml.dot b/packages/dashmate/templates/platform/drive/tenderdash/config.toml.dot index 25f493d1b4..dd5bbed486 100644 --- a/packages/dashmate/templates/platform/drive/tenderdash/config.toml.dot +++ b/packages/dashmate/templates/platform/drive/tenderdash/config.toml.dot @@ -212,7 +212,7 @@ tls-cert-file = "" tls-key-file = "" # pprof listen address (https://golang.org/pkg/net/http/pprof) -pprof-laddr = "" +pprof-laddr = "{{? it.platform.drive.tenderdash.pprof.enabled}}:{{=it.platform.drive.tenderdash.pprof.port}}{{?}}" ####################################################### ### P2P Configuration Options ### From cab74e8f84edc2491d98813622a70b74eb2d4fca Mon Sep 17 00:00:00 2001 From: Djavid Gabibiyan Date: Tue, 27 Jun 2023 17:12:28 +0500 Subject: [PATCH 07/19] test(dashmate): e2e tests (#1152) Co-authored-by: shuplenkov Co-authored-by: Ivan Shumkov --- packages/dashmate/package.json | 3 +- .../src/listr/tasks/setup/nodeTypes.js | 10 + .../setup/regular/configureNodeTaskFactory.js | 28 ++- .../configureSSLCertificateTaskFactory.js | 80 ++++---- .../setup/setupRegularPresetTaskFactory.js | 59 +++--- .../src/test/areServicesRunningFactory.js | 42 ++++ .../src/test/constants/insightLinks.js | 8 + .../dashmate/src/test/constants/services.js | 14 ++ .../src/test/constants/statusOutput.js | 11 ++ .../src/test/createSelfSignedCertificate.js | 21 ++ .../src/test/isServiceRunningFactory.js | 28 +++ .../src/test/waitForCoreDataFactory.js | 30 +++ packages/dashmate/test/bootstrap.js | 3 - packages/dashmate/test/e2e/localNetwork.js | 141 +++++++++++++ .../dashmate/test/e2e/testnetFullnode.spec.js | 185 ++++++++++++++++++ .../test/e2e/testnetHPFullnode.spec.js | 185 ++++++++++++++++++ 16 files changed, 771 insertions(+), 77 deletions(-) create mode 100644 packages/dashmate/src/test/areServicesRunningFactory.js create mode 100644 packages/dashmate/src/test/constants/insightLinks.js create mode 100644 packages/dashmate/src/test/constants/services.js create mode 100644 packages/dashmate/src/test/constants/statusOutput.js create mode 100644 packages/dashmate/src/test/createSelfSignedCertificate.js create mode 100644 packages/dashmate/src/test/isServiceRunningFactory.js create mode 100644 packages/dashmate/src/test/waitForCoreDataFactory.js create mode 100644 packages/dashmate/test/e2e/localNetwork.js create mode 100644 packages/dashmate/test/e2e/testnetFullnode.spec.js create mode 100644 packages/dashmate/test/e2e/testnetHPFullnode.spec.js diff --git a/packages/dashmate/package.json b/packages/dashmate/package.json index 8ed5d30cd2..f184de9ff9 100644 --- a/packages/dashmate/package.json +++ b/packages/dashmate/package.json @@ -7,8 +7,9 @@ "postpack": "rm -f oclif.manifest.json", "prepack": "oclif manifest && oclif readme", "version": "oclif readme && git add README.md", - "test": "yarn run test:unit", + "test": "yarn run test:unit && yarn run test:e2e", "test:unit": "mocha --recursive test/unit", + "test:e2e": "mocha --recursive test/e2e", "helper": "node scripts/helper.js" }, "repository": { diff --git a/packages/dashmate/src/listr/tasks/setup/nodeTypes.js b/packages/dashmate/src/listr/tasks/setup/nodeTypes.js index dcf33770c1..d01d018195 100644 --- a/packages/dashmate/src/listr/tasks/setup/nodeTypes.js +++ b/packages/dashmate/src/listr/tasks/setup/nodeTypes.js @@ -17,6 +17,11 @@ const NODE_TYPE_NAME_TYPES = { [NODE_TYPE_NAMES.HP_FULLNODE]: NODE_TYPE_FULLNODE, }; +const NODE_TYPE_NAME_BY_TYPE = { + [NODE_TYPE_MASTERNODE]: NODE_TYPE_NAMES.MASTERNODE, + [NODE_TYPE_FULLNODE]: NODE_TYPE_NAMES.FULLNODE, +}; + function isNodeTypeNameHighPerformance(nodeTypeName) { return [NODE_TYPE_NAMES.HP_MASTERNODE, NODE_TYPE_NAMES.HP_FULLNODE].includes(nodeTypeName); } @@ -25,8 +30,13 @@ function getNodeTypeByName(nodeTypeName) { return NODE_TYPE_NAME_TYPES[nodeTypeName]; } +function getNodeTypeNameByType(nodeType) { + return NODE_TYPE_NAME_BY_TYPE[nodeType]; +} + module.exports = { NODE_TYPE_NAMES, isNodeTypeNameHighPerformance, getNodeTypeByName, + getNodeTypeNameByType, }; diff --git a/packages/dashmate/src/listr/tasks/setup/regular/configureNodeTaskFactory.js b/packages/dashmate/src/listr/tasks/setup/regular/configureNodeTaskFactory.js index e6e0ad8253..60900750d5 100644 --- a/packages/dashmate/src/listr/tasks/setup/regular/configureNodeTaskFactory.js +++ b/packages/dashmate/src/listr/tasks/setup/regular/configureNodeTaskFactory.js @@ -49,9 +49,12 @@ function configureNodeTaskFactory() { // Platform Node Key if (ctx.isHP) { - const platformNodeKey = await task.prompt(createPlatformNodeKeyInput({ - skipInitial: ctx.nodeType === NODE_TYPE_MASTERNODE, - })); + let platformNodeKey = ctx.tenderdashNodeKey; + if (!ctx.tenderdashNodeKey) { + platformNodeKey = await task.prompt(createPlatformNodeKeyInput({ + skipInitial: ctx.nodeType === NODE_TYPE_MASTERNODE, + })); + } ctx.config.set('platform.drive.tenderdash.node.id', deriveTenderdashNodeId(platformNodeKey)); ctx.config.set('platform.drive.tenderdash.node.key', platformNodeKey); @@ -65,13 +68,18 @@ function configureNodeTaskFactory() { const showEmptyPort = ctx.preset !== PRESET_MAINNET && ctx.nodeType !== NODE_TYPE_FULLNODE; - const form = await task.prompt(await createIpAndPortsForm(ctx.preset, { - isHPMN: ctx.isHP, - initialIp: '', - initialCoreP2PPort: showEmptyPort ? '' : undefined, - initialPlatformHTTPPort: showEmptyPort ? '' : undefined, - initialPlatformP2PPort: showEmptyPort ? '' : undefined, - })); + let form; + if (ctx.initialIpForm) { + form = ctx.initialIpForm; + } else { + form = await task.prompt(await createIpAndPortsForm(ctx.preset, { + isHPMN: ctx.isHP, + initialIp: '', + initialCoreP2PPort: showEmptyPort ? '' : undefined, + initialPlatformHTTPPort: showEmptyPort ? '' : undefined, + initialPlatformP2PPort: showEmptyPort ? '' : undefined, + })); + } ctx.config.set('externalIp', form.ip); ctx.config.set('core.p2p.port', form.coreP2PPort); diff --git a/packages/dashmate/src/listr/tasks/setup/regular/configureSSLCertificateTaskFactory.js b/packages/dashmate/src/listr/tasks/setup/regular/configureSSLCertificateTaskFactory.js index d0ecf84d78..217b17ebaf 100644 --- a/packages/dashmate/src/listr/tasks/setup/regular/configureSSLCertificateTaskFactory.js +++ b/packages/dashmate/src/listr/tasks/setup/regular/configureSSLCertificateTaskFactory.js @@ -33,37 +33,41 @@ function configureSSLCertificateTaskFactory( title: 'Set SSL certificate file', enabled: (ctx) => ctx.certificateProvider === SSL_PROVIDERS.FILE, task: async (ctx, task) => { - const form = await task.prompt({ - type: 'form', - message: 'Specify paths to your certificate files', - choices: [ - { - name: 'chainFilePath', - message: 'Path to certificate chain file', - validate: validateFileExists, - }, - { - name: 'privateFilePath', - message: 'Path to certificate key file', - validate: validateFileExists, - }, - ], - validate: ({ chainFilePath, privateFilePath }) => { - if (!validateFileExists(chainFilePath)) { - return 'certificate chain file path is not valid'; - } - - if (!validateFileExists(privateFilePath)) { - return 'certificate key file path is not valid'; - } - - if (chainFilePath === privateFilePath) { - return 'the same path for both files'; - } + let form = ctx.fileCertificateProviderForm; + + if (!ctx.fileCertificateProviderForm) { + form = await task.prompt({ + type: 'form', + message: 'Specify paths to your certificate files', + choices: [ + { + name: 'chainFilePath', + message: 'Path to certificate chain file', + validate: validateFileExists, + }, + { + name: 'privateFilePath', + message: 'Path to certificate key file', + validate: validateFileExists, + }, + ], + validate: ({ chainFilePath, privateFilePath }) => { + if (!validateFileExists(chainFilePath)) { + return 'certificate chain file path is not valid'; + } + + if (!validateFileExists(privateFilePath)) { + return 'certificate key file path is not valid'; + } + + if (chainFilePath === privateFilePath) { + return 'the same path for both files'; + } - return true; - }, - }); + return true; + }, + }); + } ctx.certificateFile = fs.readFileSync(form.chainFilePath, 'utf8'); ctx.privateKeyFile = fs.readFileSync(form.privateFilePath, 'utf8'); @@ -130,13 +134,15 @@ function configureSSLCertificateTaskFactory( choices.push({ name: SSL_PROVIDERS.SELF_SIGNED, message: 'Self-signed' }); } - ctx.certificateProvider = await task.prompt({ - type: 'select', - header, - message: 'How do you want to configure SSL?', - choices, - initial: SSL_PROVIDERS.ZEROSSL, - }); + if (!ctx.certificateProvider) { + ctx.certificateProvider = await task.prompt({ + type: 'select', + header, + message: 'How do you want to configure SSL?', + choices, + initial: SSL_PROVIDERS.ZEROSSL, + }); + } ctx.config.set('platform.dapi.envoy.ssl.provider', ctx.certificateProvider); diff --git a/packages/dashmate/src/listr/tasks/setup/setupRegularPresetTaskFactory.js b/packages/dashmate/src/listr/tasks/setup/setupRegularPresetTaskFactory.js index 2f8a409105..c121d70b0b 100644 --- a/packages/dashmate/src/listr/tasks/setup/setupRegularPresetTaskFactory.js +++ b/packages/dashmate/src/listr/tasks/setup/setupRegularPresetTaskFactory.js @@ -14,6 +14,7 @@ const systemConfigs = require('../../../../configs/system'); const { NODE_TYPE_NAMES, getNodeTypeByName, + getNodeTypeNameByType, isNodeTypeNameHighPerformance, } = require('./nodeTypes'); @@ -51,31 +52,37 @@ function setupRegularPresetTaskFactory( { title: 'Node type', task: async (ctx, task) => { - const nodeTypeName = await task.prompt([ - { - type: 'select', - // Keep this order, because each item references the text in the previous item - header: ` The Dash network consists of several different node types: - Fullnode - Host the full Dash blockchain (no collateral) - Masternode - Fullnode features, plus Core services such as ChainLocks - and InstantSend (1000 DASH collateral) - Evolution fullnode - Fullnode features, plus host a full copy of the Platform - blockchain (no collateral) - Evolution masternode - Masternode features, plus Platform services such as DAPI - and Drive (4000 DASH collateral)\n`, - message: 'Select node type', - choices: [ - { name: NODE_TYPE_NAMES.FULLNODE }, - { name: NODE_TYPE_NAMES.MASTERNODE, hint: '1000 DASH collateral' }, - { name: NODE_TYPE_NAMES.HP_FULLNODE }, - { name: NODE_TYPE_NAMES.HP_MASTERNODE, hint: '4000 DASH collateral' }, - ], - initial: NODE_TYPE_NAMES.MASTERNODE, - }, - ]); - - ctx.nodeType = getNodeTypeByName(nodeTypeName); - ctx.isHP = isNodeTypeNameHighPerformance(nodeTypeName); + let nodeTypeName; + + if (!ctx.nodeType) { + nodeTypeName = await task.prompt([ + { + type: 'select', + // Keep this order, because each item references the text in the previous item + header: ` The Dash network consists of several different node types: + Fullnode - Host the full Dash blockchain (no collateral) + Masternode - Fullnode features, plus Core services such as ChainLocks + and InstantSend (1000 DASH collateral) + Evolution fullnode - Fullnode features, plus host a full copy of the Platform + blockchain (no collateral) + Evolution masternode - Masternode features, plus Platform services such as DAPI + and Drive (4000 DASH collateral)\n`, + message: 'Select node type', + choices: [ + { name: NODE_TYPE_NAMES.FULLNODE }, + { name: NODE_TYPE_NAMES.MASTERNODE, hint: '1000 DASH collateral' }, + { name: NODE_TYPE_NAMES.HP_FULLNODE }, + { name: NODE_TYPE_NAMES.HP_MASTERNODE, hint: '4000 DASH collateral' }, + ], + initial: NODE_TYPE_NAMES.MASTERNODE, + }, + ]); + + ctx.nodeType = getNodeTypeByName(nodeTypeName); + ctx.isHP = isNodeTypeNameHighPerformance(nodeTypeName); + } else { + nodeTypeName = getNodeTypeNameByType(ctx.nodeType); + } ctx.config = new Config(ctx.preset, systemConfigs[ctx.preset]); @@ -86,7 +93,7 @@ function setupRegularPresetTaskFactory( ctx.config.set('core.rpc.password', generateRandomString(12)); // eslint-disable-next-line no-param-reassign - task.output = nodeTypeName; + task.output = ctx.nodeType ? ctx.nodeType : nodeTypeName; }, options: { persistentOutput: true, diff --git a/packages/dashmate/src/test/areServicesRunningFactory.js b/packages/dashmate/src/test/areServicesRunningFactory.js new file mode 100644 index 0000000000..f13174fb1b --- /dev/null +++ b/packages/dashmate/src/test/areServicesRunningFactory.js @@ -0,0 +1,42 @@ +const generateEnvs = require('../util/generateEnvs'); + +/** + * @param {ConfigFile} configFile + * @param {Config[]} configGroup + * @param {DockerCompose} dockerCompose + * @param {Object} services + * + * @returns {areServicesRunning} + */ +function areServicesRunningFactory(configFile, configGroup, dockerCompose, services) { + /** + * Check all node services are up and running + * + * @returns {Promise} + */ + async function areServicesRunning() { + let result = true; + + for (const config of configGroup) { + if (config.name === 'local_seed') { + result = result && (await dockerCompose.isServiceRunning( + generateEnvs(configFile, config), + 'core', + )); + } else { + for (const serviceName of Object.keys(services)) { + result = result && (await dockerCompose.isServiceRunning( + generateEnvs(configFile, config), + serviceName, + )); + } + } + } + + return result; + } + + return areServicesRunning; +} + +module.exports = areServicesRunningFactory; diff --git a/packages/dashmate/src/test/constants/insightLinks.js b/packages/dashmate/src/test/constants/insightLinks.js new file mode 100644 index 0000000000..d0d8a7e50f --- /dev/null +++ b/packages/dashmate/src/test/constants/insightLinks.js @@ -0,0 +1,8 @@ +const insightURLs = { + testnet: 'http://insight.testnet.networks.dash.org:3001/insight-api', + mainnet: 'https://insight.dash.org/insight-api', +}; + +module.exports = { + INSIGHT: insightURLs, +}; diff --git a/packages/dashmate/src/test/constants/services.js b/packages/dashmate/src/test/constants/services.js new file mode 100644 index 0000000000..df40fa295a --- /dev/null +++ b/packages/dashmate/src/test/constants/services.js @@ -0,0 +1,14 @@ +const services = { + dashmate_helper: 'Dashmate Helper', + dapi_envoy: 'DAPI Envoy', + dapi_api: 'DAPI API', + drive_tenderdash: 'Drive Tenderdash', + sentinel: 'Sentinel', + drive_abci: 'Drive ABCI', + dapi_tx_filter_stream: 'DAPI Transactions Filter Stream', + core: 'Core', +}; + +module.exports = { + SERVICES: services, +}; diff --git a/packages/dashmate/src/test/constants/statusOutput.js b/packages/dashmate/src/test/constants/statusOutput.js new file mode 100644 index 0000000000..bb301c3eb6 --- /dev/null +++ b/packages/dashmate/src/test/constants/statusOutput.js @@ -0,0 +1,11 @@ +const preSyncedStatus = { + testChain: 'test', + testnet: 'testnet', + sentinel_statusNotSynced: 'dashd not synced with network! Awaiting full sync before running Sentinel.', + masternode_status: 'Waiting for ProTx to appear on-chain', + platform_status: 'Waiting for core sync', +}; + +module.exports = { + STATUS: preSyncedStatus, +}; diff --git a/packages/dashmate/src/test/createSelfSignedCertificate.js b/packages/dashmate/src/test/createSelfSignedCertificate.js new file mode 100644 index 0000000000..26c90bdd47 --- /dev/null +++ b/packages/dashmate/src/test/createSelfSignedCertificate.js @@ -0,0 +1,21 @@ +const os = require('os'); +const path = require('path'); +const fs = require('fs'); +const generateKeyPair = require('../ssl/generateKeyPair'); +const generateCsr = require('../ssl/zerossl/generateCsr'); +const createCertificate = require('../ssl/selfSigned/createSelfSignedCertificate'); + +async function createSelfSignedCertificate(ip) { + const keyPair = await generateKeyPair(); + const csr = await generateCsr(keyPair, ip); + const certificate = await createCertificate(keyPair, csr); + + const tempDir = os.tmpdir(); + const certificatePath = path.join(tempDir, 'bundle.crt'); + const privKeyPath = path.join(tempDir, 'private.key'); + fs.writeFileSync(certificatePath, certificate, 'utf8'); + fs.writeFileSync(privKeyPath, keyPair.privateKey, 'utf8'); + return { certificatePath, privKeyPath }; +} + +module.exports = createSelfSignedCertificate; diff --git a/packages/dashmate/src/test/isServiceRunningFactory.js b/packages/dashmate/src/test/isServiceRunningFactory.js new file mode 100644 index 0000000000..e670954a1a --- /dev/null +++ b/packages/dashmate/src/test/isServiceRunningFactory.js @@ -0,0 +1,28 @@ +const generateEnvs = require('../util/generateEnvs'); + +/** + * @param {Config} config + * @param {ConfigFile} configFile + * @param {DockerCompose} dockerCompose + * + * @returns {isServicesRunning} + */ +function isServiceRunningFactory(config, configFile, dockerCompose) { + /** + * Check if service is running + * + * @param {string} serviceName + * + * @returns {Promise} + */ + async function isServicesRunning(serviceName) { + return dockerCompose.isServiceRunning( + generateEnvs(configFile, config), + serviceName, + ); + } + + return isServicesRunning; +} + +module.exports = isServiceRunningFactory; diff --git a/packages/dashmate/src/test/waitForCoreDataFactory.js b/packages/dashmate/src/test/waitForCoreDataFactory.js new file mode 100644 index 0000000000..a6ed75d97a --- /dev/null +++ b/packages/dashmate/src/test/waitForCoreDataFactory.js @@ -0,0 +1,30 @@ +const wait = require('../util/wait'); + +/** + * @param {CoreRpcClient} rpcClient + * @returns {waitForCoreData} + */ +function waitForCoreDataFactory(rpcClient) { + /** + * @param {number} originalValue + * @param {function(number, number)} predicateFn + * @returns {Promise} + */ + async function waitForCoreData(originalValue, predicateFn) { + let result = originalValue; + + while (!predicateFn(result, originalValue)) { + await wait(10000); // 10 seconds + + const blockchainInfo = await rpcClient.getBlockchainInfo(); + + result = blockchainInfo.result.headers; + } + + return result; + } + + return waitForCoreData; +} + +module.exports = waitForCoreDataFactory; diff --git a/packages/dashmate/test/bootstrap.js b/packages/dashmate/test/bootstrap.js index 1ec1f4eb6a..47a4677202 100644 --- a/packages/dashmate/test/bootstrap.js +++ b/packages/dashmate/test/bootstrap.js @@ -10,9 +10,6 @@ use(dirtyChai); process.env.NODE_ENV = 'test'; -use(dirtyChai); -use(sinonChai); - beforeEach(function beforeEach() { if (!this.sinon) { this.sinon = sinon.createSandbox(); diff --git a/packages/dashmate/test/e2e/localNetwork.js b/packages/dashmate/test/e2e/localNetwork.js new file mode 100644 index 0000000000..4855eb9207 --- /dev/null +++ b/packages/dashmate/test/e2e/localNetwork.js @@ -0,0 +1,141 @@ +const path = require('path'); +const os = require('os'); +const fs = require('fs'); + +process.env.DASHMATE_HOME_DIR = path.resolve(os.tmpdir(), '.dashmate'); + +const { asValue } = require('awilix'); + +const createDIContainer = require('../../src/createDIContainer'); +const areServicesRunningFactory = require('../../src/test/areServicesRunningFactory'); +const { SERVICES } = require('../../src/test/constants/services'); + +describe('Local Network', function main() { + this.timeout(60 * 60 * 1000); // 60 minutes + this.bail(true); // bail on first failure + + let container; + let setupLocalPresetTask; + let resetNodeTask; + let group; + let configFile; + let startGroupNodesTask; + let dockerCompose; + let areServicesRunning; + let stopNodeTask; + let restartNodeTask; + + const groupName = 'local'; + + before(async () => { + container = await createDIContainer(); + + const createSystemConfigs = container.resolve('createSystemConfigs'); + + configFile = createSystemConfigs(); + + container.register({ + configFile: asValue(configFile), + }); + + const defaultGroupName = configFile.getDefaultGroupName(); + + group = configFile.getGroupConfigs(defaultGroupName); + + container.register({ + configGroup: asValue(group), + }); + + const renderServiceTemplates = container.resolve('renderServiceTemplates'); + const writeServiceConfigs = container.resolve('writeServiceConfigs'); + + for (const config of group) { + const serviceConfigFiles = renderServiceTemplates(config); + writeServiceConfigs(config.getName(), serviceConfigFiles); + } + + setupLocalPresetTask = await container.resolve('setupLocalPresetTask'); + resetNodeTask = await container.resolve('resetNodeTask'); + startGroupNodesTask = await container.resolve('startGroupNodesTask'); + restartNodeTask = await container.resolve('restartNodeTask'); + stopNodeTask = await container.resolve('stopNodeTask'); + + dockerCompose = await container.resolve('dockerCompose'); + }); + + after(async () => { + if (fs.existsSync(process.env.DASHMATE_HOME_DIR)) { + for (const config of group) { + const resetTask = resetNodeTask(config); + + await resetTask.run({ + isHardReset: false, + isForce: false, + }); + + await configFile.removeConfig(config.getName()); + } + } + }); + + describe('setup', () => { + it('should setup local network', async () => { + const setupTask = setupLocalPresetTask(); + + await setupTask.run({ + nodeCount: 3, + debugLogs: true, + minerInterval: '2.5m', + isVerbose: true, + }); + + configFile = container.resolve('configFile'); + + const configExists = configFile.isGroupExists(groupName); + + group = configFile.getGroupConfigs(groupName); + + areServicesRunning = areServicesRunningFactory(configFile, group, dockerCompose, SERVICES); + + expect(configExists).to.be.true(); + }); + }); + + describe('start', () => { + it('should start local network', async () => { + const task = startGroupNodesTask(group); + + await task.run(); + + const result = await areServicesRunning(); + + expect(result).to.be.true(); + }); + }); + + describe('restart', () => { + it('should restart local network', async () => { + for (const config of group) { + const task = restartNodeTask(config); + await task.run(); + } + + const result = await areServicesRunning(); + + expect(result).to.be.true(); + }); + }); + + describe('stop', () => { + it('should stop local network', async () => { + for (const config of group.reverse()) { + const task = stopNodeTask(config); + await task.run(); + } + + const result = await areServicesRunning(); + + expect(result).to.be.false(); + }); + }); +}); diff --git a/packages/dashmate/test/e2e/testnetFullnode.spec.js b/packages/dashmate/test/e2e/testnetFullnode.spec.js new file mode 100644 index 0000000000..81a897c5d2 --- /dev/null +++ b/packages/dashmate/test/e2e/testnetFullnode.spec.js @@ -0,0 +1,185 @@ +const path = require('path'); +const os = require('os'); +const fs = require('fs'); +const publicIp = require('public-ip'); + +process.env.DASHMATE_HOME_DIR = path.resolve(os.tmpdir(), '.dashmate'); + +const { asValue } = require('awilix'); + +const createDIContainer = require('../../src/createDIContainer'); +const { NODE_TYPE_NAMES, getNodeTypeByName } = require('../../src/listr/tasks/setup/nodeTypes'); +const { SSL_PROVIDERS } = require('../../src/constants'); +const generateTenderdashNodeKey = require('../../src/tenderdash/generateTenderdashNodeKey'); +const createSelfSignedCertificate = require('../../src/test/createSelfSignedCertificate'); +const isServiceRunningFactory = require('../../src/test/isServiceRunningFactory'); +const createRpcClient = require('../../src/core/createRpcClient'); +const waitForCoreDataFactory = require('../../src/test/waitForCoreDataFactory'); + +describe('Testnet Fullnode', function main() { + this.timeout(60 * 60 * 1000); // 60 minutes + this.bail(true); // bail on first failure + + let container; + let setupRegularPresetTask; + let resetNodeTask; + let group; + let configFile; + let dockerCompose; + let stopNodeTask; + let restartNodeTask; + let startNodeTask; + let isServiceRunning; + let coreRpcClient; + let lastBlockHeight; + let renderServiceTemplates; + let writeServiceConfigs; + let configFileRepository; + let waitForCoreData; + + const preset = 'testnet'; + + before(async () => { + container = await createDIContainer(); + + const createSystemConfigs = container.resolve('createSystemConfigs'); + + configFile = createSystemConfigs(); + + container.register({ + configFile: asValue(configFile), + }); + + const defaultGroupName = configFile.getDefaultGroupName(); + + group = configFile.getGroupConfigs(defaultGroupName); + + container.register({ + configGroup: asValue(group), + }); + + renderServiceTemplates = container.resolve('renderServiceTemplates'); + writeServiceConfigs = container.resolve('writeServiceConfigs'); + + setupRegularPresetTask = container.resolve('setupRegularPresetTask'); + resetNodeTask = container.resolve('resetNodeTask'); + startNodeTask = container.resolve('startNodeTask'); + restartNodeTask = container.resolve('restartNodeTask'); + stopNodeTask = container.resolve('stopNodeTask'); + configFileRepository = container.resolve('configFileRepository'); + + dockerCompose = container.resolve('dockerCompose'); + + configFile = container.resolve('configFile'); + }); + + after(async () => { + if (fs.existsSync(process.env.DASHMATE_HOME_DIR)) { + const config = configFile.getConfig(preset); + + const resetTask = resetNodeTask(config); + + await resetTask.run({ + isHardReset: false, + isForce: false, + }); + + await configFile.removeConfig(config.getName()); + } + }); + + describe('setup', () => { + it('should setup fullnode', async () => { + const setupTask = setupRegularPresetTask(); + + const initialIp = await publicIp.v4(); + + const { certificatePath, privKeyPath } = await createSelfSignedCertificate(initialIp); + + await setupTask.run({ + preset, + nodeType: getNodeTypeByName(NODE_TYPE_NAMES.FULLNODE), + isHP: false, + certificateProvider: SSL_PROVIDERS.FILE, + tenderdashNodeKey: generateTenderdashNodeKey(), + initialIpForm: { + ip: initialIp, + coreP2PPort: 19999, + platformHTTPPort: 36656, + platformP2PPort: 1443, + }, + fileCertificateProviderForm: { + chainFilePath: certificatePath, + privateFilePath: privKeyPath, + }, + }); + + const config = configFile.getConfig(preset); + + const serviceConfigFiles = renderServiceTemplates(config); + writeServiceConfigs(config.getName(), serviceConfigFiles); + + await configFileRepository.write(configFile); + + isServiceRunning = isServiceRunningFactory( + config, + configFile, + dockerCompose, + ); + + coreRpcClient = createRpcClient({ + port: config.get('core.rpc.port'), + user: config.get('core.rpc.user'), + pass: config.get('core.rpc.password'), + }); + + waitForCoreData = waitForCoreDataFactory(coreRpcClient); + + expect(config).to.not.be.undefined(); + }); + }); + + describe('start', () => { + it('should start fullnode', async () => { + const startTask = startNodeTask(configFile.getConfig(preset)); + await startTask.run(); + + const isRunning = await isServiceRunning('core'); + + expect(isRunning).to.be.true(); + }); + }); + + describe('sync', () => { + it('should sync Dash Core', async () => { + lastBlockHeight = await waitForCoreData(0, (currentValue) => currentValue > 0); + }); + }); + + describe('restart', () => { + it('should restart fullnode and continue syncing Dash Core', async () => { + const task = restartNodeTask(configFile.getConfig(preset)); + await task.run(); + + const isRunning = await isServiceRunning('core'); + + expect(isRunning).to.be.true(); + + await waitForCoreData( + lastBlockHeight, + (currentValue, originalValue) => currentValue > originalValue, + ); + }); + }); + + describe('stop', () => { + it('should stop fullnode', async () => { + const task = stopNodeTask(configFile.getConfig(preset)); + await task.run(); + + const isRunning = await isServiceRunning('core'); + + expect(isRunning).to.be.false(); + }); + }); +}); diff --git a/packages/dashmate/test/e2e/testnetHPFullnode.spec.js b/packages/dashmate/test/e2e/testnetHPFullnode.spec.js new file mode 100644 index 0000000000..a85f203186 --- /dev/null +++ b/packages/dashmate/test/e2e/testnetHPFullnode.spec.js @@ -0,0 +1,185 @@ +const path = require('path'); +const os = require('os'); +const fs = require('fs'); +const publicIp = require('public-ip'); + +process.env.DASHMATE_HOME_DIR = path.resolve(os.tmpdir(), '.dashmate'); + +const { asValue } = require('awilix'); + +const createDIContainer = require('../../src/createDIContainer'); +const { NODE_TYPE_NAMES, getNodeTypeByName } = require('../../src/listr/tasks/setup/nodeTypes'); +const { SSL_PROVIDERS } = require('../../src/constants'); +const generateTenderdashNodeKey = require('../../src/tenderdash/generateTenderdashNodeKey'); +const createSelfSignedCertificate = require('../../src/test/createSelfSignedCertificate'); +const isServiceRunningFactory = require('../../src/test/isServiceRunningFactory'); +const createRpcClient = require('../../src/core/createRpcClient'); +const waitForCoreDataFactory = require('../../src/test/waitForCoreDataFactory'); + +describe('Testnet HP Fullnode', function main() { + this.timeout(60 * 60 * 1000); // 60 minutes + this.bail(true); // bail on first failure + + let container; + let setupRegularPresetTask; + let resetNodeTask; + let group; + let configFile; + let dockerCompose; + let stopNodeTask; + let restartNodeTask; + let startNodeTask; + let isServiceRunning; + let coreRpcClient; + let lastBlockHeight; + let renderServiceTemplates; + let writeServiceConfigs; + let configFileRepository; + let waitForCoreData; + + const preset = 'testnet'; + + before(async () => { + container = await createDIContainer(); + + const createSystemConfigs = container.resolve('createSystemConfigs'); + + configFile = createSystemConfigs(); + + container.register({ + configFile: asValue(configFile), + }); + + const defaultGroupName = configFile.getDefaultGroupName(); + + group = configFile.getGroupConfigs(defaultGroupName); + + container.register({ + configGroup: asValue(group), + }); + + renderServiceTemplates = container.resolve('renderServiceTemplates'); + writeServiceConfigs = container.resolve('writeServiceConfigs'); + + setupRegularPresetTask = container.resolve('setupRegularPresetTask'); + resetNodeTask = container.resolve('resetNodeTask'); + startNodeTask = container.resolve('startNodeTask'); + restartNodeTask = container.resolve('restartNodeTask'); + stopNodeTask = container.resolve('stopNodeTask'); + configFileRepository = container.resolve('configFileRepository'); + + dockerCompose = container.resolve('dockerCompose'); + + configFile = container.resolve('configFile'); + }); + + after(async () => { + if (fs.existsSync(process.env.DASHMATE_HOME_DIR)) { + const config = configFile.getConfig(preset); + + const resetTask = resetNodeTask(config); + + await resetTask.run({ + isHardReset: false, + isForce: false, + }); + + await configFile.removeConfig(config.getName()); + } + }); + + describe('setup', () => { + it('should setup fullnode', async () => { + const setupTask = setupRegularPresetTask(); + + const initialIp = await publicIp.v4(); + + const { certificatePath, privKeyPath } = await createSelfSignedCertificate(initialIp); + + await setupTask.run({ + preset, + nodeType: getNodeTypeByName(NODE_TYPE_NAMES.FULLNODE), + isHP: true, + certificateProvider: SSL_PROVIDERS.FILE, + tenderdashNodeKey: generateTenderdashNodeKey(), + initialIpForm: { + ip: initialIp, + coreP2PPort: 19999, + platformHTTPPort: 36656, + platformP2PPort: 1443, + }, + fileCertificateProviderForm: { + chainFilePath: certificatePath, + privateFilePath: privKeyPath, + }, + }); + + const config = configFile.getConfig(preset); + + const serviceConfigFiles = renderServiceTemplates(config); + writeServiceConfigs(config.getName(), serviceConfigFiles); + + await configFileRepository.write(configFile); + + isServiceRunning = isServiceRunningFactory( + config, + configFile, + dockerCompose, + ); + + coreRpcClient = createRpcClient({ + port: config.get('core.rpc.port'), + user: config.get('core.rpc.user'), + pass: config.get('core.rpc.password'), + }); + + waitForCoreData = waitForCoreDataFactory(coreRpcClient); + + expect(config).to.not.be.undefined(); + }); + }); + + describe('start', () => { + it('should start fullnode', async () => { + const startTask = startNodeTask(configFile.getConfig(preset)); + await startTask.run(); + + const isRunning = await isServiceRunning('core'); + + expect(isRunning).to.be.true(); + }); + }); + + describe('sync', () => { + it('should sync Dash Core', async () => { + lastBlockHeight = await waitForCoreData(0, (currentValue) => currentValue > 0); + }); + }); + + describe('restart', () => { + it('should restart fullnode and continue syncing Dash Core', async () => { + const task = restartNodeTask(configFile.getConfig(preset)); + await task.run(); + + const isRunning = await isServiceRunning('core'); + + expect(isRunning).to.be.true(); + + await waitForCoreData( + lastBlockHeight, + (currentValue, originalValue) => currentValue > originalValue, + ); + }); + }); + + describe('stop', () => { + it('should stop fullnode', async () => { + const task = stopNodeTask(configFile.getConfig(preset)); + await task.run(); + + const isRunning = await isServiceRunning('core'); + + expect(isRunning).to.be.false(); + }); + }); +}); From de04ed3d90cfa16027f7394df501537b91e1368a Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Wed, 28 Jun 2023 15:12:21 +0800 Subject: [PATCH 08/19] feat(dashmate): setup masternode with DMT (#1203) Co-authored-by: thephez Co-authored-by: strophy <32928115+strophy@users.noreply.github.com> --- .github/workflows/all-packages.yml | 4 +- .../src/listr/prompts/createIpAndPortsForm.js | 14 +- .../prompts/createPlatformNodeKeyInput.js | 7 +- .../registerMasternodeWithCoreWallet.js | 258 ++++++++++++++++++ .../registerMasternodeWithDMT.js | 80 ++++++ .../setup/regular/configureNodeTaskFactory.js | 2 +- .../registerMasternodeGuideTaskFactory.js | 252 ++--------------- packages/dashmate/test/e2e/localNetwork.js | 2 +- .../dashmate/test/e2e/testnetFullnode.spec.js | 2 +- .../test/e2e/testnetHPFullnode.spec.js | 2 +- 10 files changed, 382 insertions(+), 241 deletions(-) create mode 100644 packages/dashmate/src/listr/prompts/registerMasternode/registerMasternodeWithCoreWallet.js create mode 100644 packages/dashmate/src/listr/prompts/registerMasternode/registerMasternodeWithDMT.js diff --git a/.github/workflows/all-packages.yml b/.github/workflows/all-packages.yml index 0dfe349b2b..e2a1472495 100644 --- a/.github/workflows/all-packages.yml +++ b/.github/workflows/all-packages.yml @@ -59,8 +59,8 @@ jobs: run: corepack enable - name: Audit NPM - run: yarn npm audit --environment production --all --recursive --ignore 1091050 - # ignore "public ip" + run: yarn npm audit --environment production --all --recursive --ignore 1091050 --ignore 1092330 + # ignore "public ip", "word-wrap" test-suite: name: Run Platform Test Suite diff --git a/packages/dashmate/src/listr/prompts/createIpAndPortsForm.js b/packages/dashmate/src/listr/prompts/createIpAndPortsForm.js index 77837776a4..9ad60d443e 100644 --- a/packages/dashmate/src/listr/prompts/createIpAndPortsForm.js +++ b/packages/dashmate/src/listr/prompts/createIpAndPortsForm.js @@ -61,7 +61,7 @@ async function createIpAndPortsForm(network, options = {}) { } let initialIp; - if (options.initialIp !== '' || !options.initialIp) { + if (options.initialIp === null || options.initialIp === undefined) { initialIp = await Promise.race([ publicIp.v4().catch(() => ''), // Resolve in 10 seconds if public IP is not available @@ -70,7 +70,9 @@ async function createIpAndPortsForm(network, options = {}) { } let initialCoreP2PPort; - if (options.initialCoreP2PPort !== '' || !options.initialCoreP2PPort || network === PRESET_MAINNET) { + if (options.initialCoreP2PPort === undefined + || options.initialCoreP2PPort === null + || network === PRESET_MAINNET) { initialCoreP2PPort = systemConfigs[network].core.p2p.port.toString(); } @@ -93,7 +95,9 @@ async function createIpAndPortsForm(network, options = {}) { if (options.isHPMN) { let initialPlatformP2PPort; - if (options.initialPlatformP2PPort !== '' || !options.initialPlatformP2PPort || network === PRESET_MAINNET) { + if (options.initialPlatformP2PPort === null + || options.initialPlatformP2PPort === undefined + || network === PRESET_MAINNET) { initialPlatformP2PPort = systemConfigs[network].platform.drive.tenderdash.p2p.port.toString(); } @@ -106,7 +110,9 @@ async function createIpAndPortsForm(network, options = {}) { }); let initialPlatformHTTPPort; - if (options.initialPlatformHTTPPort !== '' || !options.initialPlatformHTTPPort || network === PRESET_MAINNET) { + if (options.initialPlatformHTTPPort === null + || options.initialPlatformHTTPPort === undefined + || network === PRESET_MAINNET) { initialPlatformHTTPPort = systemConfigs[network].platform.dapi.envoy.http.port.toString(); } diff --git a/packages/dashmate/src/listr/prompts/createPlatformNodeKeyInput.js b/packages/dashmate/src/listr/prompts/createPlatformNodeKeyInput.js index 3b0905bd2c..c8833a4bbb 100644 --- a/packages/dashmate/src/listr/prompts/createPlatformNodeKeyInput.js +++ b/packages/dashmate/src/listr/prompts/createPlatformNodeKeyInput.js @@ -7,6 +7,11 @@ const validateTenderdashNodeKey = require('./validators/validateTenderdashNodeKe * @returns {Object} */ function createPlatformNodeKeyInput(options = {}) { + let { initial } = options; + if (initial === null || initial === undefined) { + initial = generateTenderdashNodeKey(); + } + return { type: 'input', name: 'platformNodeKey', @@ -18,7 +23,7 @@ function createPlatformNodeKeyInput(options = {}) { automatically generated for you.\n`, message: 'Enter Ed25519 node key', hint: 'Base64 encoded', - initial: options.initial === '' || options.initial ? options.initial : generateTenderdashNodeKey(), + initial, validate: validateTenderdashNodeKey, }; } diff --git a/packages/dashmate/src/listr/prompts/registerMasternode/registerMasternodeWithCoreWallet.js b/packages/dashmate/src/listr/prompts/registerMasternode/registerMasternodeWithCoreWallet.js new file mode 100644 index 0000000000..993e636b48 --- /dev/null +++ b/packages/dashmate/src/listr/prompts/registerMasternode/registerMasternodeWithCoreWallet.js @@ -0,0 +1,258 @@ +const wrapAnsi = require('wrap-ansi'); +const chalk = require('chalk'); +const BlsSignatures = require('@dashevo/bls'); + +const generateBlsKeys = require('../../../core/generateBlsKeys'); +const validateAddress = require('../validators/validateAddress'); +const { + HPMN_COLLATERAL_AMOUNT, + MASTERNODE_COLLATERAL_AMOUNT, + PRESET_MAINNET, +} = require('../../../constants'); + +const validateTxHex = require('../validators/validateTxHex'); +const validatePositiveInteger = require('../validators/validatePositiveInteger'); +const validatePercentage = require('../validators/validatePercentage'); +const formatPercentage = require('../formatters/formatPercentage'); +const createPlatformNodeKeyInput = require('../createPlatformNodeKeyInput'); +const createIpAndPortsForm = require('../createIpAndPortsForm'); +const getBLSPublicKeyFromPrivateKeyHex = require('../../../core/getBLSPublicKeyFromPrivateKeyHex'); +const systemConfigs = require('../../../../configs/system'); +const deriveTenderdashNodeId = require('../../../tenderdash/deriveTenderdashNodeId'); +const validateBLSPrivateKeyFactory = require('../validators/validateBLSPrivateKeyFactory'); + +/** + * Print prompts to collect masternode registration data with Core + * + * @param {Context} ctx + * @param {TaskWrapper} task + * @returns {Promise<{ + * keys: {}, + * ipAndPorts: { + * platformP2PPort: null, + * coreP2PPort: null, + * platformHTTPPort: null + * }, + * collateral: {}, + * operator: { + * rewardShare: null, + * privateKey: null + * }, + * platformNodeKey: null + * }>} + */ +async function registerMasternodeWithCoreWallet(ctx, task) { + const blsSignatures = await BlsSignatures(); + const validateBLSPrivateKey = validateBLSPrivateKeyFactory(blsSignatures); + + const validateAddressWithNetwork = (value) => validateAddress(value, ctx.preset); + + const collateralAmount = ctx.isHP === true + ? HPMN_COLLATERAL_AMOUNT + : MASTERNODE_COLLATERAL_AMOUNT; + + const collateralDenomination = ctx.preset === PRESET_MAINNET ? 'DASH' : 'tDASH'; + + let state = { + collateral: {}, + keys: {}, + operator: { + privateKey: null, + rewardShare: null, + }, + ipAndPorts: { + coreP2PPort: null, + platformHTTPPort: null, + platformP2PPort: null, + }, + platformNodeKey: null, + }; + + let instructionsUrl = 'https://docs.dash.org/mn-setup-core-collateral'; + if (ctx.isHP) { + instructionsUrl = 'https://docs.dash.org/evonode-setup-core-collateral'; + } + + let confirmation; + do { + const { privateKey: initialOperatorPrivateKey } = await generateBlsKeys(); + + const prompts = [ + { + type: 'form', + name: 'collateral', + header: ` Dashmate needs to collect your collateral funding transaction hash and index. + The funding value must be exactly ${collateralAmount} ${collateralDenomination}. + + Please follow the instructions on how to create a collateral funding transaction in Dash Core Wallet: + ${instructionsUrl}\n`, + message: 'Enter collateral funding transaction information:', + choices: [ + { + name: 'txId', + message: 'Transaction hash', + validate: validateTxHex, + initial: state.collateral.txId, + }, + { + name: 'outputIndex', + message: 'Output index', + validate: validatePositiveInteger, + initial: state.collateral.outputIndex, + }, + ], + validate: ({ txId, outputIndex }) => validateTxHex(txId) + && validatePositiveInteger(outputIndex), + }, + { + type: 'form', + name: 'keys', + header: ` Dashmate needs to collect details about the owner, voting and payout addresses + to use in the masternode registration transaction. These are regular Dash + addresses, encoded in base58 format.\n`, + message: 'Enter masternode addresses:', + choices: [ + { + name: 'ownerAddress', + message: 'Owner address', + validate: validateAddressWithNetwork, + initial: state.keys.ownerAddress, + }, + { + name: 'votingAddress', + message: 'Voting address', + validate: validateAddressWithNetwork, + initial: state.keys.votingAddress, + }, + { + name: 'payoutAddress', + message: 'Payout address', + validate: validateAddressWithNetwork, + initial: state.keys.payoutAddress, + }, + ], + validate: ({ ownerAddress, votingAddress, payoutAddress }) => { + if (!validateAddressWithNetwork(ownerAddress) + || !validateAddressWithNetwork(votingAddress) + || !validateAddressWithNetwork(payoutAddress)) { + return false; + } + + if (ownerAddress === payoutAddress || votingAddress === payoutAddress) { + return 'The payout address may not be the same as the owner or voting address'; + } + + return true; + }, + }, + { + type: 'form', + name: 'operator', + header: ` Dashmate needs to collect details on the operator key and operator reward share + to use in the registration transaction. The operator key is a BLS private key, + encoded in hexadecimal format. Dashmate will record the private key in the masternode + configuration, and derive the public key for use in the masternode registration + transaction. You may optionally also specify a percentage share of the + masternode reward to pay to the operator.\n`, + message: 'Enter masternode operator private key and reward share:', + choices: [ + { + name: 'privateKey', + message: 'BLS private key', + initial: state.operator.privateKey || initialOperatorPrivateKey, + validate: validateBLSPrivateKey, + }, + { + name: 'rewardShare', + message: 'Reward share', + hint: '%', + initial: state.operator.rewardShare || '0.00', + validate: validatePercentage, + format: formatPercentage, + result: (value) => Number(value).toFixed(2), + }, + ], + validate: ({ privateKey, rewardShare }) => ( + validateBLSPrivateKey(privateKey) === true && validatePercentage(rewardShare)), + }, + ]; + + if (ctx.isHP) { + prompts.push(createPlatformNodeKeyInput({ + initial: state.platformNodeKey, + })); + } + + prompts.push(await createIpAndPortsForm(ctx.preset, { + isHPMN: ctx.isHP, + initialIp: state.ipAndPorts.ip, + initialCoreP2PPort: state.ipAndPorts.coreP2PPort, + initialPlatformP2PPort: state.ipAndPorts.platformP2PPort, + initialPlatformHTTPPort: state.ipAndPorts.platformHTTPPort, + })); + + state = await task.prompt(prompts); + + const operatorPublicKeyHex = await getBLSPublicKeyFromPrivateKeyHex( + state.operator.privateKey, + ); + + const platformP2PPort = state.ipAndPorts.platformP2PPort + || systemConfigs[ctx.preset].platform.drive.tenderdash.p2p.port; + + const platformHTTPPort = state.ipAndPorts.platformHTTPPort + || systemConfigs[ctx.preset].platform.dapi.envoy.http.port; + + let command; + if (ctx.isHP) { + command = `dash-cli protx register_hpmn \\ + ${state.collateral.txId} \\ + ${state.collateral.outputIndex} \\ + ${state.ipAndPorts.ip}:${state.ipAndPorts.coreP2PPort} \\ + ${state.keys.ownerAddress} \\ + ${operatorPublicKeyHex} \\ + ${state.keys.votingAddress} \\ + ${state.operator.rewardShare} \\ + ${state.keys.payoutAddress} \\ + ${deriveTenderdashNodeId(state.platformNodeKey)} \\ + ${platformP2PPort} \\ + ${platformHTTPPort}`; + } else { + command = `dash-cli protx register \\ + ${state.collateral.txId} \\ + ${state.collateral.outputIndex} \\ + ${state.ipAndPorts.ip}:${state.ipAndPorts.coreP2PPort} \\ + ${state.keys.ownerAddress} \\ + ${operatorPublicKeyHex} \\ + ${state.keys.votingAddress} \\ + ${state.operator.rewardShare} \\ + ${state.keys.payoutAddress}`; + } + + // Wrap the command to fit the terminal width (listr uses new lines to wrap the text) + if (!ctx.isVerbose) { + command = command.replace(/\\/g, ''); + command = wrapAnsi(command, process.stdout.columns - 3, { hard: true, trim: false }); + command = command.replace(/\n/g, '\\\n'); + } + + // TODO: We need to give more info on how to run this command + + confirmation = await task.prompt({ + type: 'toggle', + name: 'confirm', + header: chalk` Now run the following command to create the registration transaction: + + {bold.cyanBright ${command}} + + Select "No" to modify the command by amending your previous input.\n`, + message: 'Was the masternode registration transaction successful?', + enabled: 'Yes', + disabled: 'No', + }); + } while (!confirmation); + + return state; +} + +module.exports = registerMasternodeWithCoreWallet; diff --git a/packages/dashmate/src/listr/prompts/registerMasternode/registerMasternodeWithDMT.js b/packages/dashmate/src/listr/prompts/registerMasternode/registerMasternodeWithDMT.js new file mode 100644 index 0000000000..af53d955cf --- /dev/null +++ b/packages/dashmate/src/listr/prompts/registerMasternode/registerMasternodeWithDMT.js @@ -0,0 +1,80 @@ +const BlsSignatures = require('@dashevo/bls'); + +const createPlatformNodeKeyInput = require('../createPlatformNodeKeyInput'); +const createIpAndPortsForm = require('../createIpAndPortsForm'); +const validateBLSPrivateKeyFactory = require('../validators/validateBLSPrivateKeyFactory'); + +/** + * Print prompts to collect masternode registration data with DMT + * + * @param {Context} ctx + * @param {TaskWrapper} task + * @returns {Promise<{ + * ipAndPorts: { + * platformP2PPort: null, + * coreP2PPort: null, + * platformHTTPPort: null + * }, + * operator: { + * rewardShare: null, + * privateKey: null + * }, + * platformNodeKey: null + * }>} + */ +async function registerMasternodeWithDMT(ctx, task) { + const blsSignatures = await BlsSignatures(); + const validateBLSPrivateKey = validateBLSPrivateKeyFactory(blsSignatures); + + const prompts = [ + { + type: 'confirm', + header: ` Complete initial DMT setup and return here to continue: + + See https://docs.dash.org/dmt-setup for instructions on using Dash Masternode Tool + to store your collateral and register your masternode.\n`, + message: 'Press any key to continue dashmate setup process...', + default: ' ', + separator: () => '', + format: () => '', + initial: true, + isTrue: () => true, + }, + { + type: 'input', + name: 'operatorPrivateKey', + header: ` Dashmate needs to collect details on the operator key. The operator + key is a BLS private key, encoded in hexadecimal format. Dashmate will record the + private key in the masternode configuration.\n`, + message: 'Enter masternode operator private key:', + validate: validateBLSPrivateKey, + }, + ]; + + if (ctx.isHP) { + prompts.push(createPlatformNodeKeyInput({ + initial: '', + })); + } + + prompts.push(await createIpAndPortsForm(ctx.preset, { + isHPMN: ctx.isHP, + initialIp: '', + initialCoreP2PPort: '', + initialPlatformP2PPort: '', + initialPlatformHTTPPort: '', + })); + + const state = await task.prompt(prompts); + + // Keep compatibility with other registration methods + state.operator = { + privateKey: state.operatorPrivateKey, + }; + + delete state.operatorPrivateKey; + + return state; +} + +module.exports = registerMasternodeWithDMT; diff --git a/packages/dashmate/src/listr/tasks/setup/regular/configureNodeTaskFactory.js b/packages/dashmate/src/listr/tasks/setup/regular/configureNodeTaskFactory.js index 60900750d5..690bb9e144 100644 --- a/packages/dashmate/src/listr/tasks/setup/regular/configureNodeTaskFactory.js +++ b/packages/dashmate/src/listr/tasks/setup/regular/configureNodeTaskFactory.js @@ -52,7 +52,7 @@ function configureNodeTaskFactory() { let platformNodeKey = ctx.tenderdashNodeKey; if (!ctx.tenderdashNodeKey) { platformNodeKey = await task.prompt(createPlatformNodeKeyInput({ - skipInitial: ctx.nodeType === NODE_TYPE_MASTERNODE, + initial: ctx.nodeType === NODE_TYPE_MASTERNODE ? '' : undefined, })); } diff --git a/packages/dashmate/src/listr/tasks/setup/regular/registerMasternodeGuideTaskFactory.js b/packages/dashmate/src/listr/tasks/setup/regular/registerMasternodeGuideTaskFactory.js index e8bd12c558..bcc449c37b 100644 --- a/packages/dashmate/src/listr/tasks/setup/regular/registerMasternodeGuideTaskFactory.js +++ b/packages/dashmate/src/listr/tasks/setup/regular/registerMasternodeGuideTaskFactory.js @@ -1,30 +1,9 @@ const { Listr } = require('listr2'); -const wrapAnsi = require('wrap-ansi'); -const chalk = require('chalk'); - -const BlsSignatures = require('@dashevo/bls'); - -const { - MASTERNODE_COLLATERAL_AMOUNT, - HPMN_COLLATERAL_AMOUNT, - PRESET_MAINNET, -} = require('../../../../constants'); - -const systemConfigs = require('../../../../../configs/system'); - -const validateAddress = require('../../../prompts/validators/validateAddress'); -const validateTxHex = require('../../../prompts/validators/validateTxHex'); -const validatePositiveInteger = require('../../../prompts/validators/validatePositiveInteger'); -const validatePercentage = require('../../../prompts/validators/validatePercentage'); -const formatPercentage = require('../../../prompts/formatters/formatPercentage'); -const generateBlsKeys = require('../../../../core/generateBlsKeys'); -const validateBLSPrivateKeyFactory = require('../../../prompts/validators/validateBLSPrivateKeyFactory'); -const createPlatformNodeKeyInput = require('../../../prompts/createPlatformNodeKeyInput'); -const createIpAndPortsForm = require('../../../prompts/createIpAndPortsForm'); const deriveTenderdashNodeId = require('../../../../tenderdash/deriveTenderdashNodeId'); const getConfigurationOutputFromContext = require('./getConfigurationOutputFromContext'); -const getBLSPublicKeyFromPrivateKeyHex = require('../../../../core/getBLSPublicKeyFromPrivateKeyHex'); +const registerMasternodeWithCoreWallet = require('../../../prompts/registerMasternode/registerMasternodeWithCoreWallet'); +const registerMasternodeWithDMT = require('../../../prompts/registerMasternode/registerMasternodeWithDMT'); /** * @return {registerMasternodeGuideTask} @@ -35,15 +14,13 @@ function registerMasternodeGuideTaskFactory() { * @return {Listr} */ async function registerMasternodeGuideTask() { - const blsSignatures = await BlsSignatures(); - - const validateBLSPrivateKey = validateBLSPrivateKeyFactory(blsSignatures); - const REGISTRARS = { CORE: 'dashCore', - ANDROID: 'dashAndroid', - IOS: 'dashIOS', - OTHER: 'other', + // TODO: Disabled until additional functionality like signing protx and so on is + // implemented there + // ANDROID: 'dashAndroid', + // IOS: 'dashIOS', + DMT: 'dmt', }; return new Listr([ @@ -58,215 +35,30 @@ function registerMasternodeGuideTaskFactory() { directly. Instead, we will generate RPC commands that you can use in Dash Core or other external tools where keys are handled securely. During this process, dashmate can optionally generate configuration elements as necessary, such as - the BLS operator key and the node id.\n`, + the BLS operator key and the node id. + + Dash Masternode Tool (DMT) - Recommended for mainnet masternodes + so the collateral can be stored + on a hardware wallet for maximum security. + + Dash Core Wallet - Recommended for testnet and devnet masternodes + where more flexibility is required.\n`, message: 'Which wallet will you use to store keys for your masternode?', choices: [ + { name: REGISTRARS.DMT, message: 'Dash Masternode Tool' }, { name: REGISTRARS.CORE, message: 'Dash Core Wallet' }, - { name: REGISTRARS.ANDROID, message: 'Android Dash Wallet' }, - { name: REGISTRARS.IOS, message: 'iOS Dash Wallet' }, - { name: REGISTRARS.OTHER, message: 'Other' }, ], - initial: REGISTRARS.CORE, + initial: REGISTRARS.DMT, }, ]); - let initialOperatorPrivateKey; - if (registrar === REGISTRARS.CORE || registrar === REGISTRARS.OTHER) { - ({ privateKey: initialOperatorPrivateKey } = await generateBlsKeys()); + let state; + if (registrar === REGISTRARS.CORE) { + state = await registerMasternodeWithCoreWallet(ctx, task); + } else if (registrar === REGISTRARS.DMT) { + state = await registerMasternodeWithDMT(ctx, task); } - // TODO: We need to add description on how to find key generation form in the - // specified wallet - - const validateAddressWithNetwork = (value) => validateAddress(value, ctx.preset); - - const collateralAmount = ctx.isHP === true - ? HPMN_COLLATERAL_AMOUNT - : MASTERNODE_COLLATERAL_AMOUNT; - - const collateralDenomination = ctx.preset === PRESET_MAINNET ? 'DASH' : 'tDASH'; - - let state = { - collateral: {}, - keys: {}, - operator: {}, - ipAndPorts: {}, - }; - - let confirmation; - do { - const prompts = [ - { - type: 'form', - name: 'collateral', - header: ` Dashmate needs to collect your collateral funding transaction hash and index. - The funding value must be exactly ${collateralAmount} ${collateralDenomination}.\n`, - message: 'Enter collateral funding transaction information:', - choices: [ - { - name: 'txId', - message: 'Transaction hash', - validate: validateTxHex, - initial: state.collateral.txId, - }, - { - name: 'outputIndex', - message: 'Output index', - validate: validatePositiveInteger, - initial: state.collateral.outputIndex, - }, - ], - validate: ({ txId, outputIndex }) => validateTxHex(txId) - && validatePositiveInteger(outputIndex), - }, - { - type: 'form', - name: 'keys', - header: ` Dashmate needs to collect details about the owner, voting and payout addresses - to use in the masternode registration transaction. These are regular Dash - addresses, encoded in base58 format.\n`, - message: 'Enter masternode addresses:', - choices: [ - { - name: 'ownerAddress', - message: 'Owner address', - validate: validateAddressWithNetwork, - initial: state.keys.ownerAddress, - }, - { - name: 'votingAddress', - message: 'Voting address', - validate: validateAddressWithNetwork, - initial: state.keys.votingAddress, - }, - { - name: 'payoutAddress', - message: 'Payout address', - validate: validateAddressWithNetwork, - initial: state.keys.payoutAddress, - }, - ], - validate: ({ ownerAddress, votingAddress, payoutAddress }) => { - if (!validateAddressWithNetwork(ownerAddress) - || !validateAddressWithNetwork(votingAddress) - || !validateAddressWithNetwork(payoutAddress)) { - return false; - } - - if (ownerAddress === payoutAddress || votingAddress === payoutAddress) { - return 'The payout address may not be the same as the owner or voting address'; - } - - return true; - }, - }, - { - type: 'form', - name: 'operator', - header: ` Dashmate needs to collect details on the operator key and operator reward share - to use in the registration transaction. The operator key is a BLS private key, - encoded in HEX format. Dashmate will record the private key in the masternode - configuration, and derive the public key for use in the masternode registration - transaction. You may optionally also specify a percentage share of the - masternode reward to pay to the operator.\n`, - message: 'Enter masternode operator private key and reward share:', - choices: [ - { - name: 'privateKey', - message: 'BLS private key', - initial: state.operator.privateKey || initialOperatorPrivateKey, - validate: validateBLSPrivateKey, - }, - { - name: 'rewardShare', - message: 'Reward share', - hint: '%', - initial: state.operator.rewardShare || '0.00', - validate: validatePercentage, - format: formatPercentage, - result: (value) => Number(value).toFixed(2), - }, - ], - validate: ({ privateKey, rewardShare }) => ( - validateBLSPrivateKey(privateKey) === true && validatePercentage(rewardShare)), - }, - ]; - - if (ctx.isHP) { - prompts.push(createPlatformNodeKeyInput({ - initial: state.platformNodeKey, - })); - } - - prompts.push(await createIpAndPortsForm(ctx.preset, { - isHPMN: ctx.isHP, - initialIp: state.ipAndPorts.ip, - initialCoreP2PPort: state.ipAndPorts.coreP2PPort, - initialPlatformP2PPort: state.ipAndPorts.platformP2PPort, - initialPlatformHTTPPort: state.ipAndPorts.platformHTTPPort, - })); - - state = await task.prompt(prompts); - - const operatorPublicKeyHex = await getBLSPublicKeyFromPrivateKeyHex( - state.operator.privateKey, - ); - - const platformP2PPort = state.ipAndPorts.platformP2PPort - || systemConfigs[ctx.preset].platform.drive.tenderdash.p2p.port; - - const platformHTTPPort = state.ipAndPorts.platformHTTPPort - || systemConfigs[ctx.preset].platform.dapi.envoy.http.port; - - let command; - if (ctx.isHP) { - command = `dash-cli protx register_hpmn \\ - ${state.collateral.txId} \\ - ${state.collateral.outputIndex} \\ - ${state.ipAndPorts.ip}:${state.ipAndPorts.coreP2PPort} \\ - ${state.keys.ownerAddress} \\ - ${operatorPublicKeyHex} \\ - ${state.keys.votingAddress} \\ - ${state.operator.rewardShare} \\ - ${state.keys.payoutAddress} \\ - ${deriveTenderdashNodeId(state.platformNodeKey)} \\ - ${platformP2PPort} \\ - ${platformHTTPPort}`; - } else { - command = `dash-cli protx register \\ - ${state.collateral.txId} \\ - ${state.collateral.outputIndex} \\ - ${state.ipAndPorts.ip}:${state.ipAndPorts.coreP2PPort} \\ - ${state.keys.ownerAddress} \\ - ${operatorPublicKeyHex} \\ - ${state.keys.votingAddress} \\ - ${state.operator.rewardShare} \\ - ${state.keys.payoutAddress}`; - } - - // Wrap the command to fit the terminal width (listr uses new lines to wrap the text) - if (!ctx.isVerbose) { - command = command.replace(/\\/g, ''); - command = wrapAnsi(command, process.stdout.columns - 3, { hard: true, trim: false }); - command = command.replace(/\n/g, '\\\n'); - } - - // TODO: We need to give more info on how to run this command - - confirmation = await task.prompt({ - type: 'toggle', - name: 'confirm', - header: chalk` Now run the following command to create the registration transaction: - - {bold.cyanBright ${command}} - - Select "No" to modify the command by amending your previous input.\n`, - message: 'Was the masternode registration transaction successful?', - enabled: 'Yes', - disabled: 'No', - }); - } while (!confirmation); - ctx.config.set('core.masternode.operator.privateKey', state.operator.privateKey); ctx.config.set('externalIp', state.ipAndPorts.ip); diff --git a/packages/dashmate/test/e2e/localNetwork.js b/packages/dashmate/test/e2e/localNetwork.js index 4855eb9207..69cafaf5c0 100644 --- a/packages/dashmate/test/e2e/localNetwork.js +++ b/packages/dashmate/test/e2e/localNetwork.js @@ -10,7 +10,7 @@ const createDIContainer = require('../../src/createDIContainer'); const areServicesRunningFactory = require('../../src/test/areServicesRunningFactory'); const { SERVICES } = require('../../src/test/constants/services'); -describe('Local Network', function main() { +describe.skip('Local Network', function main() { this.timeout(60 * 60 * 1000); // 60 minutes this.bail(true); // bail on first failure diff --git a/packages/dashmate/test/e2e/testnetFullnode.spec.js b/packages/dashmate/test/e2e/testnetFullnode.spec.js index 81a897c5d2..966d947bc5 100644 --- a/packages/dashmate/test/e2e/testnetFullnode.spec.js +++ b/packages/dashmate/test/e2e/testnetFullnode.spec.js @@ -16,7 +16,7 @@ const isServiceRunningFactory = require('../../src/test/isServiceRunningFactory' const createRpcClient = require('../../src/core/createRpcClient'); const waitForCoreDataFactory = require('../../src/test/waitForCoreDataFactory'); -describe('Testnet Fullnode', function main() { +describe.skip('Testnet Fullnode', function main() { this.timeout(60 * 60 * 1000); // 60 minutes this.bail(true); // bail on first failure diff --git a/packages/dashmate/test/e2e/testnetHPFullnode.spec.js b/packages/dashmate/test/e2e/testnetHPFullnode.spec.js index a85f203186..b01c19fc3c 100644 --- a/packages/dashmate/test/e2e/testnetHPFullnode.spec.js +++ b/packages/dashmate/test/e2e/testnetHPFullnode.spec.js @@ -16,7 +16,7 @@ const isServiceRunningFactory = require('../../src/test/isServiceRunningFactory' const createRpcClient = require('../../src/core/createRpcClient'); const waitForCoreDataFactory = require('../../src/test/waitForCoreDataFactory'); -describe('Testnet HP Fullnode', function main() { +describe.skip('Testnet HP Fullnode', function main() { this.timeout(60 * 60 * 1000); // 60 minutes this.bail(true); // bail on first failure From 096665178dbf1a9063faf53675a99f979a2b0722 Mon Sep 17 00:00:00 2001 From: pshenmic Date: Thu, 29 Jun 2023 13:30:25 +0700 Subject: [PATCH 09/19] fix(dashmate): invalid migration (#1209) Co-authored-by: Ivan Shumkov --- packages/dashmate/configs/migrations.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/dashmate/configs/migrations.js b/packages/dashmate/configs/migrations.js index eaba47b35d..bdd53a6999 100644 --- a/packages/dashmate/configs/migrations.js +++ b/packages/dashmate/configs/migrations.js @@ -578,17 +578,18 @@ module.exports = { let i = 0; Object.entries(configFile.configs) .forEach(([, config]) => { - // Update ports - config.platform.dashmate.helper.api.port = systemConfigs.base.platform - .dashmate.helper.api.port; + // Update dashmate helper port + config.dashmate.helper.api.port = systemConfigs.base.dashmate.helper.api.port; + // Add pprof config + config.platform.drive.tenderdash.pprof = systemConfigs.base.platform + .drive.tenderdash.pprof; + + // Set different ports for local netwrok if exists if (config.group === 'local') { - config.set('platform.drive.tenderdash.pprof.port', systemConfigs.base.platform - .drive.tenderdash.pprof + (i * 100)); + config.platform.drive.tenderdash.pprof.port += i * 100; + i++; - } else { - config.platform.drive.tenderdash.pprof = systemConfigs.base.platform - .drive.tenderdash.pprof; } }); return configFile; From d747179ff7ece3e937d9ab1c1ba2fc7872d4e672 Mon Sep 17 00:00:00 2001 From: pshenmic Date: Tue, 4 Jul 2023 00:23:04 +0700 Subject: [PATCH 10/19] feat(dashmate): report pulled images during update (#1186) --- .pnp.cjs | 1 + packages/dashmate/README.md | 14 +++ packages/dashmate/package.json | 1 + .../dashmate/src/commands/status/services.js | 4 +- packages/dashmate/src/commands/update.js | 62 ++++++------- packages/dashmate/src/constants.js | 2 + packages/dashmate/src/createDIContainer.js | 11 +++ packages/dashmate/src/docker/DockerCompose.js | 92 ++++++++++++++----- .../src/docker/getServiceListFactory.js | 62 +++++++++++++ .../src/listr/tasks/reindexNodeTaskFactory.js | 2 +- .../src/listr/tasks/resetNodeTaskFactory.js | 5 +- .../src/listr/tasks/startNodeTaskFactory.js | 3 +- .../src/listr/tasks/stopNodeTaskFactory.js | 2 +- .../dashmate/src/status/enums/dockerStatus.js | 4 +- packages/dashmate/src/status/scopes/core.js | 3 +- .../dashmate/src/status/scopes/platform.js | 21 +++-- .../dashmate/src/status/scopes/services.js | 37 ++------ .../dashmate/src/update/updateNodeFactory.js | 57 ++++++++++++ .../test/unit/status/scopes/core.spec.js | 6 +- .../test/unit/status/scopes/platform.spec.js | 26 +++--- .../test/unit/status/scopes/services.spec.js | 7 +- yarn.lock | 3 +- 22 files changed, 303 insertions(+), 122 deletions(-) create mode 100644 packages/dashmate/src/docker/getServiceListFactory.js create mode 100644 packages/dashmate/src/update/updateNodeFactory.js diff --git a/.pnp.cjs b/.pnp.cjs index fb425e79fa..aefcd778c8 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -8230,6 +8230,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["hasbin", "npm:1.2.3"],\ ["is-wsl", "npm:2.2.0"],\ ["jayson", "npm:3.6.5"],\ + ["js-yaml", "npm:4.1.0"],\ ["listr2", "virtual:880cda903c2a2be387819a3f857d21494004437a03c92969b9853f7bdeebdfed08d417e68364ee9e158338603a6d78d690c457a55ab11e56398bc10f0ad232fc#npm:5.0.7"],\ ["lodash", "npm:4.17.21"],\ ["memory-streams", "npm:0.1.3"],\ diff --git a/packages/dashmate/README.md b/packages/dashmate/README.md index 739eb11095..a4ba3e874c 100644 --- a/packages/dashmate/README.md +++ b/packages/dashmate/README.md @@ -53,6 +53,8 @@ USAGE FLAGS -v, --verbose use verbose mode for output --config= configuration name to use + --format=