Standardisation of Public Keys in Schema entities. (#68) (#1936)

* Standardisation of Public Keys in Schema entities. (#68)

* Standardisation in usage of Public Keys in Schema entities.
Use PK Hash where optimal, otherwise use ByteArray/LOB representation of PK.

* Redundant after rebase.

* Use .encoded and Crypto.decode<Public|Private>Key(bytes) instead of Corda serialization.

* Optimize DBPartyAndCertificate entity to store and query on ownerKeyHash.

* Updated API stability check for schema attribute change.
This commit is contained in:
josecoll
2017-10-24 22:11:41 +01:00
committed by GitHub
parent 2fe3fbbfef
commit 5349d4f850
21 changed files with 94 additions and 81 deletions

View File

@ -11,8 +11,8 @@ import net.corda.core.node.services.UnknownAnonymousPartyException
import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.utilities.debug
import net.corda.core.utilities.loggerFor
import net.corda.core.utilities.MAX_HASH_HEX_SIZE
import net.corda.node.utilities.AppendOnlyPersistentMap
import net.corda.node.utilities.MAX_HASH_HEX_SIZE
import net.corda.node.utilities.NODE_DATABASE_PREFIX
import org.bouncycastle.cert.X509CertificateHolder
import java.io.ByteArrayInputStream

View File

@ -4,12 +4,9 @@ import net.corda.core.crypto.*
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.node.services.IdentityService
import net.corda.core.node.services.KeyManagementService
import net.corda.core.serialization.SerializationDefaults
import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.core.utilities.MAX_HASH_HEX_SIZE
import net.corda.node.utilities.AppendOnlyPersistentMap
import net.corda.node.utilities.MAX_HASH_HEX_SIZE
import net.corda.node.utilities.NODE_DATABASE_PREFIX
import org.bouncycastle.operator.ContentSigner
import java.security.KeyPair
@ -47,17 +44,15 @@ class PersistentKeyManagementService(val identityService: IdentityService,
var privateKey: ByteArray = ByteArray(0)
) {
constructor(publicKey: PublicKey, privateKey: PrivateKey)
: this(publicKey.toStringShort(),
publicKey.serialize(context = SerializationDefaults.STORAGE_CONTEXT).bytes,
privateKey.serialize(context = SerializationDefaults.STORAGE_CONTEXT).bytes)
: this(publicKey.toStringShort(), publicKey.encoded, privateKey.encoded)
}
private companion object {
fun createKeyMap(): AppendOnlyPersistentMap<PublicKey, PrivateKey, PersistentKey, String> {
return AppendOnlyPersistentMap(
toPersistentEntityKey = { it.toStringShort() },
fromPersistentEntity = { Pair(it.publicKey.deserialize(context = SerializationDefaults.STORAGE_CONTEXT),
it.privateKey.deserialize(context = SerializationDefaults.STORAGE_CONTEXT)) },
fromPersistentEntity = { Pair(Crypto.decodePublicKey(it.publicKey), Crypto.decodePrivateKey(
it.privateKey)) },
toPersistentEntity = { key: PublicKey, value: PrivateKey ->
PersistentKey(key, value)
},

View File

@ -1,6 +1,8 @@
package net.corda.node.services.network
import net.corda.core.concurrent.CordaFuture
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.toStringShort
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
@ -17,6 +19,7 @@ import net.corda.core.node.services.NetworkMapCache.MapChange
import net.corda.core.node.services.NotaryService
import net.corda.core.node.services.PartyInfo
import net.corda.core.schemas.NodeInfoSchemaV1
import net.corda.core.serialization.SerializationDefaults
import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
@ -323,9 +326,9 @@ open class PersistentNetworkMapCache(private val database: CordaPersistence, con
private fun findByIdentityKey(session: Session, identityKey: PublicKey): List<NodeInfoSchemaV1.PersistentNodeInfo> {
val query = session.createQuery(
"SELECT n FROM ${NodeInfoSchemaV1.PersistentNodeInfo::class.java.name} n JOIN n.legalIdentitiesAndCerts l WHERE l.owningKey = :owningKey",
"SELECT n FROM ${NodeInfoSchemaV1.PersistentNodeInfo::class.java.name} n JOIN n.legalIdentitiesAndCerts l WHERE l.owningKeyHash = :owningKeyHash",
NodeInfoSchemaV1.PersistentNodeInfo::class.java)
query.setParameter("owningKey", identityKey.toBase58String())
query.setParameter("owningKeyHash", identityKey.toStringShort())
return query.resultList
}

View File

@ -7,9 +7,9 @@ import net.corda.core.messaging.SingleMessageRecipient
import net.corda.core.serialization.SerializationDefaults
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.core.utilities.MAX_HASH_HEX_SIZE
import net.corda.node.services.api.NetworkMapCacheInternal
import net.corda.node.services.messaging.MessagingService
import net.corda.node.utilities.MAX_HASH_HEX_SIZE
import net.corda.node.utilities.NODE_DATABASE_PREFIX
import net.corda.node.utilities.PersistentMap
import net.corda.nodeapi.ArtemisMessagingComponent

View File

@ -3,6 +3,7 @@ package net.corda.node.services.transactions
import co.paralleluniverse.fibers.Suspendable
import com.google.common.util.concurrent.SettableFuture
import net.corda.core.contracts.StateRef
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.DigitalSignature
import net.corda.core.crypto.SecureHash
import net.corda.core.flows.FlowLogic
@ -15,6 +16,7 @@ import net.corda.core.node.services.NotaryService
import net.corda.core.node.services.TimeWindowChecker
import net.corda.core.node.services.UniquenessProvider
import net.corda.core.schemas.PersistentStateRef
import net.corda.core.serialization.SerializationDefaults
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.core.transactions.FilteredTransaction
@ -110,7 +112,7 @@ class BFTNonValidatingNotaryService(override val services: ServiceHubInternal,
inputIndex = it.consumingIndex,
requestingParty = Party(
name = CordaX500Name.parse(it.party.name),
owningKey = parsePublicKeyBase58(it.party.owningKey))))
owningKey = Crypto.decodePublicKey(it.party.owningKey))))
},
toPersistentEntity = { (txHash, index): StateRef, (id, inputIndex, requestingParty): UniquenessProvider.ConsumingTx ->
PersistedCommittedState(
@ -118,7 +120,7 @@ class BFTNonValidatingNotaryService(override val services: ServiceHubInternal,
consumingTxHash = id.toString(),
consumingIndex = inputIndex,
party = PersistentUniquenessProvider.PersistentParty(requestingParty.name.toString(),
requestingParty.owningKey.toBase58String())
requestingParty.owningKey.encoded)
)
},
persistentEntityClass = PersistedCommittedState::class.java

View File

@ -1,6 +1,7 @@
package net.corda.node.services.transactions
import net.corda.core.contracts.StateRef
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SecureHash
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
@ -8,10 +9,11 @@ import net.corda.core.internal.ThreadBox
import net.corda.core.node.services.UniquenessException
import net.corda.core.node.services.UniquenessProvider
import net.corda.core.schemas.PersistentStateRef
import net.corda.core.serialization.SerializationDefaults
import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.core.utilities.loggerFor
import net.corda.core.utilities.parsePublicKeyBase58
import net.corda.core.utilities.toBase58String
import net.corda.node.utilities.AppendOnlyPersistentMap
import net.corda.node.utilities.NODE_DATABASE_PREFIX
import java.io.Serializable
@ -44,7 +46,7 @@ class PersistentUniquenessProvider : UniquenessProvider, SingletonSerializeAsTok
var name: String = "",
@Column(name = "requesting_party_key", length = 255)
var owningKey: String = ""
var owningKey: ByteArray = ByteArray(0)
) : Serializable
@Entity
@ -75,14 +77,14 @@ class PersistentUniquenessProvider : UniquenessProvider, SingletonSerializeAsTok
inputIndex = it.consumingIndex,
requestingParty = Party(
name = CordaX500Name.parse(it.party.name),
owningKey = parsePublicKeyBase58(it.party.owningKey))))
owningKey = Crypto.decodePublicKey(it.party.owningKey))))
},
toPersistentEntity = { (txHash, index): StateRef, (id, inputIndex, requestingParty): UniquenessProvider.ConsumingTx ->
PersistentNotaryCommit(
id = PersistentStateRef(txHash.toString(), index),
consumingTxHash = id.toString(),
consumingIndex = inputIndex,
party = PersistentParty(requestingParty.name.toString(), requestingParty.owningKey.toBase58String())
party = PersistentParty(requestingParty.name.toString(), requestingParty.owningKey.encoded)
)
},
persistentEntityClass = PersistentNotaryCommit::class.java

