Skip to content

Dpp 0.25 (WIP) #47

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
buildscript {
ext.kotlin_version = '1.4.32'
ext.dashj_version = '19.1-CJ-SNAPSHOT'
ext.dpp_version = '0.24-SNAPSHOT'
ext.dapi_client_version = '0.24-SNAPSHOT'
ext.dpp_version = '0.25-SNAPSHOT'
ext.dapi_client_version = '0.25-SNAPSHOT'
repositories {
mavenLocal()
mavenCentral()
Expand Down Expand Up @@ -75,6 +75,7 @@ dependencies {
implementation "org.dashj:dashj-core:$dashj_version"
implementation "org.dashj:dashj-bls:1.0.0"
implementation "org.dashj:dashj-merk:0.22-SNAPSHOT"
implementation 'org.dashj:manual:0.25-SNAPSHOT'
implementation 'com.squareup.retrofit2:retrofit:2.6.4'
implementation 'com.squareup.retrofit2:converter-gson:2.6.4'
implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0'
Expand All @@ -95,6 +96,9 @@ dependencies {
exclude module: "protobuf-lite"
}
implementation 'io.grpc:grpc-stub:1.54.0' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-netty-shaded:1.54.0' // replace with the latest version
implementation 'io.netty:netty-tcnative-boringssl-static:2.0.46.Final' // replace with the latest version

compileOnly 'javax.annotation:javax.annotation-api:1.3.2'
implementation 'org.slf4j:slf4j-api:1.7.30'
implementation 'org.json:json:20190722'
Expand Down
Binary file added src/main/jniLibs/libdashj_dpp_bindings.dylib
Binary file not shown.
13 changes: 9 additions & 4 deletions src/main/kotlin/org/dashj/platform/dapiclient/DapiClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import org.bitcoinj.core.BloomFilter
import org.bitcoinj.core.Sha256Hash
import org.bitcoinj.core.Utils
import org.bitcoinj.evolution.SimplifiedMasternodeListManager
import org.bitcoinj.params.DevNetParams
import org.bitcoinj.quorums.LLMQParameters
import org.dash.platform.dapi.v0.CoreOuterClass
import org.dash.platform.dapi.v0.PlatformOuterClass
Expand Down Expand Up @@ -375,8 +376,7 @@ class DapiClient(
when {
waitForResult == null -> {
logger.info("broadcastStateTransitionAndWait: failure: Timeout or no proof returned")
// TODO: uncomment the next line when proofs are enabled
// throw StateTransitionBroadcastException(2, "Timeout", ByteArray(0))
throw StateTransitionBroadcastException(2, "Timeout", ByteArray(0))

// TODO: remove this line when proofs are enabled
logger.info("broadcastStateTransitionAndWait: success ($successRate)")
Expand Down Expand Up @@ -479,6 +479,9 @@ class DapiClient(
throw NotFoundException("Identity $identityId does not exist in the proof")
}
}
response.identity.isEmpty -> {
return throw NotFoundException("Identity $identityId does not exist")
}
else -> {
return GetIdentityResponse(response)
}
Expand Down Expand Up @@ -595,7 +598,7 @@ class DapiClient(
val method = GetContractMethod(contractIdByteArray, prove)
val response = grpcRequest(method, retryCallback = retryCallback) as PlatformOuterClass.GetDataContractResponse?
return when {
response == null -> {
response == null || response.dataContract.isEmpty -> {
throw NotFoundException("DataContract ${Identifier.from(contractId)} does not exist")
}
prove && response.hasProof() -> {
Expand Down Expand Up @@ -935,7 +938,8 @@ class DapiClient(
retriesLeft // if called recursively
}
val address = dapiAddress ?: dapiAddressListProvider.getLiveAddress()
val grpcMasternode = DAPIGrpcMasternode(address, timeOut)
val allowSelfSignedCertificate = dpp.params is DevNetParams
val grpcMasternode = DAPIGrpcMasternode(address, timeOut, allowSelfSignedCertificate)
lastUsedAddress = address

logger.info(
Expand Down Expand Up @@ -1046,6 +1050,7 @@ class DapiClient(
e.status.code != Status.INTERNAL.code &&
e.status.code != Status.CANCELLED.code &&
e.status.code != Status.UNKNOWN.code &&
e.status.code != Status.ALREADY_EXISTS.code && // ST was already submitted
e.status.code != Status.UNIMPLEMENTED.code // perhaps we contacted an old node
) {
throw e
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ open class BroadcastRetryCallback(
when (e.status.code) {
Status.UNAUTHENTICATED.code -> return false
Status.FAILED_PRECONDITION.code -> return false
Status.ALREADY_EXISTS.code -> return false
}
if (grpcMethod is BroadcastStateTransitionMethod) {
if (e.status.code == Status.INVALID_ARGUMENT.code) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class DocumentQuery private constructor(
}

data class Builder(
private var where: MutableList<List<Any>>? = null,
private var where: MutableList<List<Any>>? = mutableListOf(),
private var orderBy: MutableList<List<String>>? = null,
private var limit: Int = -1,
private var startAt: Identifier? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ package org.dashj.platform.dapiclient.provider
import com.google.common.base.Stopwatch
import io.grpc.ManagedChannel
import io.grpc.ManagedChannelBuilder
import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts
import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder
import io.grpc.netty.shaded.io.netty.handler.ssl.util.InsecureTrustManagerFactory
import org.dash.platform.dapi.v0.CoreGrpc
import org.dash.platform.dapi.v0.PlatformGrpc
import org.slf4j.LoggerFactory
import java.util.concurrent.TimeUnit

class DAPIGrpcMasternode(address: DAPIAddress, val timeout: Long) : DAPIMasternode(address) {
class DAPIGrpcMasternode(address: DAPIAddress, val timeout: Long, val allowSelfSignedCertificate: Boolean) : DAPIMasternode(address) {
// gRPC properties
private lateinit var channel: ManagedChannel
val platform: PlatformGrpc.PlatformBlockingStub by lazy {
Expand All @@ -41,9 +44,19 @@ class DAPIGrpcMasternode(address: DAPIAddress, val timeout: Long) : DAPIMasterno

init {
val watch = Stopwatch.createStarted()
channel = ManagedChannelBuilder.forAddress(address.host, address.grpcPort)
.useTransportSecurity()
.build()
if (!allowSelfSignedCertificate) {
channel = ManagedChannelBuilder.forAddress(address.host, address.grpcPort)
.useTransportSecurity()
.build()
} else {
channel = NettyChannelBuilder.forAddress(address.host, address.grpcPort)
.sslContext(
GrpcSslContexts.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE) // a trust manager that trusts all certificates
.build()
)
.build()
}

logger.debug("Connecting to GRPC host: ${address.host}:${address.grpcPort} (time: $watch)")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
*/
package org.dashj.platform.dapiclient

import org.bitcoinj.params.AbsintheDevNetParams
import org.bitcoinj.params.TestNet3Params
import org.dashj.platform.dpp.DashPlatformProtocol
import org.junit.jupiter.api.Test

class DapiClientTest : BaseTest() {

val PARAMS = TestNet3Params.get()
val PARAMS = AbsintheDevNetParams.get()
val stateRepository = StateRepositoryMock()
val dpp = DashPlatformProtocol(stateRepository, PARAMS)
val client = DapiClient(PARAMS.defaultHPMasternodeList.toList(), dpp)
Expand Down
43 changes: 33 additions & 10 deletions src/test/kotlin/org/dashj/platform/dapiclient/DapiGrpcClientTest.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.dashj.platform.dapiclient

import com.google.common.base.Converter
import com.google.common.base.Stopwatch
import com.hashengineering.crypto.X11
import io.grpc.Status
Expand All @@ -10,28 +11,31 @@ import org.bitcoinj.core.Context
import org.bitcoinj.core.ECKey
import org.bitcoinj.core.Sha256Hash
import org.bitcoinj.core.Utils
import org.bitcoinj.params.AbsintheDevNetParams
import org.bitcoinj.params.DevNetParams
import org.bitcoinj.params.TestNet3Params
import org.dashj.dpp.DPP
import org.dashj.platform.dapiclient.errors.NotFoundException
import org.dashj.platform.dapiclient.model.DocumentQuery
import org.dashj.platform.dapiclient.provider.DAPIAddress
import org.dashj.platform.dapiclient.provider.ListDAPIAddressProvider
import org.dashj.platform.dpp.DashPlatformProtocol
import org.dashj.platform.dpp.document.Document
import org.dashj.platform.dpp.identifier.Identifier
import org.dashj.platform.dpp.identity.IdentityCreateTransition
import org.dashj.platform.dpp.identity.IdentityFactory
import org.dashj.platform.dpp.toHex
import org.dashj.platform.dpp.util.Cbor
import org.dashj.platform.dpp.util.Converters
import org.json.JSONObject
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.Assertions.fail
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import java.io.File

class DapiGrpcClientTest : BaseTest() {

val PARAMS = TestNet3Params.get()
val PARAMS = AbsintheDevNetParams.get()
val CONTEXT = Context.getOrCreate(PARAMS)
val masternodeList = PARAMS.defaultHPMasternodeList.toList()
val dpnsContractId = SystemIds.dpnsDataContractId // DPNS contract
Expand Down Expand Up @@ -155,7 +159,7 @@ class DapiGrpcClientTest : BaseTest() {
.orderBy("normalizedLabel", true)
.build()
val documentsResponse = client.getDocuments(dpnsContractId.toBuffer(), "domain", query)

assertTrue(documentsResponse.documents.isNotEmpty())
val jsonDpnsFile = File("src/test/resources/dpns-contract.json").readText()
val jsonDpns = JSONObject(jsonDpnsFile)
val rawContract = jsonDpns.toMap()
Expand Down Expand Up @@ -209,6 +213,15 @@ class DapiGrpcClientTest : BaseTest() {
}
}

@Test
fun getIdentityTest() {
val dppA = DPP
val id = "7633TgdebkBWnBQ7peF56mxLaGSTBxuzCavHYbN6ZW8V";
val result = client.getIdentity(Identifier.from(id).toBuffer())
assertEquals(125, result.identity.size)
print(IdentityFactory(dpp, stateRepository).createFromBuffer(result.identity).toJSON())
}

@Test
fun getIdentityFromBadPubKeyBytes() {
val key = ECKey()
Expand Down Expand Up @@ -259,8 +272,8 @@ class DapiGrpcClientTest : BaseTest() {
"profile",
DocumentQuery.builder()
.where("\$ownerId", "==", Identifier.from("3HSUPuMgR5qpZt1y5NbE2BBheM11yLRXKZoqdsKgxVNt"))
.where("\$updatedAt", ">", 0)
.orderBy("\$updatedAt", true)
//.where("\$updatedAt", ">", 0)
//.orderBy("\$updatedAt", true)
.build()
)

Expand Down Expand Up @@ -319,8 +332,8 @@ class DapiGrpcClientTest : BaseTest() {
"profile",
DocumentQuery.builder()
.where("\$ownerId", "in", Identifier.from("3HSUPuMgR5qpZt1y5NbE2BBheM11yLRXKZoqdsKgxVNt"))
.where("\$updatedAt", ">", 0)
.orderBy("\$updatedAt")
//.where("\$updatedAt", ">", 0)
//.orderBy("\$updatedAt")
.orderBy("\$ownerId")
.build()
)
Expand All @@ -334,4 +347,14 @@ class DapiGrpcClientTest : BaseTest() {
.build()
)
}

@Test
fun broadcastStateTransitionTest() {
val st = "a5647479706502697369676e617475726558411ff1764ead95ff03f90b177fa138bd0b510309da5ac75b6b0498d18f4a1f55036c77d6626b9dc660b54ca9f7085fef1a9070d2694e064175c6b68cb9d947b2017e6a7075626c69634b65797382a76269640064646174615821038035e6856dd646654eb1a76dd9bd93af0e21889feb68a652fb8360974be3b6a964747970650067707572706f73650068726561644f6e6c79f4697369676e617475726558412085d4139c1f81b223beee448f92b117fd489a995424102c40b2ca4ec6cd31ce7e7b9410e2aa8a88f47f6fcf757bdd801b7f8f091c3bf803f850c64ee24e7c62e96d73656375726974794c6576656c00a762696401646461746158210396605ff4ca17f88a6294d8ce5b65d7ae797ab7ef61f7ff38acdf036cf9c61c0d64747970650067707572706f73650068726561644f6e6c79f4697369676e6174757265584120ca609cbb2f4a2fe563ffb4d093e59e3f2bb3f3bdb56cf7fe2ddf7b4e16f43d685d1a56caac7e8476adb7e2cc131db1b9a3a3fa78fa10f36724d20fb69de69d5a6d73656375726974794c6576656c026e61737365744c6f636b50726f6f66a3647479706501686f7574506f696e7458249683e679611f3c2f0bfaf7f8ee55f9312fbf059a421e36ab5d3c4a854946ca220000000075636f7265436861696e4c6f636b65644865696768741a0001edce6f70726f746f636f6c56657273696f6e01"
val map = Cbor.decode(Converters.fromHex(st))
map["signature"] = ByteArray(65)
val icst = IdentityCreateTransition(AbsintheDevNetParams.get(), map)
assertTrue(DPP.validateIdentityCreateTransition(icst.toObject()))
client.broadcastStateTransitionInternal(icst, false)
}
}
15 changes: 10 additions & 5 deletions src/test/kotlin/org/dashj/platform/dapiclient/ProofTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ import org.bitcoinj.core.Context
import org.bitcoinj.core.Sha256Hash
import org.bitcoinj.core.Utils
import org.bitcoinj.crypto.BLSPublicKey
import org.bitcoinj.params.AbsintheDevNetParams
import org.bitcoinj.params.TestNet3Params
import org.bitcoinj.quorums.LLMQParameters
import org.bitcoinj.quorums.Quorum
import org.dash.platform.dapi.v0.PlatformOuterClass
import org.dashj.dpp.DPP
import org.dashj.merk.ByteArrayKey
import org.dashj.merk.MerkVerifyProof
import org.dashj.merk.blake3
Expand All @@ -29,9 +31,11 @@ import org.dashj.platform.dapiclient.proofs.MerkleTree
import org.dashj.platform.dapiclient.proofs.ProofVerifier
import org.dashj.platform.dpp.DashPlatformProtocol
import org.dashj.platform.dpp.identifier.Identifier
import org.dashj.platform.dpp.identity.Identity
import org.dashj.platform.dpp.identity.IdentityFactory
import org.dashj.platform.dpp.toByteArray
import org.dashj.platform.dpp.toHex
import org.dashj.platform.dpp.util.Cbor
import org.dashj.platform.dpp.util.Converters
import org.junit.jupiter.api.Assertions.assertArrayEquals
import org.junit.jupiter.api.Assertions.assertEquals
Expand All @@ -47,9 +51,9 @@ class ProofTest : BaseTest() {
// BLS.Init()
}

val PARAMS = TestNet3Params.get()
val PARAMS = AbsintheDevNetParams.get()
val CONTEXT = Context.getOrCreate(PARAMS)
val masternodeList = PARAMS.defaultMasternodeList.toList()
val masternodeList = PARAMS.defaultHPMasternodeList.toList()
val dpnsContractId = SystemIds.dpnsDataContractId // DPNS contract
val dashPayContractId = SystemIds.dashpayDataContractId
val identityId = SystemIds.dashpayOwnerId
Expand All @@ -58,8 +62,8 @@ class ProofTest : BaseTest() {
val badIdentityId = Identifier.from("GrdbRMnZ5pPiFWuzPR62goRVj6sxpqvLKMT87ZmuZPyr")

// these values are taken from https://github.com/dashevo/dash-network-configs/blob/master/testnet.yml
val publicKeyHashDpns = Utils.sha256hash160(Converters.fromHex("03922abfd8765ba334e8c16c63ea0d6f2f09ba19bb07684c12f75f46a1255a136f"))
val publicKeyHashDashpay = Utils.sha256hash160(Converters.fromHex("03a5d8392f3793699a53ed00e87600536679bd1c44f2bfda28c51e30c8daa10f9a"))
val publicKeyHashDpns = Utils.sha256hash160(Converters.fromHex("037cb691d72a2ea23ea76a5e311bd6dffa4abbb6a359fc86108aeefa6d4268e3d9"))
val publicKeyHashDashpay = Utils.sha256hash160(Converters.fromHex("03292da1684067c3b78ecef3d3e2c132434e7aa9930c0a520bfc4e2ad73a3edd6b"))

val publicKeyHash = publicKeyHashDpns
val publicKeyHashes = listOf(publicKeyHashDpns, publicKeyHashDashpay)
Expand All @@ -77,7 +81,8 @@ class ProofTest : BaseTest() {
fun getIdentityWithProof() {
try {
val identityBytes = client.getIdentity(identityId.toBuffer(), false).identity
val identity = dpp.identity.createFromBuffer(identityBytes)
val identityBytesCbor = DPP.getIdentityCborFromBincode(identityBytes)
val identity = dpp.identity.createFromBuffer(identityBytesCbor)
assertEquals(identityId, identity.id)
println("identity: ${identityBytes.toHex()}")

Expand Down