From 1344bfd6bbed18b95d21535df71029ea86963014 Mon Sep 17 00:00:00 2001
From: sofusmortensen <sofusmortensen@gmail.com>
Date: Wed, 23 Mar 2016 17:51:14 +0000
Subject: [PATCH] Replaced programRef in ContractState with a simple reference
 to contract

---
 .../kotlin/contracts/AnotherDummyContract.kt  | 12 +++--
 .../java/contracts/JavaCommercialPaper.java   |  8 ++--
 contracts/src/main/kotlin/contracts/Cash.kt   |  5 ++-
 .../main/kotlin/contracts/CommercialPaper.kt  |  4 +-
 .../src/main/kotlin/contracts/CrowdFund.kt    |  4 +-
 .../main/kotlin/contracts/DummyContract.kt    |  4 +-
 contracts/src/main/kotlin/contracts/IRS.kt    |  4 +-
 core/src/main/kotlin/core/Structures.kt       | 19 +-------
 .../kotlin/core/TransactionVerification.kt    | 12 +++--
 .../main/kotlin/core/serialization/Kryo.kt    | 44 ++++++++++++++++++-
 src/main/kotlin/core/node/AbstractNode.kt     | 23 ++--------
 src/main/kotlin/core/node/ClassLoader.kt      |  6 +++
 .../kotlin/core/node/services/Services.kt     |  7 +--
 .../core/node/services/StorageServiceImpl.kt  |  3 --
 .../protocols/ResolveTransactionsProtocol.kt  |  2 +-
 .../kotlin/contracts/CommercialPaperTests.kt  |  4 +-
 src/test/kotlin/contracts/CrowdFundTests.kt   |  4 +-
 src/test/kotlin/core/MockServices.kt          | 10 +----
 src/test/kotlin/core/TransactionGroupTests.kt |  2 +-
 .../messaging/TwoPartyTradeProtocolTests.kt   |  5 +--
 src/test/kotlin/core/node/ClassLoaderTests.kt |  5 +++
 src/test/kotlin/core/testutils/TestUtils.kt   |  6 +--
 22 files changed, 100 insertions(+), 93 deletions(-)

diff --git a/contracts/isolated/src/main/kotlin/contracts/AnotherDummyContract.kt b/contracts/isolated/src/main/kotlin/contracts/AnotherDummyContract.kt
index bec6b01cfe..1cee079cbb 100644
--- a/contracts/isolated/src/main/kotlin/contracts/AnotherDummyContract.kt
+++ b/contracts/isolated/src/main/kotlin/contracts/AnotherDummyContract.kt
@@ -8,6 +8,7 @@
 
 package contracts.isolated
 
+import core.*
 import core.Contract
 import core.ContractState
 import core.TransactionForVerification
@@ -15,17 +16,20 @@ import core.crypto.SecureHash
 
 // The dummy contract doesn't do anything useful. It exists for testing purposes.
 