View File

@ -20,14 +20,6 @@ import java.util.concurrent.CopyOnWriteArrayList
*/
const val NODE_DATABASE_PREFIX = "node_"
/**
* The maximum supported field-size for hash HEX-encoded outputs (e.g. database fields).
* This value is enough to support hash functions with outputs up to 512 bits (e.g. SHA3-512), in which
* case 128 HEX characters are required.
* 130 was selected instead of 128, to allow for 2 extra characters that will be used as hash-scheme identifiers.
*/
internal const val MAX_HASH_HEX_SIZE = 130
//HikariDataSource implements Closeable which allows CordaPersistence to be Closeable
class CordaPersistence(var dataSource: HikariDataSource, private val schemaService: SchemaService,
private val createIdentityService: () -> IdentityService, databaseProperties: Properties) : Closeable {

View File

@ -448,7 +448,7 @@ class HibernateConfigurationTest : TestDependencyInjectionBase() {
criteriaBuilder.sum(cashStates.get<Long>("pennies")))
// group by
criteriaQuery.groupBy(cashStates.get<String>("issuerParty"), cashStates.get<String>("currency"))
criteriaQuery.groupBy(cashStates.get<String>("issuerPartyHash"), cashStates.get<String>("currency"))
// order by
criteriaQuery.orderBy(criteriaBuilder.desc(criteriaBuilder.sum(cashStates.get<Long>("pennies"))))

View File

@ -3,6 +3,7 @@ package net.corda.node.services.vault
import net.corda.core.contracts.*
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.entropyToKeyPair
import net.corda.core.crypto.toStringShort
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.identity.PartyAndCertificate
@ -693,7 +694,7 @@ class VaultQueryTests : TestDependencyInjectionBase() {
services.fillWithSomeTestCash(100.SWISS_FRANCS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L))
}
database.transaction {
val logicalExpression = builder { CashSchemaV1.PersistentCashState::issuerParty.isNull() }
val logicalExpression = builder { CashSchemaV1.PersistentCashState::issuerPartyHash.isNull() }
val criteria = VaultCustomQueryCriteria(logicalExpression)
val results = vaultService.queryBy<Cash.State>(criteria)
assertThat(results.states).hasSize(0)
@ -708,7 +709,7 @@ class VaultQueryTests : TestDependencyInjectionBase() {
services.fillWithSomeTestCash(100.SWISS_FRANCS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L))
}
database.transaction {
val logicalExpression = builder { CashSchemaV1.PersistentCashState::issuerParty.notNull() }
val logicalExpression = builder { CashSchemaV1.PersistentCashState::issuerPartyHash.notNull() }
val criteria = VaultCustomQueryCriteria(logicalExpression)
val results = vaultService.queryBy<Cash.State>(criteria)
assertThat(results.states).hasSize(3)
@ -830,7 +831,7 @@ class VaultQueryTests : TestDependencyInjectionBase() {
database.transaction {
// DOCSTART VaultQueryExample23
val sum = builder {
CashSchemaV1.PersistentCashState::pennies.sum(groupByColumns = listOf(CashSchemaV1.PersistentCashState::issuerParty,
CashSchemaV1.PersistentCashState::pennies.sum(groupByColumns = listOf(CashSchemaV1.PersistentCashState::issuerPartyHash,
CashSchemaV1.PersistentCashState::currency),
orderBy = Sort.Direction.DESC)
}
@ -841,16 +842,16 @@ class VaultQueryTests : TestDependencyInjectionBase() {
assertThat(results.otherResults).hasSize(12)
assertThat(results.otherResults[0]).isEqualTo(40000L)
assertThat(results.otherResults[1]).isEqualTo(BOC_PUBKEY.toBase58String())
assertThat(results.otherResults[1]).isEqualTo(BOC_PUBKEY.toStringShort())
assertThat(results.otherResults[2]).isEqualTo("GBP")
assertThat(results.otherResults[3]).isEqualTo(30000L)
assertThat(results.otherResults[4]).isEqualTo(DUMMY_CASH_ISSUER.party.owningKey.toBase58String())
assertThat(results.otherResults[4]).isEqualTo(DUMMY_CASH_ISSUER.party.owningKey.toStringShort())
assertThat(results.otherResults[5]).isEqualTo("GBP")
assertThat(results.otherResults[6]).isEqualTo(20000L)
assertThat(results.otherResults[7]).isEqualTo(BOC_PUBKEY.toBase58String())
assertThat(results.otherResults[7]).isEqualTo(BOC_PUBKEY.toStringShort())
assertThat(results.otherResults[8]).isEqualTo("USD")
assertThat(results.otherResults[9]).isEqualTo(10000L)
assertThat(results.otherResults[10]).isEqualTo(DUMMY_CASH_ISSUER.party.owningKey.toBase58String())
assertThat(results.otherResults[10]).isEqualTo(DUMMY_CASH_ISSUER.party.owningKey.toStringShort())
assertThat(results.otherResults[11]).isEqualTo("USD")
}
}