Skip to content

Commit 545cfdc

Browse files
committed
update tutorial to match code
1 parent 01c4fe6 commit 545cfdc

File tree

1 file changed

+58
-52
lines changed

1 file changed

+58
-52
lines changed

docs/tutorial_start_here.md

Lines changed: 58 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
# Marbles - Demo
22

3-
*Note these docs are under active development*
4-
The instructions are not yet 100% compelte, but knock yourself out and give it a go. 3/23/2017
5-
63
## About Marbles
74
- The underlying network for this application is the [Hyperledger Fabric](https://github.com/hyperledger/fabric/tree/master/docs), a Linux Foundation project. You may want to review these instructions to understand a bit about the Hyperledger Fabric.
85
- **This demo is to aid a developer learn the basics of chaincode and app development with a Hyperledger network.**
@@ -34,14 +31,14 @@ Thus, we will stringify JSON objects to store more complex structures.
3431

3532
Attributes of a marble:
3633

37-
1. name (unique string, will be used as key)
34+
1. id (unique string, will be used as key)
3835
1. color (string, css color names)
3936
1. size (int, size in mm)
4037
1. owner (string)
4138

4239
We are going to create a Web based UI that can set these values and store them in our blockchain.
4340
The marble gets created in the blockchain storage aka ledger as a key value pair.
44-
The `key` is the marble name, and the `value` is a JSON string containing the attributes of the marble (listed above).
41+
The `key` is the marble id, and the `value` is a JSON string containing the attributes of the marble (listed above).
4542
Interacting with the cc is done by using the gRPC protocol to a peer on the network.
4643
The details of the gRPC protocol are taken care of by an SDK called [Hyperledger Fabric Client](https://www.npmjs.com/package/fabric-client) SDK.
4744
Check the picture below for topology details.
@@ -246,24 +243,33 @@ enrollment.enroll = function (options, cb) {
246243
client.setStateStore(store);
247244

248245
// [Step 3]
249-
return getSubmitter(client, options); //do most of the work here
246+
return getSubmitter(client, options); //do most of the work here
250247
}).then(function (submitter) {
251248

252249
// [Step 4]
253-
chain.addOrderer(new Orderer(options.orderer_url));
250+
chain.addOrderer(new Orderer(options.orderer_url, {
251+
pem: options.pem,
252+
'ssl-target-name-override': options.common_name //can be null if cert matches hostname
253+
}));
254254

255255
// [Step 5]
256256
try {
257257
for (var i in options.peer_urls) {
258-
chain.addPeer(new Peer(options.peer_urls[i]));
258+
chain.addPeer(new Peer(options.peer_urls[i], {
259+
pem: options.pem,
260+
'ssl-target-name-override': options.common_name
261+
}));
259262
logger.debug('added peer', options.peer_urls[i]);
260263
}
261264
}
262265
catch (e) {
263266
//might error if peer already exists, but we don't care
264267
}
265268
try {
266-
chain.setPrimaryPeer(new Peer(options.peer_urls[0]));
269+
chain.setPrimaryPeer(new Peer(options.peer_urls[0], {
270+
pem: options.pem,
271+
'ssl-target-name-override': options.common_name
272+
}));
267273
logger.debug('added primary peer', options.peer_urls[0]);
268274
}
269275
catch (e) {
@@ -293,6 +299,7 @@ enrollment.enroll = function (options, cb) {
293299
1. Next we create a key value store to store the enrollment certifcates with `newDefaultKeyValueStore`
294300
1. Next we enroll our admin. This is when we authenticate to the CA with our enroll ID and enroll secret. The CA will issue enrollment certificates which the SDK will store in the key value store. Since we are using the default key value store, it will be stored in our local file system.
295301
1. After successful enrollment we set the orderer URL. The orderer is not needed yet, but will be when we try to invoke chaincode.
302+
- The bussiness with `ssl-target-name-override` is only needed if you have self signed certificates. Set this field equal to the `common name` you used to create the PEM file.
296303
1. Next we set the Peer URLs. These are also not needed yet, but we are going to setup our SDK chain object fully.
297304
1. At this point the SDK is fully configured and ready to interact with the blockchain.
298305

@@ -305,7 +312,7 @@ __/chaincode/marbles.go__
305312
```go
306313
type Marble struct {
307314
ObjectType string `json:"docType"`
308-
Name string `json:"name"` //the fieldtags are needed to keep case from bouncing around
315+
Id string `json:"id"`
309316
Color string `json:"color"`
310317
Size int `json:"size"`
311318
Owner OwnerRelation `json:"owner"`
@@ -315,22 +322,17 @@ __/chaincode/marbles.go__
315322
__/chaincode/write_ledger.go__
316323

317324
```go
318-
// ============================================================================================================================
319-
// Set Owner on Marble
320-
// ============================================================================================================================
321325
func set_owner(stub shim.ChaincodeStubInterface, args []string) pb.Response {
322326
var err error
323327
fmt.Println("starting set_owner")
324328

325-
//todo! dsh - get the "company that authed the transfer" from the certificate instead of an argument
326-
//should be possible since we can now add attributes to tx cert during
327-
//as is this is broken (security wise), but it's much easier to demo...
329+
// this is quirky
330+
// todo - get the "company that authed the transfer" from the certificate instead of an argument
331+
// should be possible since we can now add attributes to the enrollment cert
332+
// as is.. this is a bit broken (security wise), but it's much much easier to demo! holding off for demos sake
328333

329-
// 0 , 1 , 2 3
330-
// marble, to user, to company, company that auth the transfer
331-
// "name", "bob", "united_marbles", "united_mables"
332-
if len(args) < 4 {
333-
return shim.Error("Incorrect number of arguments. Expecting 4")
334+
if len(args) != 3 {
335+
return shim.Error("Incorrect number of arguments. Expecting 3")
334336
}
335337

336338
// input sanitation
@@ -340,29 +342,35 @@ __/chaincode/write_ledger.go__
340342
}
341343

342344
var marble_id = args[0]
343-
var new_user = strings.ToLower(args[1])
344-
var new_company = args[2]
345-
var authed_by_company = args[3]
346-
fmt.Println(marble_id + "->" + new_user + " - " + new_company + "|" + authed_by_company)
345+
var new_owner_id = args[1]
346+
var authed_by_company = args[2]
347+
fmt.Println(marble_id + "->" + new_owner_id + " - |" + authed_by_company)
348+
349+
// check if user already exists
350+
owner, err := get_owner(stub, new_owner_id)
351+
if err != nil {
352+
return shim.Error("This owner does not exist - " + new_owner_id)
353+
}
347354

348-
// get marble's current state
355+
// get marble's current state
349356
marbleAsBytes, err := stub.GetState(marble_id)
350357
if err != nil {
351358
return shim.Error("Failed to get marble")
352359
}
353360
res := Marble{}
354-
json.Unmarshal(marbleAsBytes, &res) //un stringify it aka JSON.parse()
361+
json.Unmarshal(marbleAsBytes, &res) //un stringify it aka JSON.parse()
355362

356-
//check authorizing company
363+
// check authorizing company
357364
if res.Owner.Company != authed_by_company{
358365
return shim.Error("The company '" + authed_by_company + "' cannot authorize transfers for '" + res.Owner.Company + "'.")
359366
}
360367

361-
//transfer the marble
362-
res.Owner.Username = new_user //change the owner
363-
res.Owner.Company = new_company //change the owner
364-
jsonAsBytes, _ := json.Marshal(res)
365-
err = stub.PutState(args[0], jsonAsBytes) //rewrite the marble with id as key
368+
// transfer the marble
369+
res.Owner.Id = new_owner_id //change the owner
370+
res.Owner.Username = owner.Username
371+
res.Owner.Company = owner.Company
372+
jsonAsBytes, _ := json.Marshal(res) //convert to array of bytes
373+
err = stub.PutState(args[0], jsonAsBytes) //rewrite the marble with id as key
366374
if err != nil {
367375
return shim.Error(err.Error())
368376
}
@@ -374,10 +382,10 @@ __/chaincode/write_ledger.go__
374382

375383
This `set_owner()` function will change the owner of a particular marble.
376384
It takes in an array of strings input argument and returns `nil` if successful.
377-
Within the array the first index should have the name of the marble which is also the key in the key/value pair.
378-
We first need to retrieve the current marble struct.
385+
Within the array the first index should have the id of the marble which is also the key in the key/value pair.
386+
We first need to retrieve the current marble struct by using this id.
379387
This is done with `stub.GetState(marble_id)` and then unmarshal it into a marble structure with `json.Unmarshal(marbleAsBytes, &res)`.
380-
From there we can index into the structure with `res.Owner.Username` and overwrite the marble's owner with the new username and company.
388+
From there we can index into the structure with `res.Owner.Id` and overwrite the marble's owner with the new owners Id.
381389
Next we Marshal the structure back up so that we can use `stub.PutState()` to overwrite the marble with its new attributes.
382390

383391
Let’s take 1 step up and look at how this chaincode was called from our node.js app.
@@ -406,6 +414,7 @@ __/utils/websocket_server_side.js__
406414
size: data.size,
407415
marble_owner: data.username,
408416
owners_company: data.company,
417+
owner_id: data.owner_id,
409418
auth_company: process.env.marble_company,
410419
};
411420

@@ -419,9 +428,8 @@ __/utils/websocket_server_side.js__
419428
else if (data.type == 'transfer_marble') {
420429
logger.info('[ws] transfering req');
421430
options.args = {
422-
marble_id: data.name,
423-
marble_owner: data.username,
424-
owners_company: data.company,
431+
marble_id: data.id,
432+
owner_id: data.owner_id,
425433
auth_company: process.env.marble_company
426434
};
427435

@@ -461,10 +469,11 @@ __/utils/marbles_cc_lib.js__
461469
cc_function: 'set_owner',
462470
cc_args: [
463471
options.args.marble_id,
464-
options.args.marble_owner,
465-
options.args.owners_company,
472+
options.args.owner_id,
466473
options.args.auth_company
467-
]
474+
],
475+
pem: g_options.pem,
476+
common_name: g_options.common_name
468477
};
469478
fcw.invoke_chaincode(enrollObj, opts, cb);
470479
};
@@ -494,15 +503,13 @@ __/public/js/ui_building.js__
494503

495504
// ------------ Transfer Marble ------------ //
496505
else{
497-
var dragged_user = $(ui.draggable).attr('username').toLowerCase();
498-
var dropped_user = $(event.target).parents('.marblesWrap').attr('username').toLowerCase();
499-
var dropped_company = $(event.target).parents('.marblesWrap').attr('company');
506+
var dragged_owner_id = $(ui.draggable).attr('owner_id');
500507
var dropped_owner_id = $(event.target).parents('.marblesWrap').attr('owner_id');
501508

502-
console.log('dropped a marble', dragged_user, dropped_user, dropped_company);
503-
if(dragged_user != dropped_user){ //only transfer marbles that changed owners
504-
$(ui.draggable).addClass('invalid');
505-
transfer_marble(marble_id, dropped_user, dropped_company, dropped_owner_id);
509+
console.log('dropped a marble', dragged_owner_id, dropped_owner_id);
510+
if (dragged_owner_id != dropped_owner_id) {
511+
$(ui.draggable).addClass('invalid bounce');
512+
transfer_marble(marble_id, dropped_owner_id);
506513
return true;
507514
}
508515
}
@@ -515,9 +522,8 @@ __/public/js/ui_building.js__
515522
show_tx_step({ state: 'building_proposal' }, function () {
516523
var obj = {
517524
type: 'transfer_marble',
518-
name: marbleName,
519-
username: to_username,
520-
company: to_company,
525+
id: marbleId,
526+
owner_id: to_owner_id,
521527
v: 1
522528
};
523529
console.log(wsTxt + ' sending transfer marble msg', obj);

0 commit comments

Comments
 (0)