-
Notifications
You must be signed in to change notification settings - Fork 60
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
asset transfer #639
base: main
Are you sure you want to change the base?
asset transfer #639
Conversation
33a1ca7
to
13f5dd3
Compare
bd56a9f
to
6040977
Compare
321360b
to
f9d2870
Compare
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Angelo De Caro <[email protected]>
|
||
func TestAssetTransferWithTwoNetworks(network *integration.Infrastructure) { | ||
// give some time to the nodes to get the public parameters | ||
time.Sleep(10 * time.Second) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this sleep is better after start
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we have it in all tests, maybe we can replace it with a different check in another PR.
assert.Equal(me, pledgeInfo.Script.Recipient, "recipient is different [%s]!=[%s]", me, pledgeInfo.Script.Recipient) | ||
|
||
// Store the pledge and send a notification back | ||
_, err = context.RunView(pledge.NewAcceptPledgeIndoView(pledgeInfo)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Info*
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adecaro There is a typo in the name of the method.
NewAcceptPledgeInfoView
instead of NewAcceptPledgeIndoView
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
heheheh, good catch.
@@ -23,7 +24,7 @@ import ( | |||
var _ = Describe("DLog end to end", func() { | |||
BeforeEach(func() { token.Drivers = append(token.Drivers, "dlog") }) | |||
|
|||
for _, t := range integration2.AllTestTypes { | |||
for _, t := range integration2.WebSocketNoReplicationOnly { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to revert this, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
switch { | ||
case output.IsHTLC(): | ||
// check script details | ||
script, err := output.HTLC() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we could use just one interface for both, like
Script() ValidatableScript
that only contains the method validate. That would be maybe more extensible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is just an example, one might perform more checks...
"github.com/hyperledger-labs/fabric-token-sdk/token/token" | ||
) | ||
|
||
// Claim contains the input information to claim a token |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe to give more context
claim a token that has already been pledged, but not yet claimed by someone else, reclaimed by the owner or redeemed by the issuer of the network.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added the comment to the View
assert.NoError(err, "failed to request claim") | ||
|
||
return view2.AsResponder(context, session, | ||
func(context view.Context) (interface{}, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could extract this to a view and re-use the logic in both pledge and fast pledge
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is just an example in an integration test.
} | ||
|
||
func IssueActionMetadata(attributes map[string][]byte, opts *driver.IssueOptions) (map[string][]byte, error) { | ||
var metadata *IssueMetadata |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe to avoid nesting
if len(opts.Attributes) == 0 {
return nil, nil
}
tokenID, hasTokenID := ...
network, hasNetwork := ...
if !hasTokenID || !hasNetwork {
return nil, nil
}
marshalled, err := json.Marshal(&IssueMetadata{tokenID.(*token.ID), network.(string)})
if err != nil {return nil, err}
key := common.Hashable(marshalled).String()
attributes := map[string][]byte{
key: marshalled
}
if proofOpt, ok := ...; ok {
attributes[key + ProofOfClaimSuffix] = proofOpt.([]byte)
}
return attributes, nil
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay
OriginNetwork string | ||
} | ||
|
||
func IssueActionMetadata(attributes map[string][]byte, opts *driver.IssueOptions) (map[string][]byte, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we don't use the attributes
as an input, it's better to avoid passing it as a param for more clarity. Otherwise this implies that the attributes we output depend on the input attributes. Which would require that the different metadataGenerators be called in a specific order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
attributes is used an input and output, you can have multiple functions manipulating these attributes
var metadata *IssueMetadata | ||
var proof []byte | ||
if len(opts.Attributes) != 0 { | ||
tokenID, ok1 := opts.Attributes["github.com/hyperledger-labs/fabric-token-sdk/token/services/interop/pledge/tokenID"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could have these attributes as constants
return errors.Wrap(err, "failed constructing metadata key") | ||
} | ||
|
||
if out.IsRedeem() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would make it a bit more clear to re-use the common parts:
if out.IsRedeem() {
key = pledge.RedeemPledgeKey + key
} else {
if !script.Sender.Equal(...) {...}
key = pledge.MetadataReclaimKey + key
}
v, ok := ctx.TransferAction.GetMetadta()[key]
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Angelo De Caro <[email protected]>
Signed-off-by: Angelo De Caro <[email protected]>
assert.NoError(err, "failed to retrieve pledged token during redeem") | ||
|
||
// make sure token was in fact claimed in the other network | ||
proof, err := pledge.RequestProofOfTokenWithMetadataExistence(context, rv.TokenID, rv.TMSID, script) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we change the name of the method to RequestProofOfExistenceOfTokenWithMetadata
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay
Signed-off-by: Angelo De Caro <[email protected]>
if owner.Type == htlc.ScriptType { | ||
// Then, the first output must be compatible with this input. | ||
if len(ctx.TransferAction.GetOutputs()) != 1 { | ||
return errors.New("invalid transfer action: an htlc script only transfers the ownership of a token") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should also enforce that len(Inputs) == 1
since a claim
and a reclaim
are just ownership transfers.
|
||
tokenID, hasTokenID := opts.Attributes[TokenIDKey] | ||
network, hasNetwork := opts.Attributes[NetworkKey] | ||
if !hasTokenID && !hasNetwork { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we perform this check? It does not seem to have an impact on the output of the method.
return err | ||
} | ||
if time.Now().Before(script.Deadline) { | ||
return errors.New("cannot reclaim pledge yet: wait for timeout to elapse.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's both reclaim and redeem. Shall we say cannot change the state of the pledge yet
?
logger.Debugf("Is Mine [%s,%s,%s]? [%b] with [%s]", view2.Identity(tok.Owner.Raw), tok.Type, tok.Quantity, len(ids) != 0, ids) | ||
return "", ids, len(ids) != 0 | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does Issued
implement. A comment will be helpful.
v, ok := ctx.TransferAction.GetMetadata()[pledge.MetadataKey+script.ID] | ||
if !ok { | ||
return errors.Errorf("empty metadata for pledge script with identifier %s", script.ID) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What information does this metadata convey?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Going through the rest of the code, this seems to enforce to enforce the uniqueness of PledgeID
.
} | ||
|
||
func (t *Output) GetOwner() []byte { | ||
if t.Owner != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be if ! t.IsRedeem()
?
}, nil | ||
} | ||
|
||
func (p *StateQueryExecutor) Exist(tokenID *token.ID) ([]byte, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exists
?
logger.Debugf("failed unmarshalling pledge script [%s]: [%s]", tok, err) | ||
return nil | ||
} | ||
if script.Sender.IsNone() || script.Recipient.IsNone() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we return an error
here?
|
||
// IDExists scans the ledger for a pledge identifier, taking into account the timeout | ||
// IDExists returns true, if entry identified by key (MetadataKey+pledgeID) is occupied. | ||
func IDExists(ctx view.Context, pledgeID string, timeout time.Duration, opts ...token.ServiceOption) (bool, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method does not seem to be used elsewhere.
return &ReceiveTransactionView{} | ||
} | ||
|
||
func (f *ReceiveTransactionView) Call(context view.Context) (interface{}, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall we use v
or rtv
instead of f
?
if err != nil { | ||
return errors.Errorf("input owner at index [%d] cannot be unmarshalled", index) | ||
} | ||
scriptInf := &htlc.ScriptInfo{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall move ScriptInfo
under a common
repo. Since this is a bit confusing.
if err := json.Unmarshal(token.Owner.OwnerInfo, scriptInf); err != nil { | ||
return errors.Wrapf(err, "failed to unmarshal script info") | ||
} | ||
scriptSender, _, scriptIssuer, err := pledge.GetScriptSenderAndRecipient(owner) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall we call the method GetScriptStakeholders
?
if err := session.Receive(recipientData); err != nil { | ||
return nil, errors.Wrapf(err, "failed to receive recipient data") | ||
} | ||
//if err := tms.WalletManager().RegisterRecipientIdentity(recipientData); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall we remove the commented code? Or is this a todo?
} | ||
logger.Debugf("proof of existence in claim request is valid [%s]", err) | ||
|
||
if !req.ClaimDeadline.After(time.Now()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall we start with checking the time first?
return nil, errors.Wrapf(err, "failed storing pledge info") | ||
} | ||
|
||
// raw, err := a.info.Bytes() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we remove this?
if err != nil { | ||
return nil, errors.WithMessagef(err, "failed getting prover for [%s]", c.source) | ||
} | ||
return p.Exist(c.tokenID) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exists
?
}, nil | ||
} | ||
|
||
func (v *StateVerifier) VerifyProofExistence(proofRaw []byte, tokenID *token.ID, metadata []byte) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about VerifyProofOfTokenExistence
?
return nil | ||
} | ||
|
||
func (v *StateVerifier) VerifyProofNonExistence(proofRaw []byte, tokenID *token.ID, origin string, deadline time.Time) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about VerifyProofOfTokenNonExistence
@@ -88,6 +94,25 @@ func (t *Translator) CreateTransferActionMetadataKey(key string) (translator.Key | |||
return createCompositeKey(TransferActionMetadataPrefix, []string{key}) | |||
} | |||
|
|||
func (t *Translator) CreateProofOfExistenceKey(tokenId *token.ID) (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe CreateProofOfTokenExistenceKey
}) | ||
} | ||
|
||
func (t *Translator) CreateProofOfMetadataExistenceKey(tokenID *token.ID, origin string) (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe CreateProofOfTokenMetadataExistenceKey
return createCompositeKey(ProofOfExistencePrefix, []string{id}) | ||
} | ||
|
||
func (t *Translator) CreateProofOfNonExistenceKey(tokenID *token.ID, origin string) (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe CreateProofOfTokenMetadataNonExistenceKey
This PR adapts the code in #437 to the current shape of the token-sdk. The code is mostly contribution of @HagarMeir .
To be addressed in another PR: