Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fabric Interop Node SDK Support for HTLC-based Asset Exchanges #45

Merged
merged 18 commits into from
May 18, 2021
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
b6d129c
Initial checkin of Fabric Interop Node SDK for HTLC Asset Exchanges
VRamakrishna May 5, 2021
fa2190d
Added asset lock and claim functions in Fabric Interop Node SDK
VRamakrishna May 6, 2021
7f128ce
Added reclaim and asset lock query functions to Fabric Interop Node SDK
VRamakrishna May 7, 2021
6e4c4b5
Changed asset lock and claim field names to reflect Base64 encoding
VRamakrishna May 7, 2021
6564624
Updated field and function names in Fabric Interop Node SDK based on …
VRamakrishna May 7, 2021
4624fea
Generating secure pseudorandom hash preimage for asset locks in Fabri…
VRamakrishna May 11, 2021
e79cce1
Updated error handling in asset exchange functions in Fabric Interop …
VRamakrishna May 12, 2021
28629fc
Merge remote-tracking branch 'upstream/main' into main
VRamakrishna May 15, 2021
4f5eae8
Fabric Interop CC asset exchange code cleanup
VRamakrishna May 16, 2021
afa400f
Emitting asset exchange (HTLC) events from Fabric Interop CC
VRamakrishna May 16, 2021
04239fc
Added timeout listeners to asset locking functions in Fabric Interop SDK
VRamakrishna May 16, 2021
4694f61
HTLC asset event listener functions in Fabric Interop SDK
VRamakrishna May 16, 2021
a5813d2
Fabric Interop SDK refactoring and adding fungible asset event listeners
VRamakrishna May 17, 2021
fdc53c6
Fabric Interop SDK: HTLC event promises, API updates, code cleanup
VRamakrishna May 17, 2021
73d3992
Exposed event-related functions in Fabric Interop SDK
VRamakrishna May 17, 2021
2717622
Minor code refactoring and commenting
VRamakrishna May 18, 2021
2ebeb32
Added more comments on event setting in Fabric asset management base …
VRamakrishna May 18, 2021
aa0cb2c
Merge remote-tracking branch 'upstream/main' into main
VRamakrishna May 18, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions common/interop-protos/common/asset_locks.proto
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ message AssetClaim {
}