-val ANOTHER_DUMMY_PROGRAM_ID = SecureHash.sha256("dummy")
+val ANOTHER_DUMMY_PROGRAM_ID = AnotherDummyContract()
 
 class AnotherDummyContract : Contract {
-    class State : ContractState {
-        override val programRef: SecureHash = ANOTHER_DUMMY_PROGRAM_ID
+    data class State(val foo: Int) : ContractState {
+        override val contract = ANOTHER_DUMMY_PROGRAM_ID
     }
 
     override fun verify(tx: TransactionForVerification) {
+        requireThat {
+            "justice will be served" by false
+        }
         // Always accepts.
     }
 
     // The "empty contract"
-    override val legalContractReference: SecureHash = SecureHash.sha256("https://anotherdummy.org")
+    override val legalContractReference = SecureHash.sha256("https://anotherdummy.org")
 }
\ No newline at end of file
diff --git a/contracts/src/main/java/contracts/JavaCommercialPaper.java b/contracts/src/main/java/contracts/JavaCommercialPaper.java
index 798ff960d2..dd447f0556 100644
--- a/contracts/src/main/java/contracts/JavaCommercialPaper.java
+++ b/contracts/src/main/java/contracts/JavaCommercialPaper.java
@@ -32,7 +32,8 @@ import static kotlin.collections.CollectionsKt.single;
  *
  */
 public class JavaCommercialPaper implements Contract {
-    public static SecureHash JCP_PROGRAM_ID = SecureHash.sha256("java commercial paper (this should be a bytecode hash)");
+    //public static SecureHash JCP_PROGRAM_ID = SecureHash.sha256("java commercial paper (this should be a bytecode hash)");
+    public static Contract JCP_PROGRAM_ID = new JavaCommercialPaper();
 
     public static class State implements ContractState, ICommercialPaperState {
         private PartyReference issuance;
@@ -87,8 +88,9 @@ public class JavaCommercialPaper implements Contract {
 
         @NotNull
         @Override
-        public SecureHash getProgramRef() {
-            return SecureHash.Companion.sha256("java commercial paper (this should be a bytecode hash)");
+        public Contract getContract() {
+            return JCP_PROGRAM_ID;
+            //return SecureHash.Companion.sha256("java commercial paper (this should be a bytecode hash)");
         }
 
         @Override
diff --git a/contracts/src/main/kotlin/contracts/Cash.kt b/contracts/src/main/kotlin/contracts/Cash.kt
index 8901597400..b216bcacc4 100644
--- a/contracts/src/main/kotlin/contracts/Cash.kt
+++ b/contracts/src/main/kotlin/contracts/Cash.kt
@@ -22,7 +22,8 @@ import java.util.*
 //
 
 // Just a fake program identifier for now. In a real system it could be, for instance, the hash of the program bytecode.
-val CASH_PROGRAM_ID = SecureHash.sha256("cash")
+val CASH_PROGRAM_ID = Cash()
+    //SecureHash.sha256("cash")
 
 class InsufficientBalanceException(val amountMissing: Amount) : Exception()
 
@@ -62,7 +63,7 @@ class Cash : Contract {
             /** There must be a MoveCommand signed by this key to claim the amount */
             override val owner: PublicKey
     ) : OwnableState {
-        override val programRef = CASH_PROGRAM_ID
+        override val contract = CASH_PROGRAM_ID
         override fun toString() = "${Emoji.bagOfCash}Cash($amount at $deposit owned by ${owner.toStringShort()})"
 
         override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Move(), copy(owner = newOwner))
diff --git a/contracts/src/main/kotlin/contracts/CommercialPaper.kt b/contracts/src/main/kotlin/contracts/CommercialPaper.kt
index 225fb197a5..417bc5c40e 100644
--- a/contracts/src/main/kotlin/contracts/CommercialPaper.kt
+++ b/contracts/src/main/kotlin/contracts/CommercialPaper.kt
@@ -38,7 +38,7 @@ import java.time.Instant
  *    to do this in the Apache BVal project).
  */
 
-val CP_PROGRAM_ID = SecureHash.sha256("replace-me-later-with-bytecode-hash")
+val CP_PROGRAM_ID = CommercialPaper()
 
 // TODO: Generalise the notion of an owned instrument into a superclass/supercontract. Consider composition vs inheritance.
 class CommercialPaper : Contract {
@@ -51,7 +51,7 @@ class CommercialPaper : Contract {
             val faceValue: Amount,
             val maturityDate: Instant
     ) : OwnableState, ICommercialPaperState {
-        override val programRef = CP_PROGRAM_ID
+        override val contract = CP_PROGRAM_ID
 
         fun withoutOwner() = copy(owner = NullPublicKey)
         override fun withNewOwner(newOwner: PublicKey) = Pair(Commands.Move(), copy(owner = newOwner))
diff --git a/contracts/src/main/kotlin/contracts/CrowdFund.kt b/contracts/src/main/kotlin/contracts/CrowdFund.kt
index 8c7590821e..bc1dc7ce3f 100644
--- a/contracts/src/main/kotlin/contracts/CrowdFund.kt
+++ b/contracts/src/main/kotlin/contracts/CrowdFund.kt
@@ -15,7 +15,7 @@ import java.security.PublicKey
 import java.time.Instant
 import java.util.*
 
-val CROWDFUND_PROGRAM_ID = SecureHash.sha256("crowdsourcing")
+val CROWDFUND_PROGRAM_ID = CrowdFund()
 
 /**
  * This is a basic crowd funding contract. It allows a party to create a funding opportunity, then for others to
@@ -57,7 +57,7 @@ class CrowdFund : Contract {
             val closed: Boolean = false,
             val pledges: List<Pledge> = ArrayList()
     ) : ContractState {
-        override val programRef = CROWDFUND_PROGRAM_ID
+        override val contract = CROWDFUND_PROGRAM_ID
 
         val pledgedAmount: Amount get() = pledges.map { it.amount }.sumOrZero(campaign.target.currency)
     }
diff --git a/contracts/src/main/kotlin/contracts/DummyContract.kt b/contracts/src/main/kotlin/contracts/DummyContract.kt
index 52956d71c5..5a7761acba 100644
--- a/contracts/src/main/kotlin/contracts/DummyContract.kt
+++ b/contracts/src/main/kotlin/contracts/DummyContract.kt
@@ -15,11 +15,11 @@ import core.crypto.SecureHash
 
 // The dummy contract doesn't do anything useful. It exists for testing purposes.
 
-val DUMMY_PROGRAM_ID = SecureHash.sha256("dummy")
+val DUMMY_PROGRAM_ID = DummyContract()
 
 class DummyContract : Contract {
     class State : ContractState {
-        override val programRef: SecureHash = DUMMY_PROGRAM_ID
+        override val contract = DUMMY_PROGRAM_ID
     }
 
     override fun verify(tx: TransactionForVerification) {
diff --git a/contracts/src/main/kotlin/contracts/IRS.kt b/contracts/src/main/kotlin/contracts/IRS.kt
index 273272a927..a8cf5177a8 100644
--- a/contracts/src/main/kotlin/contracts/IRS.kt
+++ b/contracts/src/main/kotlin/contracts/IRS.kt
@@ -18,7 +18,7 @@ import java.math.RoundingMode
 import java.time.LocalDate
 import java.util.*
 
-val IRS_PROGRAM_ID = SecureHash.sha256("replace-me-later-with-bytecode-hash-of-irs-code")
+val IRS_PROGRAM_ID = InterestRateSwap()
 
 // This is a placeholder for some types that we haven't identified exactly what they are just yet for things still in discussion
 open class UnknownType()
@@ -349,7 +349,7 @@ class InterestRateSwap() : Contract {
             val calculation: Calculation,
             val common: Common
     ) : ContractState {
-        override val programRef = IRS_PROGRAM_ID
+        override val contract = IRS_PROGRAM_ID
 
         /**
          * For evaluating arbitrary java on the platform
diff --git a/core/src/main/kotlin/core/Structures.kt b/core/src/main/kotlin/core/Structures.kt
index 56a8a0d326..08aca588e0 100644
--- a/core/src/main/kotlin/core/Structures.kt
+++ b/core/src/main/kotlin/core/Structures.kt
@@ -32,11 +32,9 @@ interface NamedByHash {
  */
 interface ContractState {
     /**
-     * Refers to a bytecode program that has previously been published to the network. This contract program
-     * will be executed any time this state is used in an input. It must accept in order for the
-     * transaction to proceed.
+     * Contract by which the state belongs
      */
-    val programRef: SecureHash
+    val contract: Contract
 }
 
 interface OwnableState : ContractState {
@@ -144,19 +142,6 @@ interface Contract {
     val legalContractReference: SecureHash
 }
 
-/** A contract factory knows how to lazily load and instantiate contract objects. */
-interface ContractFactory {
-    /**
-     * Loads, instantiates and returns a contract object from its class bytecodes, given the hash of that bytecode.
-     *
-     * @throws UnknownContractException if the hash doesn't map to any known contract.
-     * @throws ClassCastException if the hash mapped to a contract, but it was not of type T
-     */
-    operator fun <T : Contract> get(hash: SecureHash): T
-}
-
-class UnknownContractException : Exception()
-
 /**
  * An attachment is a ZIP (or an optionally signed JAR) that contains one or more files. Attachments are meant to
  * contain public static data which can be referenced from transactions and utilised from contracts. Good examples
diff --git a/core/src/main/kotlin/core/TransactionVerification.kt b/core/src/main/kotlin/core/TransactionVerification.kt
index 5f24af239d..3e9e2ce89f 100644
--- a/core/src/main/kotlin/core/TransactionVerification.kt
+++ b/core/src/main/kotlin/core/TransactionVerification.kt
@@ -28,7 +28,7 @@ class TransactionGroup(val transactions: Set<LedgerTransaction>, val nonVerified
     /**
      * Verifies the group and returns the set of resolved transactions.
      */
-    fun verify(programMap: ContractFactory): Set<TransactionForVerification> {
+    fun verify(): Set<TransactionForVerification> {
         // Check that every input can be resolved to an output.
         // Check that no output is referenced by more than one input.
         // Cycles should be impossible due to the use of hashes as pointers.
@@ -55,7 +55,7 @@ class TransactionGroup(val transactions: Set<LedgerTransaction>, val nonVerified
         }
 
         for (tx in resolved)
-            tx.verify(programMap)
+            tx.verify()
         return resolved
     }
 
@@ -79,13 +79,11 @@ data class TransactionForVerification(val inStates: List<ContractState>,
      * @throws IllegalStateException if a state refers to an unknown contract.
      */
     @Throws(TransactionVerificationException::class, IllegalStateException::class)
-    fun verify(programMap: ContractFactory) {
+    fun verify() {
         // For each input and output state, locate the program to run. Then execute the verification function. If any
         // throws an exception, the entire transaction is invalid.
-        val programHashes = (inStates.map { it.programRef } + outStates.map { it.programRef }).toSet()
-        for (hash in programHashes) {
-            // TODO: Change this interface to ensure that attachment JARs are put on the classpath before execution.
-            val program: Contract = programMap[hash]
+        val programs = (inStates.map { it.contract } + outStates.map { it.contract }).toSet()
+        for (program in programs) {
             try {
                 program.verify(this)
             } catch(e: Throwable) {
diff --git a/core/src/main/kotlin/core/serialization/Kryo.kt b/core/src/main/kotlin/core/serialization/Kryo.kt
index ffbf602e25..5c05164a3a 100644
--- a/core/src/main/kotlin/core/serialization/Kryo.kt
+++ b/core/src/main/kotlin/core/serialization/Kryo.kt
@@ -16,8 +16,7 @@ import com.esotericsoftware.kryo.Serializer
 import com.esotericsoftware.kryo.io.Input
 import com.esotericsoftware.kryo.io.Output
 import com.esotericsoftware.kryo.serializers.JavaSerializer
-import core.SignedTransaction
-import core.WireTransaction
+import core.*
 import core.crypto.SecureHash
 import core.crypto.generateKeyPair
 import core.crypto.sha256
@@ -179,6 +178,19 @@ class ImmutableClassSerializer<T : Any>(val klass: KClass<T>) : Serializer<T>()
     }
 }
 
+fun Kryo.useClassLoader(cl: ClassLoader, body: () -> Unit) {
+    val tmp = this.classLoader
+    this.classLoader = cl
+    try {
+        body()
+    }
+    finally {
+        if (tmp != null) {
+            this.classLoader
+        }
+    }
+}
+
 fun createKryo(k: Kryo = Kryo()): Kryo {
     return k.apply {
         // Allow any class to be deserialized (this is insecure but for prototyping we don't care)
@@ -201,6 +213,34 @@ fun createKryo(k: Kryo = Kryo()): Kryo {
             }
         })
 
+       register(WireTransaction::class.java, object : Serializer<WireTransaction>() {
+            override fun write(kryo: Kryo, output: Output, obj: WireTransaction) {
+
+                kryo.writeClassAndObject( output, obj.inputs )
+                kryo.writeClassAndObject( output, obj.attachments )
+
+                kryo.writeClassAndObject( output, obj.outputs )
+                kryo.writeClassAndObject( output, obj.commands )
+
+            }
+
+            override fun read(kryo: Kryo, input: Input, type: Class<WireTransaction>): WireTransaction {
+                var inputs = kryo.readClassAndObject( input ) as List<StateRef>
+                var attachments = kryo.readClassAndObject( input ) as List<SecureHash>
+
+                // had we access to AttachmentStorage here, a ClassLoader could be created
+
+                // val customClassLoader = createClassLoader( attachments )
+                // kryo.useClassLoader(customClassLoader) {
+
+                    var outputs = kryo.readClassAndObject(input) as List<ContractState>
+                    var commands = kryo.readClassAndObject(input) as List<Command>
+
+                return WireTransaction(inputs, attachments, outputs, commands)
+                // }
+            }
+        })
+
         // Some things where the JRE provides an efficient custom serialisation.
         val ser = JavaSerializer()
         val keyPair = generateKeyPair()
diff --git a/src/main/kotlin/core/node/AbstractNode.kt b/src/main/kotlin/core/node/AbstractNode.kt
index 3e637f8603..a3276337b4 100644
--- a/src/main/kotlin/core/node/AbstractNode.kt
+++ b/src/main/kotlin/core/node/AbstractNode.kt
@@ -66,22 +66,6 @@ abstract class AbstractNode(val dir: Path, val configuration: NodeConfiguration,
 
     val legallyIdentifableAddress: LegallyIdentifiableNode get() = LegallyIdentifiableNode(net.myAddress, storage.myLegalIdentity)
 
-    // TODO: This will be obsoleted by "PLT-12: Basic module/sandbox system for contracts"
-    protected val contractFactory = object : ContractFactory {
-        private val contracts = mapOf(
-                CASH_PROGRAM_ID to Cash::class.java,
-                CP_PROGRAM_ID to CommercialPaper::class.java,
-                CROWDFUND_PROGRAM_ID to CrowdFund::class.java,
-                DUMMY_PROGRAM_ID to DummyContract::class.java
-        )
-
-        override fun <T : Contract> get(hash: SecureHash): T {
-            val c = contracts[hash] ?: throw UnknownContractException()
-            @Suppress("UNCHECKED_CAST")
-            return c.newInstance() as T
-        }
-    }
-
     lateinit var storage: StorageService
     lateinit var smm: StateMachineManager
     lateinit var wallet: WalletService
@@ -147,12 +131,11 @@ abstract class AbstractNode(val dir: Path, val configuration: NodeConfiguration,
         val attachments = makeAttachmentStorage(dir)
         _servicesThatAcceptUploads += attachments
         val (identity, keypair) = obtainKeyPair(dir)
-        return constructStorageService(attachments, keypair, identity, contractFactory)
+        return constructStorageService(attachments, keypair, identity)
     }
 
-    protected open fun constructStorageService(attachments: NodeAttachmentService, keypair: KeyPair, identity: Party,
-                                               contractFactory: ContractFactory) =
-            StorageServiceImpl(attachments, contractFactory, keypair, identity)
+    protected open fun constructStorageService(attachments: NodeAttachmentService, keypair: KeyPair, identity: Party) =
+            StorageServiceImpl(attachments, keypair, identity)
 
     private fun obtainKeyPair(dir: Path): Pair<Party, KeyPair> {
         // Load the private identity key, creating it if necessary. The identity key is a long term well known key that
diff --git a/src/main/kotlin/core/node/ClassLoader.kt b/src/main/kotlin/core/node/ClassLoader.kt
index e57e1360cf..c19b72c29b 100644
--- a/src/main/kotlin/core/node/ClassLoader.kt
+++ b/src/main/kotlin/core/node/ClassLoader.kt
@@ -6,6 +6,8 @@ import java.io.File
 import java.io.FileOutputStream
 import java.net.URL
 import java.net.URLClassLoader
+import java.security.AccessControlContext
+import java.security.ProtectionDomain
 import java.util.*
 import java.util.jar.JarEntry
 
@@ -28,6 +30,10 @@ class ClassLoader private constructor(val tmpFiles: List<File> )
         }
     }
 
+    override fun loadClass(name: String?, resolve: Boolean): Class<*>? {
+        return super.loadClass(name, resolve)
+    }
+
     companion object {
         fun create(streams: List<Attachment>) : ClassLoader {
 
diff --git a/src/main/kotlin/core/node/services/Services.kt b/src/main/kotlin/core/node/services/Services.kt
index 6974af1c4e..538369c80a 100644
--- a/src/main/kotlin/core/node/services/Services.kt
+++ b/src/main/kotlin/core/node/services/Services.kt
@@ -116,11 +116,6 @@ interface StorageService {
     /** Provides access to storage of arbitrary JAR files (which may contain only data, no code). */
     val attachments: AttachmentStorage
 
-    /**
-     * A map of program hash->contract class type, used for verification.
-     */
-    val contractPrograms: ContractFactory
-
     /**
      * Returns the legal identity that this node is configured with. Assumed to be initialised when the node is
      * first installed.
@@ -186,6 +181,6 @@ interface ServiceHub {
             storageService.validatedTransactions[it.txhash] ?: throw TransactionResolutionException(it.txhash)
         }
         val ltxns = dependencies.map { it.verifyToLedgerTransaction(identityService, storageService.attachments) }
-        TransactionGroup(setOf(ltx), ltxns.toSet()).verify(storageService.contractPrograms)
+        TransactionGroup(setOf(ltx), ltxns.toSet()).verify()
     }
 }
diff --git a/src/main/kotlin/core/node/services/StorageServiceImpl.kt b/src/main/kotlin/core/node/services/StorageServiceImpl.kt
index b0a0490282..3d7d07c6ff 100644
--- a/src/main/kotlin/core/node/services/StorageServiceImpl.kt
+++ b/src/main/kotlin/core/node/services/StorageServiceImpl.kt
@@ -1,6 +1,5 @@
 package core.node.services
 
-import core.ContractFactory
 import core.Party
 import core.SignedTransaction
 import core.crypto.SecureHash
@@ -10,7 +9,6 @@ import java.security.KeyPair
 import java.util.*
 
 open class StorageServiceImpl(attachments: AttachmentStorage,
-                              contractFactory: ContractFactory,
                               keypair: KeyPair,
                               identity: Party = Party("Unit test party", keypair.public),
                               // This parameter is for unit tests that want to observe operation details.
@@ -39,7 +37,6 @@ open class StorageServiceImpl(attachments: AttachmentStorage,
         get() = getMapOriginal("state-machines")
 
     override val attachments: AttachmentStorage = attachments
-    override val contractPrograms = contractFactory
     override val myLegalIdentity = identity
     override val myLegalIdentityKey = keypair
 }
\ No newline at end of file
diff --git a/src/main/kotlin/protocols/ResolveTransactionsProtocol.kt b/src/main/kotlin/protocols/ResolveTransactionsProtocol.kt
index 8e6a638c9d..a224b3b0d4 100644
--- a/src/main/kotlin/protocols/ResolveTransactionsProtocol.kt
+++ b/src/main/kotlin/protocols/ResolveTransactionsProtocol.kt
@@ -66,7 +66,7 @@ class ResolveTransactionsProtocol(private val txHashes: Set<SecureHash>,
         }
 
         // Run all the contracts and throw an exception if any of them reject.
-        TransactionGroup(toVerify, alreadyVerified).verify(serviceHub.storageService.contractPrograms)
+        TransactionGroup(toVerify, alreadyVerified).verify()
 
         // Now write all the transactions we just validated back to the database for next time, including
         // signatures so we can serve up these transactions to other peers when we, in turn, send one that
diff --git a/src/test/kotlin/contracts/CommercialPaperTests.kt b/src/test/kotlin/contracts/CommercialPaperTests.kt
index b252f24e38..0c85c5c466 100644
--- a/src/test/kotlin/contracts/CommercialPaperTests.kt
+++ b/src/test/kotlin/contracts/CommercialPaperTests.kt
@@ -219,11 +219,11 @@ class CommercialPaperTestsGeneric {
         val validRedemption = makeRedeemTX(TEST_TX_TIME + 31.days)
 
         val e = assertFailsWith(TransactionVerificationException::class) {
-            TransactionGroup(setOf(issueTX, moveTX, tooEarlyRedemption), setOf(corpWalletTX, alicesWalletTX)).verify(MockContractFactory)
+            TransactionGroup(setOf(issueTX, moveTX, tooEarlyRedemption), setOf(corpWalletTX, alicesWalletTX)).verify()
         }
         assertTrue(e.cause!!.message!!.contains("paper must have matured"))
 
-        TransactionGroup(setOf(issueTX, moveTX, validRedemption), setOf(corpWalletTX, alicesWalletTX)).verify(MockContractFactory)
+        TransactionGroup(setOf(issueTX, moveTX, validRedemption), setOf(corpWalletTX, alicesWalletTX)).verify()
     }
 
     // Generate a trade lifecycle with various parameters.
diff --git a/src/test/kotlin/contracts/CrowdFundTests.kt b/src/test/kotlin/contracts/CrowdFundTests.kt
index e7dd5ed531..e734ae73a3 100644
--- a/src/test/kotlin/contracts/CrowdFundTests.kt
+++ b/src/test/kotlin/contracts/CrowdFundTests.kt
@@ -160,11 +160,11 @@ class CrowdFundTests {
         val validClose = makeFundedTX(TEST_TX_TIME + 8.days)
 
         val e = assertFailsWith(TransactionVerificationException::class) {
-            TransactionGroup(setOf(registerTX, pledgeTX, tooEarlyClose), setOf(miniCorpWalletTx, aliceWalletTX)).verify(MockContractFactory)
+            TransactionGroup(setOf(registerTX, pledgeTX, tooEarlyClose), setOf(miniCorpWalletTx, aliceWalletTX)).verify()
         }
         assertTrue(e.cause!!.message!!.contains("the closing date has past"))
 
         // This verification passes
-        TransactionGroup(setOf(registerTX, pledgeTX, validClose), setOf(aliceWalletTX)).verify(MockContractFactory)
+        TransactionGroup(setOf(registerTX, pledgeTX, validClose), setOf(aliceWalletTX)).verify()
     }
 }
\ No newline at end of file
diff --git a/src/test/kotlin/core/MockServices.kt b/src/test/kotlin/core/MockServices.kt
index 43f0f500aa..bace9ab1be 100644
--- a/src/test/kotlin/core/MockServices.kt
+++ b/src/test/kotlin/core/MockServices.kt
@@ -116,15 +116,7 @@ class MockAttachmentStorage : AttachmentStorage {
 }
 
 @ThreadSafe
-class MockStorageService : StorageServiceImpl(MockAttachmentStorage(), MockContractFactory, generateKeyPair()) {
-}
-
-object MockContractFactory : ContractFactory {
-    override operator fun <T : Contract> get(hash: SecureHash): T {
-        val clazz = TEST_PROGRAM_MAP[hash] ?: throw UnknownContractException()
-        @Suppress("UNCHECKED_CAST")
-        return clazz.newInstance() as T
-    }
+class MockStorageService : StorageServiceImpl(MockAttachmentStorage(), generateKeyPair()) {
 }
 
 class MockServices(
diff --git a/src/test/kotlin/core/TransactionGroupTests.kt b/src/test/kotlin/core/TransactionGroupTests.kt
index 81746777eb..730e9873ea 100644
--- a/src/test/kotlin/core/TransactionGroupTests.kt
+++ b/src/test/kotlin/core/TransactionGroupTests.kt
@@ -153,6 +153,6 @@ class TransactionGroupTests {
 
         // Now go through the conversion -> verification path with them.
         val ltxns = signedTxns.map { it.verifyToLedgerTransaction(MockIdentityService, MockStorageService().attachments) }.toSet()
-        TransactionGroup(ltxns, emptySet()).verify(MockContractFactory)
+        TransactionGroup(ltxns, emptySet()).verify()
     }
 }
\ No newline at end of file
diff --git a/src/test/kotlin/core/messaging/TwoPartyTradeProtocolTests.kt b/src/test/kotlin/core/messaging/TwoPartyTradeProtocolTests.kt
index cba57e831d..955cefc1de 100644
--- a/src/test/kotlin/core/messaging/TwoPartyTradeProtocolTests.kt
+++ b/src/test/kotlin/core/messaging/TwoPartyTradeProtocolTests.kt
@@ -195,10 +195,9 @@ class TwoPartyTradeProtocolTests : TestWithInMemoryNetwork() {
         return net.createNode(null) { path, config, net, tsNode ->
             object : MockNetwork.MockNode(path, config, net, tsNode) {
                 // That constructs the storage service object in a customised way ...
-                override fun constructStorageService(attachments: NodeAttachmentService, keypair: KeyPair, identity: Party,
-                                                     contractFactory: ContractFactory): StorageServiceImpl {
+                override fun constructStorageService(attachments: NodeAttachmentService, keypair: KeyPair, identity: Party): StorageServiceImpl {
                     // To use RecordingMaps instead of ordinary HashMaps.
-                    return StorageServiceImpl(attachments, contractFactory, keypair, identity, { tableName -> name })
+                    return StorageServiceImpl(attachments, keypair, identity, { tableName -> name })
                 }
             }
         }
diff --git a/src/test/kotlin/core/node/ClassLoaderTests.kt b/src/test/kotlin/core/node/ClassLoaderTests.kt
index 1c10317dc3..c09acc2e11 100644
--- a/src/test/kotlin/core/node/ClassLoaderTests.kt
+++ b/src/test/kotlin/core/node/ClassLoaderTests.kt
@@ -173,4 +173,9 @@ class ClassLoaderTests {
         assertNotNull(state2)
     }
 
+    @Test
+    fun `white list serialization`() {
+
+    }
+
 }
\ No newline at end of file
diff --git a/src/test/kotlin/core/testutils/TestUtils.kt b/src/test/kotlin/core/testutils/TestUtils.kt
index 68aac26d83..d2d67402be 100644
--- a/src/test/kotlin/core/testutils/TestUtils.kt
+++ b/src/test/kotlin/core/testutils/TestUtils.kt
@@ -74,7 +74,7 @@ val TEST_KEYS_TO_CORP_MAP: Map<PublicKey, Party> = mapOf(
 
 // In a real system this would be a persistent map of hash to bytecode and we'd instantiate the object as needed inside
 // a sandbox. For unit tests we just have a hard-coded list.
-val TEST_PROGRAM_MAP: Map<SecureHash, Class<out Contract>> = mapOf(
+val TEST_PROGRAM_MAP: Map<Contract, Class<out Contract>> = mapOf(
         CASH_PROGRAM_ID to Cash::class.java,
         CP_PROGRAM_ID to CommercialPaper::class.java,
         JavaCommercialPaper.JCP_PROGRAM_ID to JavaCommercialPaper::class.java,
@@ -162,7 +162,7 @@ open class TransactionForTest : AbstractTransactionForTest() {
     protected fun run(time: Instant) {
         val cmds = commandsToAuthenticatedObjects()
         val tx = TransactionForVerification(inStates, outStates.map { it.state }, emptyList(), cmds, SecureHash.randomSHA256())
-        tx.verify(MockContractFactory)
+        tx.verify()
     }
 
     fun accepts(time: Instant = TEST_TX_TIME) = run(time)
@@ -319,7 +319,7 @@ class TransactionGroupDSL<T : ContractState>(private val stateType: Class<T>) {
     fun verify() {
         val group = toTransactionGroup()
         try {
-            group.verify(MockContractFactory)
+            group.verify()
         } catch (e: TransactionVerificationException) {
             // Let the developer know the index of the transaction that failed.
             val wtx: WireTransaction = txns.find { it.id == e.tx.origHash }!!