Skip to content

Commit 23316ab

Browse files
authored
Merge pull request #45 from VRamakrishna/main
Fabric Interop Node SDK Support for HTLC-based Asset Exchanges
2 parents 5e2dbc8 + aa0cb2c commit 23316ab

File tree

10 files changed

+1459
-158
lines changed

10 files changed

+1459
-158
lines changed

common/interop-protos/common/asset_locks.proto

+16-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ message AssetClaim {
1818
}
1919

2020
message AssetLockHTLC {
21-
bytes hash = 1;
21+
bytes hashBase64 = 1;
2222
uint64 expiryTimeSecs = 2;
2323
enum TimeSpec {
2424
EPOCH = 0;
@@ -28,7 +28,7 @@ message AssetLockHTLC {
2828
}
2929

3030
message AssetClaimHTLC {
31-
bytes hashPreimage = 1;
31+
bytes hashPreimageBase64 = 1;
3232
}
3333

3434
message AssetExchangeAgreement {
@@ -44,3 +44,17 @@ message FungibleAssetExchangeAgreement {
4444
string locker = 3;
4545
string recipient = 4;
4646
}
47+
48+
message AssetContractHTLC {
49+
string contractId = 1;
50+
AssetExchangeAgreement agreement = 2;
51+
AssetLockHTLC lock = 3;
52+
AssetClaimHTLC claim = 4;
53+
}
54+
55+
message FungibleAssetContractHTLC {
56+
string contractId = 1;
57+
FungibleAssetExchangeAgreement agreement = 2;
58+
AssetLockHTLC lock = 3;
59+
AssetClaimHTLC claim = 4;
60+
}

core/network/fabric-interop-cc/contracts/interop/manage_assets.go

+39-42
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ const(
4747
contractIdPrefix = "ContractId_" // prefix for the map, contractId --> asset-key
4848
)
4949

50+
// helper functions to log and return errors
51+
func logThenErrorf(format string, args ...interface{}) error {
52+
errorMsg := fmt.Sprintf(format, args...)
53+
log.Error(errorMsg)
54+
return errors.New(errorMsg)
55+
}
56+
5057
// function to generate a "SHA256" hash in base64 format for a given preimage
5158
func generateSHA256HashInBase64Form(preimage string) string {
5259
hasher := sha256.New()
@@ -68,9 +75,7 @@ func generateContractIdMapKey(contractId string) string {
6875
func generateAssetLockKeyAndContractId(ctx contractapi.TransactionContextInterface, assetAgreement *common.AssetExchangeAgreement) (string, string, error) {
6976
assetLockKey, err := ctx.GetStub().CreateCompositeKey("AssetExchangeContract", []string{assetAgreement.Type, assetAgreement.Id})
7077
if err != nil {
71-
errorMsg := fmt.Sprintf("error while creating composite key: %+v", err)
72-
log.Error(errorMsg)
73-
return "", "", errors.New(errorMsg)
78+
return "", "", logThenErrorf("error while creating composite key: %+v", err)
7479
}
7580

7681
contractId := generateSHA256HashInBase64Form(assetLockKey)
@@ -98,7 +103,7 @@ func (s *SmartContract) LockAsset(ctx contractapi.TransactionContextInterface, a
98103
return "", err
99104
}
100105
//display the requested asset agreement
101-
log.Info(fmt.Sprintf("assetExchangeAgreement: %+v\n", assetAgreement))
106+
log.Infof("assetExchangeAgreement: %+v\n", assetAgreement)
102107

103108
lockInfoHTLC := &common.AssetLockHTLC{}
104109
err = proto.Unmarshal([]byte(lockInfoBytes), lockInfoHTLC)
@@ -107,12 +112,10 @@ func (s *SmartContract) LockAsset(ctx contractapi.TransactionContextInterface, a
107112
return "", err
108113
}
109114
//display the passed lock information
110-
log.Info(fmt.Sprintf("lockInfoHTLC: %+v\n", lockInfoHTLC))
115+
log.Infof("lockInfoHTLC: %+v\n", lockInfoHTLC)
111116

112117
if lockInfoHTLC.TimeSpec != common.AssetLockHTLC_EPOCH {
113-
errorMsg := "only EPOCH time is supported at present"
114-
log.Error(errorMsg)
115-
return "", errors.New(errorMsg)
118+
return "", logThenErrorf("only EPOCH time is supported at present")
116119
}
117120

118121
assetLockKey, contractId, err := generateAssetLockKeyAndContractId(ctx, assetAgreement)
@@ -121,7 +124,7 @@ func (s *SmartContract) LockAsset(ctx contractapi.TransactionContextInterface, a
121124
return "", err
122125
}
123126

124-
assetLockVal := AssetLockValue{Locker: assetAgreement.Locker, Recipient: assetAgreement.Recipient, Hash: string(lockInfoHTLC.Hash), ExpiryTimeSecs: lockInfoHTLC.ExpiryTimeSecs}
127+
assetLockVal := AssetLockValue{Locker: assetAgreement.Locker, Recipient: assetAgreement.Recipient, Hash: string(lockInfoHTLC.HashBase64), ExpiryTimeSecs: lockInfoHTLC.ExpiryTimeSecs}
125128

126129
assetLockValBytes, err := ctx.GetStub().GetState(assetLockKey)
127130
if err != nil {
@@ -130,16 +133,12 @@ func (s *SmartContract) LockAsset(ctx contractapi.TransactionContextInterface, a
130133
}
131134

132135
if assetLockValBytes != nil {
133-
errorMsg := fmt.Sprintf("asset of type %s and ID %s is already locked", assetAgreement.Type, assetAgreement.Id)
134-
log.Error(errorMsg)
135-
return "", errors.New(errorMsg)
136+
return "", logThenErrorf("asset of type %s and ID %s is already locked", assetAgreement.Type, assetAgreement.Id)
136137
}
137138

138139
assetLockValBytes, err = json.Marshal(assetLockVal)
139140
if err != nil {
140-
errorMsg := fmt.Sprintf("marshal error: %s", err)
141-
log.Error(errorMsg)
142-
return "", errors.New(errorMsg)
141+
return "", logThenErrorf("marshal error: %+v", err)
143142
}
144143

145144
err = ctx.GetStub().PutState(assetLockKey, assetLockValBytes)
@@ -150,9 +149,7 @@ func (s *SmartContract) LockAsset(ctx contractapi.TransactionContextInterface, a
150149

151150
assetLockKeyBytes, err := json.Marshal(assetLockKey)
152151
if err != nil {
153-
errorMsg := fmt.Sprintf("marshal error: %s", err)
154-
log.Error(errorMsg)
155-
return "", errors.New(errorMsg)
152+
return "", logThenErrorf("marshal error: %+v", err)
156153
}
157154

158155
err = ctx.GetStub().PutState(generateContractIdMapKey(string(contractId)), assetLockKeyBytes)
@@ -173,7 +170,7 @@ func (s *SmartContract) UnLockAsset(ctx contractapi.TransactionContextInterface,
173170
return err
174171
}
175172
//display the requested asset agreement
176-
log.Info(fmt.Sprintf("assetExchangeAgreement: %+v\n", assetAgreement))
173+
log.Infof("assetExchangeAgreement: %+v\n", assetAgreement)
177174

178175
assetLockKey, _, err := generateAssetLockKeyAndContractId(ctx, assetAgreement)
179176
if err != nil {
@@ -187,7 +184,7 @@ func (s *SmartContract) UnLockAsset(ctx contractapi.TransactionContextInterface,
187184
return err
188185
}
189186

190-
if assetLockValBytes == nil {
187+
if assetLockValBytes == nil {
191188
errorMsg := fmt.Sprintf("no asset of type %s and ID %s is locked", assetAgreement.Type, assetAgreement.Id)
192189
log.Error(errorMsg)
193190
return errors.New(errorMsg)
@@ -209,7 +206,7 @@ func (s *SmartContract) UnLockAsset(ctx contractapi.TransactionContextInterface,
209206

210207
// Check if expiry time is elapsed
211208
currentTimeSecs := uint64(time.Now().Unix())
212-
if uint64(currentTimeSecs) < assetLockVal.ExpiryTimeSecs {
209+
if currentTimeSecs < assetLockVal.ExpiryTimeSecs {
213210
errorMsg := fmt.Sprintf("cannot unlock asset of type %s and ID %s as the expiry time is not yet elapsed", assetAgreement.Type, assetAgreement.Id)
214211
log.Error(errorMsg)
215212
return errors.New(errorMsg)
@@ -235,7 +232,7 @@ func (s *SmartContract) IsAssetLocked(ctx contractapi.TransactionContextInterfac
235232
return false, err
236233
}
237234
//display the requested asset agreement
238-
log.Info(fmt.Sprintf("assetExchangeAgreement: %+v\n", assetAgreement))
235+
log.Infof("assetExchangeAgreement: %+v\n", assetAgreement)
239236

240237
assetLockKey, _, err := generateAssetLockKeyAndContractId(ctx, assetAgreement)
241238
if err != nil {
@@ -262,11 +259,11 @@ func (s *SmartContract) IsAssetLocked(ctx contractapi.TransactionContextInterfac
262259
log.Error(errorMsg)
263260
return false, errors.New(errorMsg)
264261
}
265-
log.Info(fmt.Sprintf("assetLockVal: %+v\n", assetLockVal))
262+
log.Infof("assetLockVal: %+v\n", assetLockVal)
266263

267264
// Check if expiry time is elapsed
268265
currentTimeSecs := uint64(time.Now().Unix())
269-
if uint64(currentTimeSecs) >= assetLockVal.ExpiryTimeSecs {
266+
if currentTimeSecs >= assetLockVal.ExpiryTimeSecs {
270267
errorMsg := fmt.Sprintf("expiry time for asset of type %s and ID %s is already elapsed", assetAgreement.Type, assetAgreement.Id)
271268
log.Error(errorMsg)
272269
return false, errors.New(errorMsg)
@@ -307,9 +304,9 @@ func checkIfCorrectPreimage(preimageBase64 string, hashBase64 string) (bool, err
307304

308305
shaHashBase64 := generateSHA256HashInBase64Form(string(preimage))
309306
if shaHashBase64 == hashBase64 {
310-
log.Info(fmt.Sprintf("%s: preimage %s is passed correctly.\n", funName, preimage))
307+
log.Infof("%s: preimage %s is passed correctly.\n", funName, preimage)
311308
} else {
312-
log.Info(fmt.Sprintf("%s: preimage %s is not passed correctly.\n", funName, preimage))
309+
log.Infof("%s: preimage %s is not passed correctly.\n", funName, preimage)
313310
return false, nil
314311
}
315312
return true, nil
@@ -325,7 +322,7 @@ func (s *SmartContract) ClaimAsset(ctx contractapi.TransactionContextInterface,
325322
return err
326323
}
327324
// display the requested asset agreement
328-
log.Info(fmt.Sprintf("assetExchangeAgreement: %+v\n", assetAgreement))
325+
log.Infof("assetExchangeAgreement: %+v\n", assetAgreement)
329326

330327
claimInfo := &common.AssetClaimHTLC{}
331328
err = proto.Unmarshal([]byte(claimInfoBytes), claimInfo)
@@ -336,7 +333,7 @@ func (s *SmartContract) ClaimAsset(ctx contractapi.TransactionContextInterface,
336333
}
337334

338335
// display the claim information
339-
log.Info(fmt.Sprintf("claimInfo: %+v\n", claimInfo))
336+
log.Infof("claimInfo: %+v\n", claimInfo)
340337

341338
assetLockKey, _, err := generateAssetLockKeyAndContractId(ctx, assetAgreement)
342339
if err != nil {
@@ -372,14 +369,14 @@ func (s *SmartContract) ClaimAsset(ctx contractapi.TransactionContextInterface,
372369

373370
// Check if expiry time is elapsed
374371
currentTimeSecs := uint64(time.Now().Unix())
375-
if uint64(currentTimeSecs) >= assetLockVal.ExpiryTimeSecs {
372+
if currentTimeSecs >= assetLockVal.ExpiryTimeSecs {
376373
errorMsg := fmt.Sprintf("cannot claim asset of type %s and ID %s as the expiry time is already elapsed", assetAgreement.Type, assetAgreement.Id)
377374
log.Error(errorMsg)
378375
return errors.New(errorMsg)
379376
}
380377

381378
// compute the hash from the preimage
382-
isCorrectPreimage, err := checkIfCorrectPreimage(string(claimInfo.HashPreimage), string(assetLockVal.Hash))
379+
isCorrectPreimage, err := checkIfCorrectPreimage(string(claimInfo.HashPreimageBase64), string(assetLockVal.Hash))
383380
if err != nil {
384381
errorMsg := fmt.Sprintf("claim asset of type %s and ID %s error: %v", assetAgreement.Type, assetAgreement.Id, err)
385382
log.Error(errorMsg)
@@ -452,7 +449,7 @@ func (s *SmartContract) UnLockAssetUsingContractId(ctx contractapi.TransactionCo
452449

453450
// Check if expiry time is elapsed
454451
currentTimeSecs := uint64(time.Now().Unix())
455-
if uint64(currentTimeSecs) < assetLockVal.ExpiryTimeSecs {
452+
if currentTimeSecs < assetLockVal.ExpiryTimeSecs {
456453
errorMsg := fmt.Sprintf("cannot unlock asset associated with the contractId %s as the expiry time is not yet elapsed", contractId)
457454
log.Error(errorMsg)
458455
return errors.New(errorMsg)
@@ -493,18 +490,18 @@ func (s *SmartContract) ClaimAssetUsingContractId(ctx contractapi.TransactionCon
493490
}
494491

495492
// display the claim information
496-
log.Info(fmt.Sprintf("claimInfo: %+v\n", claimInfo))
493+
log.Infof("claimInfo: %+v\n", claimInfo)
497494

498495
// Check if expiry time is elapsed
499496
currentTimeSecs := uint64(time.Now().Unix())
500-
if uint64(currentTimeSecs) >= assetLockVal.ExpiryTimeSecs {
497+
if currentTimeSecs >= assetLockVal.ExpiryTimeSecs {
501498
errorMsg := fmt.Sprintf("cannot claim asset associated with contractId %s as the expiry time is already elapsed", contractId)
502499
log.Error(errorMsg)
503500
return errors.New(errorMsg)
504501
}
505502

506503
// compute the hash from the preimage
507-
isCorrectPreimage, err := checkIfCorrectPreimage(string(claimInfo.HashPreimage), string(assetLockVal.Hash))
504+
isCorrectPreimage, err := checkIfCorrectPreimage(string(claimInfo.HashPreimageBase64), string(assetLockVal.Hash))
508505
if err != nil {
509506
errorMsg := fmt.Sprintf("claim asset associated with contractId %s failed with error: %v", contractId, err)
510507
log.Error(errorMsg)
@@ -545,7 +542,7 @@ func (s *SmartContract) IsAssetLockedQueryUsingContractId(ctx contractapi.Transa
545542

546543
// Check if expiry time is elapsed
547544
currentTimeSecs := uint64(time.Now().Unix())
548-
if uint64(currentTimeSecs) >= assetLockVal.ExpiryTimeSecs {
545+
if currentTimeSecs >= assetLockVal.ExpiryTimeSecs {
549546
errorMsg := fmt.Sprintf("expiry time for asset associated with contractId %s is already elapsed", contractId)
550547
log.Error(errorMsg)
551548
return false, errors.New(errorMsg)
@@ -577,7 +574,7 @@ func (s *SmartContract) LockFungibleAsset(ctx contractapi.TransactionContextInte
577574
}
578575

579576
//display the passed lock information
580-
log.Info(fmt.Sprintf("lockInfoHTLC: %+v\n", lockInfoHTLC))
577+
log.Infof("lockInfoHTLC: %+v\n", lockInfoHTLC)
581578

582579
if lockInfoHTLC.TimeSpec != common.AssetLockHTLC_EPOCH {
583580
errorMsg := "only EPOCH time is supported at present"
@@ -589,7 +586,7 @@ func (s *SmartContract) LockFungibleAsset(ctx contractapi.TransactionContextInte
589586
contractId := generateFungibleAssetLockContractId(ctx, assetAgreement)
590587

591588
assetLockVal := FungibleAssetLockValue{Type: assetAgreement.Type, NumUnits: assetAgreement.NumUnits, Locker: assetAgreement.Locker,
592-
Recipient: assetAgreement.Recipient, Hash: string(lockInfoHTLC.Hash), ExpiryTimeSecs: lockInfoHTLC.ExpiryTimeSecs}
589+
Recipient: assetAgreement.Recipient, Hash: string(lockInfoHTLC.HashBase64), ExpiryTimeSecs: lockInfoHTLC.ExpiryTimeSecs}
593590

594591
assetLockValBytes, err := ctx.GetStub().GetState(contractId)
595592
if err != nil {
@@ -660,7 +657,7 @@ func (s *SmartContract) IsFungibleAssetLocked(ctx contractapi.TransactionContext
660657

661658
// Check if expiry time is elapsed
662659
currentTimeSecs := uint64(time.Now().Unix())
663-
if uint64(currentTimeSecs) >= assetLockVal.ExpiryTimeSecs {
660+
if currentTimeSecs >= assetLockVal.ExpiryTimeSecs {
664661
errorMsg := fmt.Sprintf("expiry time for fungible asset associated with contractId %s is already elapsed", contractId)
665662
log.Error(errorMsg)
666663
return false, errors.New(errorMsg)
@@ -687,18 +684,18 @@ func (s *SmartContract) ClaimFungibleAsset(ctx contractapi.TransactionContextInt
687684
}
688685

689686
// display the claim information
690-
log.Info(fmt.Sprintf("claimInfo: %+v\n", claimInfo))
687+
log.Infof("claimInfo: %+v\n", claimInfo)
691688

692689
// Check if expiry time is elapsed
693690
currentTimeSecs := uint64(time.Now().Unix())
694-
if uint64(currentTimeSecs) >= assetLockVal.ExpiryTimeSecs {
691+
if currentTimeSecs >= assetLockVal.ExpiryTimeSecs {
695692
errorMsg := fmt.Sprintf("cannot claim fungible asset associated with contractId %s as the expiry time is already elapsed", contractId)
696693
log.Error(errorMsg)
697694
return errors.New(errorMsg)
698695
}
699696

700697
// compute the hash from the preimage
701-
isCorrectPreimage, err := checkIfCorrectPreimage(string(claimInfo.HashPreimage), string(assetLockVal.Hash))
698+
isCorrectPreimage, err := checkIfCorrectPreimage(string(claimInfo.HashPreimageBase64), string(assetLockVal.Hash))
702699
if err != nil {
703700
errorMsg := fmt.Sprintf("claim fungible asset associated with contractId %s failed with error: %v", contractId, err)
704701
log.Error(errorMsg)
@@ -732,7 +729,7 @@ func (s *SmartContract) UnLockFungibleAsset(ctx contractapi.TransactionContextIn
732729

733730
// Check if expiry time is elapsed
734731
currentTimeSecs := uint64(time.Now().Unix())
735-
if uint64(currentTimeSecs) < assetLockVal.ExpiryTimeSecs {
732+
if currentTimeSecs < assetLockVal.ExpiryTimeSecs {
736733
errorMsg := fmt.Sprintf("cannot unlock fungible asset associated with the contractId %s as the expiry time is not yet elapsed", contractId)
737734
log.Error(errorMsg)
738735
return errors.New(errorMsg)

0 commit comments

Comments
 (0)