message AssetLockHTLC {
bytes hash = 1;
bytes hashBase64 = 1;
uint64 expiryTimeSecs = 2;
enum TimeSpec {
EPOCH = 0;
Expand All @@ -28,7 +28,7 @@ message AssetLockHTLC {
}

message AssetClaimHTLC {
bytes hashPreimage = 1;
bytes hashPreimageBase64 = 1;
}

message AssetExchangeAgreement {
Expand All @@ -44,3 +44,17 @@ message FungibleAssetExchangeAgreement {
string locker = 3;
string recipient = 4;
}

message AssetContractHTLC {
string contractId = 1;
AssetExchangeAgreement agreement = 2;
AssetLockHTLC lock = 3;
AssetClaimHTLC claim = 4;
}

message FungibleAssetContractHTLC {
string contractId = 1;
FungibleAssetExchangeAgreement agreement = 2;
AssetLockHTLC lock = 3;
AssetClaimHTLC claim = 4;
}
73 changes: 46 additions & 27 deletions core/network/fabric-interop-cc/contracts/interop/manage_assets.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,25 @@ const(
contractIdPrefix = "ContractId_" // prefix for the map, contractId --> asset-key
)

// helper functions to log and return errors
func logAndReturnErrorfBool(retVal bool, format string, args ...interface{}) (bool, error) {
errorMsg := fmt.Sprintf(format, args...)
log.Error(errorMsg)
return retVal, errors.New(errorMsg)
}

func logAndReturnErrorfInt(retVal int, format string, args ...interface{}) (int, error) {
errorMsg := fmt.Sprintf(format, args...)
log.Error(errorMsg)
return retVal, errors.New(errorMsg)
}

func logAndReturnErrorfString(retVal string, format string, args ...interface{}) (string, error) {
errorMsg := fmt.Sprintf(format, args...)
log.Error(errorMsg)
return retVal, errors.New(errorMsg)
}

VRamakrishna marked this conversation as resolved.
Show resolved Hide resolved
// function to generate a "SHA256" hash in base64 format for a given preimage
func generateSHA256HashInBase64Form(preimage string) string {
hasher := sha256.New()
Expand Down Expand Up @@ -98,7 +117,7 @@ func (s *SmartContract) LockAsset(ctx contractapi.TransactionContextInterface, a
return "", err
}
//display the requested asset agreement
log.Info(fmt.Sprintf("assetExchangeAgreement: %+v\n", assetAgreement))
log.Infof("assetExchangeAgreement: %+v\n", assetAgreement)

lockInfoHTLC := &common.AssetLockHTLC{}
err = proto.Unmarshal([]byte(lockInfoBytes), lockInfoHTLC)
Expand All @@ -107,7 +126,7 @@ func (s *SmartContract) LockAsset(ctx contractapi.TransactionContextInterface, a
return "", err
}
//display the passed lock information
log.Info(fmt.Sprintf("lockInfoHTLC: %+v\n", lockInfoHTLC))
log.Infof("lockInfoHTLC: %+v\n", lockInfoHTLC)

if lockInfoHTLC.TimeSpec != common.AssetLockHTLC_EPOCH {
errorMsg := "only EPOCH time is supported at present"
Expand All @@ -121,7 +140,7 @@ func (s *SmartContract) LockAsset(ctx contractapi.TransactionContextInterface, a
return "", err
}

assetLockVal := AssetLockValue{Locker: assetAgreement.Locker, Recipient: assetAgreement.Recipient, Hash: string(lockInfoHTLC.Hash), ExpiryTimeSecs: lockInfoHTLC.ExpiryTimeSecs}
assetLockVal := AssetLockValue{Locker: assetAgreement.Locker, Recipient: assetAgreement.Recipient, Hash: string(lockInfoHTLC.HashBase64), ExpiryTimeSecs: lockInfoHTLC.ExpiryTimeSecs}

assetLockValBytes, err := ctx.GetStub().GetState(assetLockKey)
if err != nil {
Expand Down Expand Up @@ -173,7 +192,7 @@ func (s *SmartContract) UnLockAsset(ctx contractapi.TransactionContextInterface,
return err
}
//display the requested asset agreement
log.Info(fmt.Sprintf("assetExchangeAgreement: %+v\n", assetAgreement))
log.Infof("assetExchangeAgreement: %+v\n", assetAgreement)

assetLockKey, _, err := generateAssetLockKeyAndContractId(ctx, assetAgreement)
if err != nil {
Expand All @@ -187,7 +206,7 @@ func (s *SmartContract) UnLockAsset(ctx contractapi.TransactionContextInterface,
return err
}

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

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

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

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

shaHashBase64 := generateSHA256HashInBase64Form(string(preimage))
if shaHashBase64 == hashBase64 {
log.Info(fmt.Sprintf("%s: preimage %s is passed correctly.\n", funName, preimage))
log.Infof("%s: preimage %s is passed correctly.\n", funName, preimage)
} else {
log.Info(fmt.Sprintf("%s: preimage %s is not passed correctly.\n", funName, preimage))
log.Infof("%s: preimage %s is not passed correctly.\n", funName, preimage)
return false, nil
}
return true, nil
Expand All @@ -325,7 +344,7 @@ func (s *SmartContract) ClaimAsset(ctx contractapi.TransactionContextInterface,
return err
}
// display the requested asset agreement
log.Info(fmt.Sprintf("assetExchangeAgreement: %+v\n", assetAgreement))
log.Infof("assetExchangeAgreement: %+v\n", assetAgreement)

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

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

assetLockKey, _, err := generateAssetLockKeyAndContractId(ctx, assetAgreement)
if err != nil {
Expand Down Expand Up @@ -372,14 +391,14 @@ func (s *SmartContract) ClaimAsset(ctx contractapi.TransactionContextInterface,

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

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

// Check if expiry time is elapsed
currentTimeSecs := uint64(time.Now().Unix())
if uint64(currentTimeSecs) < assetLockVal.ExpiryTimeSecs {
if currentTimeSecs < assetLockVal.ExpiryTimeSecs {
errorMsg := fmt.Sprintf("cannot unlock asset associated with the contractId %s as the expiry time is not yet elapsed", contractId)
log.Error(errorMsg)
return errors.New(errorMsg)
Expand Down Expand Up @@ -493,18 +512,18 @@ func (s *SmartContract) ClaimAssetUsingContractId(ctx contractapi.TransactionCon
}

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

// Check if expiry time is elapsed
currentTimeSecs := uint64(time.Now().Unix())
if uint64(currentTimeSecs) >= assetLockVal.ExpiryTimeSecs {
if currentTimeSecs >= assetLockVal.ExpiryTimeSecs {
errorMsg := fmt.Sprintf("cannot claim asset associated with contractId %s as the expiry time is already elapsed", contractId)
log.Error(errorMsg)
return errors.New(errorMsg)
}

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

// Check if expiry time is elapsed
currentTimeSecs := uint64(time.Now().Unix())
if uint64(currentTimeSecs) >= assetLockVal.ExpiryTimeSecs {
if currentTimeSecs >= assetLockVal.ExpiryTimeSecs {
errorMsg := fmt.Sprintf("expiry time for asset associated with contractId %s is already elapsed", contractId)
log.Error(errorMsg)
return false, errors.New(errorMsg)
Expand Down Expand Up @@ -577,7 +596,7 @@ func (s *SmartContract) LockFungibleAsset(ctx contractapi.TransactionContextInte
}

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

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

assetLockVal := FungibleAssetLockValue{Type: assetAgreement.Type, NumUnits: assetAgreement.NumUnits, Locker: assetAgreement.Locker,
Recipient: assetAgreement.Recipient, Hash: string(lockInfoHTLC.Hash), ExpiryTimeSecs: lockInfoHTLC.ExpiryTimeSecs}
Recipient: assetAgreement.Recipient, Hash: string(lockInfoHTLC.HashBase64), ExpiryTimeSecs: lockInfoHTLC.ExpiryTimeSecs}

assetLockValBytes, err := ctx.GetStub().GetState(contractId)
if err != nil {
Expand Down Expand Up @@ -660,7 +679,7 @@ func (s *SmartContract) IsFungibleAssetLocked(ctx contractapi.TransactionContext

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

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

// Check if expiry time is elapsed
currentTimeSecs := uint64(time.Now().Unix())
if uint64(currentTimeSecs) >= assetLockVal.ExpiryTimeSecs {
if currentTimeSecs >= assetLockVal.ExpiryTimeSecs {
errorMsg := fmt.Sprintf("cannot claim fungible asset associated with contractId %s as the expiry time is already elapsed", contractId)
log.Error(errorMsg)
return errors.New(errorMsg)
}

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

// Check if expiry time is elapsed
currentTimeSecs := uint64(time.Now().Unix())
if uint64(currentTimeSecs) < assetLockVal.ExpiryTimeSecs {
if currentTimeSecs < assetLockVal.ExpiryTimeSecs {
errorMsg := fmt.Sprintf("cannot unlock fungible asset associated with the contractId %s as the expiry time is not yet elapsed", contractId)
log.Error(errorMsg)
return errors.New(errorMsg)
Expand Down
Loading