-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Legend:
🔴: High priority.
🟡: Medium priority.
🟢: Low priority.
🔵: Discussion.
General
- 🟢 Since the TPC-C methods are overloaded based on their parameter types (string or strongly typed/parsed object), a more explicit separation of such methods would make sense. Accordingly, the current
TPCCclass could be namedTPCCContractAPI(orTpccContractApi, not sure about the commonly used casing), and the strongly typed methods could be extracted into aTpccBusinessApiclass, which now deals purely with business-level objects, not Fabric API-enforced strings.
Line 49 in 385c149
public final class TPCC implements ContractInterface { - 🟢 The following and similar nested statements should be split into multiple statements using variable assignments, so it's easier to read (and would facilitate step-by-step debugging if we could set that up 😄).
Line 76 in 385c149
JSON.serialize(this.delivery(ctx, JSON.deserialize(parameters, DeliveryInput.class)));
Delivery
- 🟡 The name of the
getOldestNewOrderForDistrictmethod is misleading. It doesn't return the oldest new order, but actually "performs" the delivery. It should either be renamed to something likedeliverOldestNewOrderForDistrictto reflect its functionality or its contents should be inlined into the shortdeliverymethod, except for thegetOldestNewOrderfunctionality (just like in the JS version) since that's the "abstraction border" between the business-level and registry-level functionality.
Line 349 in 385c149
this.getOldestNewOrderForDistrict( - 🔴 🔵 If I understand correctly, the
selectimplementation now reads every entry of a given type, then it's filtered inside the chaincode usingmatching:
Line 1201 in 385c149
.select(ctx, new NewOrder())
This is really wasteful if it works that way and could cause a lot of MVCC conflicts. The originalselectsupported a partial iterator and early-break functionality for such scenarios (we only need the first/earliest new order of a given warehouse and district). The implementation is functionally correct, but not robust enough extra-functionally. - 🟡 The
getOrderLineAmountfunction also does more than its name suggests:
Line 1264 in 385c149
this.getOrderLineAmount(ctx, w_id, d_id, order.getO_id(), i, ol_delivery_d);
New Order
- 🟡 I find single-statement for/if/etc blocks without curly brackets really error-prone. We should always use them for clarity, and in the name of defensive programming. The following is just an example
Line 490 in 119b79f
for (int i = 0; i < input.getI_ids().length; ++i)
Lines 1446 to 1447 in 119b79f
if (stock.getS_quantity() >= i_qty + 10) stock.decreaseQuantity(i_qty); else stock.setS_quantity(stock.getS_quantity() - i_qty + 91); - 🔴 The existence of a referenced item must be checked (i.e., the exception handled) because it determines the return value of the transaction.
Line 1427 in 119b79f
registry.read(ctx, item);
See here:
blockchain-benchmarks-tpcc/smart-contract/hyperledger-fabric/v1/javascript/lib/tpcc.js
Line 287 in 119b79f
if (!item) { - 🔴 The
dist_infoattribute must be assigned the value of the requireds_dist_xxattribute from theStockinstance.
Line 1504 in 119b79f
.dist_info(padDistrictInfo("s_dist_" + stockDistrictId))
See here:
blockchain-benchmarks-tpcc/smart-contract/hyperledger-fabric/v1/javascript/lib/tpcc.js
Line 361 in 119b79f
ol_dist_info: stock[`s_dist_${stockDistrictId}`]
Order Status
- 🟡 Single statement blocks without curly braces:
Lines 1568 to 1569 in 119b79f
if (c_id == null && c_last == null) throw new IllegalArgumentException("At least one of c_id and c_last must be specified");
Lines 1583 to 1584 in 119b79f
for (final Customer c : allCustomers) if (c.getC_last().equals(c_last)) matchingCustomers.add(c);
Lines 1585 to 1586 in 119b79f
if (matchingCustomers.isEmpty()) throw new NotFoundException("Customer matching last name '%s' not found".formatted(c_last));
Line 1589 in 119b79f
if (N > Integer.MAX_VALUE) logger.warn("Size of matching CUSTOMER list is out of range");
Line 1617 in 119b79f
if (allOrders.isEmpty()) throw new NotFoundException("No orders found");
Line 1621 in 119b79f
for (final Order o : allOrders) if (o.getO_c_id() == o_c_id) matchingOrders.add(o);
Lines 1622 to 1623 in 119b79f
if (matchingOrders.isEmpty()) throw new NotFoundException("Could not find last order of customer"); - 🔴 Sorting by customer first name is missing:
Line 1588 in 119b79f
final double N = Math.ceil(matchingCustomers.size() / 2d);
See here:
blockchain-benchmarks-tpcc/smart-contract/hyperledger-fabric/v1/javascript/lib/ledgerUtils.js
Line 347 in 119b79f
customerList.sort((c1, c2) => c1.c_first.localeCompare(c2.c_first));
Payment
LGTM
Stock Level
- 🟢 The minimum constraint should be propagated back to the JS implementation to make it more robust:
blockchain-benchmarks-tpcc/smart-contract/hyperledger-fabric/v1/javascript/lib/tpcc.js
Line 637 in 119b79f
const o_id_min = district.d_next_o_id - 20; - 🟡 Single statement block without curly braces:
Line 1677 in 119b79f
if (itemIds.isEmpty()) throw new NotFoundException("Could not find item IDs of recent ORDERs");
Other components
TBD