Skip to content

Commit 4ba4cc1

Browse files
committed
Rebasing on top of master, addressing review comments
Signed-off-by: prakashngit <[email protected]>
1 parent 08fd54d commit 4ba4cc1

File tree

10 files changed

+36
-54
lines changed

10 files changed

+36
-54
lines changed

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@ PDO uses a distributed ledger, in this case the
1616
[Hyperledger Sawtooth](https://sawtooth.hyperledger.org/)
1717
distributed ledger, to ensure that there is a single, authoritative
1818
instance of the object, and to provide a means of guaranteeing atomicity of
19-
updates across interacting objects. There is also ongoing efforts to support
20-
[Microsoft Confidential Consortium Framework (CCF)](https://microsoft.github.io/CCF/) based ledger.
21-
PDO performs contract execution and storage off the blockchain, with only a hash of
19+
updates across interacting objects. PDO performs contract execution and storage off the blockchain, with only a hash of
2220
blockchain state stored on the distributed ledger.
2321

22+
There is also an ongoing experimental effort to add support for
23+
[Microsoft Confidential Consortium Framework (CCF)](https://microsoft.github.io/CCF/) based ledger.
24+
Currently, the PDO/CCF combo is restricted to virtual enclaves, and lacks docker as well as
25+
automated test support.
26+
2427
PDO provides benefits for both application developers seeking to define and
2528
implement privacy-preserving distributed ledgers, and for service providers
2629
seeking to provide blockchain services.

build/__tools__/run-tests.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ function cleanup {
5454

5555
trap cleanup EXIT
5656

57-
5857
# -----------------------------------------------------------------
5958
yell run unit tests for python, common, contracts and eservice
6059
# -----------------------------------------------------------------

ccf_transaction_processor/Readme.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ The TP must viewed as a CCF application. Documentation for building and deployin
1414
can be found at https://microsoft.github.io/CCF/. The CCF legder that stores the PDO TP registries is
1515
encrypted, and is accessible only within CCF encalves. Currently PDO/CCF combination is supported
1616
only under the virtual enclave mode for both PDO and CCF. (set env variable SGX_MODE=SIM for PDO &
17-
set cmake flag TARGET=virtual for ccf). Support for HW mode for both PDO and CCF will be added soon.
17+
set cmake flag TARGET=virtual for ccf). Support for HW mode for both PDO and CCF will be added soon. Further,
18+
the current implementation of PDO TP hasn't been tested under multi-threaded CCF enclaves.(CCF 0.7.1 offers initial support for multi-threading). It is recommended that the application is deployed with single worker thread per enclave. Please see https://microsoft.github.io/CCF/developers/threading.html for instructions.
1819

1920
CCF uses mutually authenticated TLS channels for transactions. Given that in PDO client authentication is implemented within the transaction processor itself, we do not utilize the client authentication feature provided by CCF. Once CCF is deployed, CCF's network certificate (networkcert.pem) and one set of user keys (userccf_cert.pem & userccf_privk.pem)
2021
must be made available to all PDO processes that want to submit a CCF transaction. In this case, every
@@ -26,12 +27,7 @@ As far as PDO is concerned, CCF based TP is functionally identical to the Sawtoo
2627
TP (except for one additional feature described below). A key difference beween the two ledgers
2728
is the fact that while the ledger in CCF is encrypted as noted above, the ledger is Sawtooth is stored in plain text.
2829
Even though the no part of conract state gets stored in the ledger in both CCF & Sawtooth, encrypting the
29-
ledger as in CCF helps to hide transaction patterns that are otherwise visible in Sawtooth ledger. Detailed documentation
30-
about Sawtooth based TP can be found at $PDO_SRC/sawtooth/docs. The schema for JSON payloads used to submit
31-
CCF transactions can be found at
32-
[${PDO_SRC}/python/pdo/submitter/ccf/docs/](../python/pdo/submitter/ccf/docs/ccf_payload_schema.json).
33-
For additional references to documentation about PDO, including transaction processor protocols,
34-
see [${PDO_SRC}/README.md](../README.md)
30+
ledger as in CCF helps to hide transaction patterns that are otherwise visible in Sawtooth ledger. Detailed documentation about Sawtooth based TP can be found at $PDO_SRC/sawtooth/docs. The schema for JSON payloads used to submit CCF transactions can be found at [${PDO_SRC}/python/pdo/submitter/ccf/docs/](../python/pdo/submitter/ccf/docs/ccf_payload_schema.json). For additional references to documentation about PDO, including transaction processor protocols, see [${PDO_SRC}/README.md](../README.md)
3531

3632
A feature of the CCF based TP that is not supported by Sawtooth based TP is the fact that
3733
responses to read-transactions include a payload signature, where the signature is generated by the CCF enclave

ccf_transaction_processor/transaction_processor/ccl_registry.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ namespace ccf
8989
vector<uint8_t> contract_enclave_signature;
9090
vector<uint8_t> signature;
9191
vector<uint8_t> nonce;
92-
string verifying_key; // for the pdo_signature
9392
string state_update_info; //json string
9493
};
9594

@@ -126,7 +125,7 @@ namespace ccf
126125
// check input complies with schema
127126
DECLARE_JSON_TYPE(Update_contract_state::In);
128127
DECLARE_JSON_REQUIRED_FIELDS(Update_contract_state::In, verb, contract_enclave_id, \
129-
contract_enclave_signature, signature, nonce, verifying_key, state_update_info);
128+
contract_enclave_signature, signature, nonce, state_update_info);
130129

131130
DECLARE_JSON_TYPE(Get_current_state_info::In);
132131
DECLARE_JSON_REQUIRED_FIELDS(Get_current_state_info::In, contract_id);

ccf_transaction_processor/transaction_processor/contract_registry.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ namespace ccf
4747
string contract_enclave_id;
4848
string contract_id;
4949
string encrypted_state_encryption_key;
50-
string signature;
50+
string signature; // this is the enclave signature for the add enclave to contract transaction
5151
std::vector<ProvisioningKeysToSecretMap> provisioning_key_state_secret_pairs;
5252

5353
MSGPACK_DEFINE(contract_enclave_id, contract_id, encrypted_state_encryption_key, signature, provisioning_key_state_secret_pairs);
@@ -100,7 +100,6 @@ namespace ccf
100100
struct Add_enclave {
101101
struct In {
102102
string contract_id;
103-
string contract_creator_verifying_key_PEM;
104103
string enclave_info; //json string
105104
std::vector<uint8_t> signature;
106105
};
@@ -128,7 +127,7 @@ namespace ccf
128127
signature, contract_id, provisioning_service_ids);
129128

130129
DECLARE_JSON_TYPE(Add_enclave::In);
131-
DECLARE_JSON_REQUIRED_FIELDS(Add_enclave::In, contract_id, contract_creator_verifying_key_PEM, \
130+
DECLARE_JSON_REQUIRED_FIELDS(Add_enclave::In, contract_id, \
132131
enclave_info, signature);
133132

134133
DECLARE_JSON_TYPE(Verify_contract::In);

ccf_transaction_processor/transaction_processor/enclave_registry.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ namespace ccf
5454

5555
struct Verify_enclave {
5656
struct In {
57-
string verifying_key; //enclave_id
57+
string enclave_id; //enclave_id
5858
};
5959

6060
struct Out {
@@ -72,7 +72,7 @@ namespace ccf
7272
registration_block_context, organizational_info, EHS_verifying_key, signature);
7373

7474
DECLARE_JSON_TYPE(Verify_enclave::In);
75-
DECLARE_JSON_REQUIRED_FIELDS(Verify_enclave::In, verifying_key);
75+
DECLARE_JSON_REQUIRED_FIELDS(Verify_enclave::In, enclave_id);
7676

7777
DECLARE_JSON_TYPE(Verify_enclave::Out);
7878
DECLARE_JSON_REQUIRED_FIELDS(Verify_enclave::Out, verifying_key, encryption_key, proof_data, last_registration_block_context, \

ccf_transaction_processor/transaction_processor/pdo_tp.cpp

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ namespace ccfapp
2525

2626
TPHandler::TPHandler(Store& store):
2727
UserHandlerRegistry(store),
28-
enclavetable(store.create<string, EnclaveInfo>("encalves")),
28+
enclavetable(store.create<string, EnclaveInfo>("enclaves")),
2929
contracttable(store.create<string, ContractInfo>("contracts")),
3030
ccltable(store.create<string, ContractStateInfo>("ccl_updates")),
3131
signer(store.create<string, map<string, string>>("signer"))
@@ -71,10 +71,11 @@ namespace ccfapp
7171

7272
auto signer_local = signer_view->get("signer");
7373
try{
74+
// if local signer exists, it means that we are waiting for global commit of the signer.
75+
// The signer is not used until it gets globally committed.
7476
if (!signer_local.has_value()){
7577
// create the key, done only the first time this rpc is called
76-
auto curve = CurveImpl::secp256k1_mbedtls;
77-
auto kp = make_key_pair(curve);
78+
auto kp = make_key_pair(CurveImpl::secp256k1_mbedtls);
7879
auto privk_pem = kp->private_key_pem();
7980
auto pubk_pem = kp->public_key_pem();
8081
map<string, string> key_pair;
@@ -153,10 +154,10 @@ namespace ccfapp
153154
const auto in = params.get<Register_contract::In>();
154155

155156
// Capture the current view
156-
auto view = tx.get_view(contracttable);
157+
auto contract_view = tx.get_view(contracttable);
157158

158159
// Check if enclave was previously registered
159-
auto contract_r = view->get(in.contract_id);
160+
auto contract_r = contract_view->get(in.contract_id);
160161
if (contract_r.has_value())
161162
{
162163
return make_error(
@@ -186,7 +187,7 @@ namespace ccfapp
186187
}
187188

188189
//store the data
189-
view->put(in.contract_id, new_contract);
190+
contract_view->put(in.contract_id, new_contract);
190191

191192
// No need to commit the Tx, this is automatically taken care of !
192193

@@ -211,14 +212,8 @@ namespace ccfapp
211212
}
212213
auto contract_info = contract_r.value();
213214

214-
//ensure the contract owner is the one adding enclaves to contract
215-
if (in.contract_creator_verifying_key_PEM != contract_info.contract_creator_verifying_key_PEM){
216-
return make_error(
217-
jsonrpc::StandardErrorCodes::INVALID_PARAMS, "Enclave can only be added by the contract owner");
218-
}
219-
220-
// Verify Pdo transaction signature
221-
if (!verify_pdo_transaction_signature_add_enclave(in.signature, in.contract_creator_verifying_key_PEM, \
215+
// Verify Pdo transaction signature (ensures that the contract ownder is the one adding encalves)
216+
if (!verify_pdo_transaction_signature_add_enclave(in.signature, contract_info.contract_creator_verifying_key_PEM, \
222217
in.contract_id, in.enclave_info)){
223218
return make_error(
224219
jsonrpc::StandardErrorCodes::INVALID_PARAMS, "Invalid PDO payload signature");
@@ -272,12 +267,12 @@ namespace ccfapp
272267
// To Do: This signature verification does not work. The following function returns "true" until this is fixed
273268
// see git issues for status
274269
if (!verify_enclave_signature_add_enclave(enclave_info_temp.signature, this->enclave_pubk_verifier[enclave_r.value().verifying_key], \
275-
in.contract_creator_verifying_key_PEM, in.contract_id, enclave_info_temp.provisioning_key_state_secret_pairs, \
270+
contract_info.contract_creator_verifying_key_PEM, in.contract_id, enclave_info_temp.provisioning_key_state_secret_pairs, \
276271
enclave_info_temp.encrypted_state_encryption_key)){
277272

278273
// the following code is to aid in debugging the signature verification issue.
279274
string message = in.contract_id;
280-
message += in.contract_creator_verifying_key_PEM;
275+
message += contract_info.contract_creator_verifying_key_PEM;
281276
for (auto prov :enclave_info_temp.provisioning_key_state_secret_pairs ) {
282277
message += prov.pspk;
283278
message += prov.encrypted_secret;
@@ -375,12 +370,8 @@ namespace ccfapp
375370
jsonrpc::StandardErrorCodes::INVALID_PARAMS, "Init operation must not have CCL dependeices from other contracts");
376371
}
377372

378-
if (in.verifying_key != contract_info.contract_creator_verifying_key_PEM){
379-
return make_error(
380-
jsonrpc::StandardErrorCodes::INVALID_PARAMS, "Init operation can only be performed by the contract creator");
381-
}
382-
383-
if (!verify_pdo_transaction_signature_update_contract_state(in.signature, in.verifying_key, \
373+
// sign check ensures that Init operation can only be performed by the contract creator
374+
if (!verify_pdo_transaction_signature_update_contract_state(in.signature, contract_info.contract_creator_verifying_key_PEM, \
384375
in.contract_enclave_id, in.contract_enclave_signature, in.state_update_info)){
385376
return make_error(
386377
jsonrpc::StandardErrorCodes::INVALID_PARAMS, "Invalid PDO payload signature");
@@ -417,8 +408,8 @@ namespace ccfapp
417408
jsonrpc::StandardErrorCodes::INVALID_PARAMS, "Update verb must be either init or update");
418409
}
419410

420-
// verify contract enclave signature
421-
411+
// verify contract enclave signature. This signature also ensures (via the notion of channel ids) that
412+
// the contraction invocation was performed by the transaction submitter.
422413
if (!verify_enclave_signature_update_contract_state(in.contract_enclave_signature, this->enclave_pubk_verifier[enclave_r.value().verifying_key], \
423414
in.nonce, contract_info.contract_creator_verifying_key_PEM, contract_info.contract_code_hash, \
424415
state_update_info)) {
@@ -451,7 +442,7 @@ namespace ccfapp
451442
auto verify_enclave = [this](Store::Tx& tx, const nlohmann::json& params) {
452443
const auto in = params.get<Verify_enclave::In>();
453444
auto enclave_view = tx.get_view(enclavetable);
454-
auto enclave_r = enclave_view->get_globally_committed(in.verifying_key);
445+
auto enclave_r = enclave_view->get_globally_committed(in.enclave_id);
455446

456447
if (enclave_r.has_value())
457448
{
@@ -464,14 +455,14 @@ namespace ccfapp
464455
}
465456

466457
string doc_to_sign;
467-
doc_to_sign += in.verifying_key;
458+
doc_to_sign += in.enclave_id;
468459
doc_to_sign += enclave_r.value().encryption_key;
469460
doc_to_sign += enclave_r.value().proof_data;
470461
doc_to_sign += enclave_r.value().registration_block_context;
471462
doc_to_sign += enclave_r.value().EHS_verifying_key;
472463
auto signature = TPHandler::sign_document(doc_to_sign);
473464

474-
return make_success(Verify_enclave::Out{in.verifying_key, enclave_r.value().encryption_key, \
465+
return make_success(Verify_enclave::Out{in.enclave_id, enclave_r.value().encryption_key, \
475466
enclave_r.value().proof_data, enclave_r.value().registration_block_context, \
476467
enclave_r.value().EHS_verifying_key, signature});
477468
}

ccf_transaction_processor/transaction_processor/pdo_tp.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ namespace ccfapp
4949
static constexpr auto ADD_ENCLAVE_TO_CONTRACT ="add_enclave_to_contract";
5050
static constexpr auto UPDATE_CONTRACT_STATE ="ccl_update";
5151

52-
5352
//methods that read the tables, used by PDO to verify write transactions
5453
static constexpr auto VERIFY_ENCLAVE_REGISTRATION = "verify_enclave_registration";
5554
static constexpr auto VERIFY_CONTRACT_REGISTRATION = "verify_contract_registration";
@@ -68,8 +67,8 @@ namespace ccfapp
6867
Store::Map<string, EnclaveInfo>& enclavetable; // key is encalve_id
6968
Store::Map<string, ContractInfo>& contracttable; // key is contract_id
7069
Store::Map<string, ContractStateInfo>& ccltable; // key is contract_id + state_hash (string addition)
71-
Store::Map<string, map<string, string>>& signer; //key string indicates if signer has been initialized or not
72-
// value is pubk: & privk:
70+
Store::Map<string, map<string, string>>& signer; //There is at most one entry in this map. if there is an
71+
//entry key="signer". value is pubk: & privk:
7372

7473
// functions to verify signatures, only wite methods sign transactions, read methods do not.
7574
bool verify_pdo_transaction_signature_register_enclave(const vector<uint8_t>& signature, const string & verifying_key,

python/pdo/contract/state.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,6 @@ def get_current_state_hash(ledger_config, contract_id) :
247247
logger.info('error getting state hash; %s', str(e))
248248
raise Exception('failed to retrieve contract state hash; {}'.format(contract_id))
249249

250-
return current_state_hash
251-
252250
# --------------------------------------------------
253251
@classmethod
254252
def get_from_ledger(cls, ledger_config, contract_id, current_state_hash = None) :

python/pdo/submitter/ccf/ccf_submitter.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -450,9 +450,9 @@ def build_enclave_registration_from_data(
450450

451451
# -----------------------------------------------------------------
452452
@staticmethod
453-
def build_verify_enclave_from_data(verifying_key):
453+
def build_verify_enclave_from_data(enclave_id):
454454
payloadblob = dict()
455-
payloadblob['verifying_key'] = verifying_key
455+
payloadblob['enclave_id'] = enclave_id
456456
# there is no need to sign these verification transactions
457457
return payloadblob
458458

@@ -509,7 +509,6 @@ def build_add_enclave_to_contract_from_data(
509509
payloadblob = dict()
510510
payloadblob['contract_id'] = contract_id
511511
payloadblob['enclave_info'] = json.dumps(enclave_info_quintuples, sort_keys=True)
512-
payloadblob['contract_creator_verifying_key_PEM'] = contract_creator_keys.verifying_key
513512

514513
# sign the payload after adding a nonce
515514
payloadblob['signature'] = compute_pdo_add_enclave_signature(contract_creator_keys.signing_key,
@@ -546,7 +545,6 @@ def build_initialize_contract_state_transaction_from_data(
546545
state_update_info['dependency_list'] = dependency_list
547546
state_update_info_string = json.dumps(state_update_info, sort_keys=True)
548547
payloadblob['state_update_info'] = state_update_info_string
549-
payloadblob['verifying_key'] = verifying_key
550548
payloadblob['nonce'] = nonce
551549
payloadblob['signature'] = compute_pdo_update_contract_state_signature(signing_key, verifying_key, contract_enclave_id, \
552550
contract_enclave_signature, state_update_info_string)

0 commit comments

Comments
 (0)