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

Remove signature metadata action #358

Merged
merged 17 commits into from
Aug 30, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
28 changes: 28 additions & 0 deletions token/core/common/metadata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
Copyright IBM Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package common

import (
"strings"

token2 "github.com/hyperledger-labs/fabric-token-sdk/token"
)

// SetTransferActionMetadata extracts the transfer metadata from the passed attributes and
// sets them to the passed metadata
func SetTransferActionMetadata(attrs map[interface{}]interface{}, metadata map[string][]byte) {
for key, value := range attrs {
k, ok1 := key.(string)
v, ok2 := value.([]byte)
if ok1 && ok2 {
if strings.HasPrefix(k, token2.TransferMetadataPrefix) {
mKey := strings.TrimPrefix(k, token2.TransferMetadataPrefix)
metadata[mKey] = v
}
}
}
}
20 changes: 6 additions & 14 deletions token/core/fabtoken/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,7 @@ import (
"github.com/pkg/errors"
)

// Signature contains metadata
type Signature struct {
metadata map[string][]byte // metadata may include for example the preimage of an htlc script
}

// Metadata returns the contained metadata
func (s *Signature) Metadata() map[string][]byte {
return s.metadata
}

// OutputMetadata contains a serialization of the issuer of the token.
// TokenInformation contains a serialization of the issuer of the token.
// type, value and owner of token can be derived from the token itself.
type OutputMetadata struct {
Issuer []byte
Expand Down Expand Up @@ -127,6 +117,8 @@ type TransferAction struct {
Inputs []string
// outputs to be created as a result of the transfer
Outputs []*Output
// Metadata contains the action's metadata
adecaro marked this conversation as resolved.
Show resolved Hide resolved
Metadata map[string][]byte
}

// Serialize marshals TransferAction
Expand Down Expand Up @@ -196,7 +188,7 @@ func (t *TransferAction) Deserialize(raw []byte) error {
return json.Unmarshal(raw, t)
}

// GetMetadata returns nil, indicating that fabtoken TransferAction carries no metadata
func (t *TransferAction) GetMetadata() []byte {
return nil
// GetMetadata returns the claim pre-image
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change this comment

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

func (t *TransferAction) GetMetadata() map[string][]byte {
return t.Metadata
}
9 changes: 7 additions & 2 deletions token/core/fabtoken/sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package fabtoken

import (
"github.com/hyperledger-labs/fabric-smart-client/platform/view/view"
"github.com/hyperledger-labs/fabric-token-sdk/token/core/common"
"github.com/hyperledger-labs/fabric-token-sdk/token/core/identity"
"github.com/hyperledger-labs/fabric-token-sdk/token/core/interop"
"github.com/hyperledger-labs/fabric-token-sdk/token/driver"
Expand Down Expand Up @@ -46,10 +47,14 @@ func (s *Service) Transfer(txID string, wallet driver.OwnerWallet, ids []*token2

// assemble transfer action
transfer := &TransferAction{
Inputs: inputIDs,
Outputs: outs,
Inputs: inputIDs,
Outputs: outs,
Metadata: map[string][]byte{},
}

// add transfer action's metadata
common.SetTransferActionMetadata(opts.Attributes, transfer.Metadata)

// assemble transfer metadata
var receivers []view.Identity
for i, output := range outs {
Expand Down
80 changes: 71 additions & 9 deletions token/core/fabtoken/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,24 +150,86 @@ func (v *Validator) VerifyTokenRequest(ledger driver.Ledger, signatureProvider d
actions = append(actions, action)
}
for _, action := range ta {
actions = append(actions, action)
act, err := AddMetadataToTransferAction(action, ledger, signatureProvider)
if err != nil {
return nil, errors.Wrap(err, "failed adding metadata to transfer action")
}
actions = append(actions, act)
}

// actions are returned and will be used later to update the ledger
return actions, nil
}

func AddMetadataToTransferAction(action *TransferAction, ledger driver.Ledger, signatureProvider driver.SignatureProvider) (*TransferAction, error) {
for _, sig := range signatureProvider.Signatures() {
claim := &htlc.ClaimSignature{}
if err = json.Unmarshal(sig, claim); err != nil {
if err := json.Unmarshal(sig, claim); err != nil {
continue
}
if len(claim.Preimage) == 0 || len(claim.RecipientSignature) == 0 {
return nil, errors.New("expected a valid claim preImage and recipient signature")
}
actions = append(actions, &Signature{
metadata: map[string][]byte{
"claimPreimage": claim.Preimage,
},
})
if IsItAnExchangeClaimTransferAction(action, ledger) {
if len(action.Metadata) == 0 {
return nil, errors.Errorf("cannot find htlc pre-image, no metadata")
}
value, ok := action.Metadata[htlc.ClaimPreImage]
if !ok {
return nil, errors.Errorf("cannot find htlc pre-image, missing metadata entry")
}
if !bytes.Equal(value, claim.Preimage) {
return nil, errors.Errorf("invalid action, cannot match htlc pre-image with metadata [%x]!=[%x]", value, claim.Preimage)
}
}
}
// actions are returned and will be used later to update the ledger
return actions, nil
return action, nil
}

func IsItAnExchangeClaimTransferAction(action *TransferAction, ledger driver.Ledger) bool {
if action.NumOutputs() != 1 {
logger.Debugf("Number of outputs is %d", action.NumOutputs())
return false
}
out, ok := action.GetOutputs()[0].(*Output)
if !ok {
logger.Debugf("invalid transfer action output")
return false
}
if out.IsRedeem() {
logger.Debugf("this is a redeem")
return false
}
inputs, err := RetrieveInputsFromTransferAction(action, ledger)
if err != nil {
logger.Debugf("error while retrieving inputs from transfer action: %v", err)
return false
}
if len(inputs) != 1 {
logger.Debugf("Number of inputs is %d", len(inputs))
return false
}
inOwner, err := identity.UnmarshallRawOwner(inputs[0].Owner.Raw)
if err != nil {
logger.Debugf("error while unmarshalling input raw owner: %v", err)
return false
}
if inOwner.Type != htlc.ScriptType {
logger.Debugf("script recipient does not match the output owner")
return false
}
script := &htlc.Script{}
err = json.Unmarshal(inOwner.Identity, script)
if err != nil {
logger.Debugf("error while unmarshalling into script: %v", err)
return false
}
if !script.Recipient.Equal(out.Output.Owner.Raw) {
logger.Debugf("script recipient does not match the output owner")
return false
}
logger.Debugf("this is an exchange claim")
return true
}

// VerifyTokenRequestFromRaw validates the raw token request
Expand Down
13 changes: 9 additions & 4 deletions token/core/zkatdlog/crypto/transfer/sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Copyright IBM Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package transfer

import (
Expand Down Expand Up @@ -110,6 +111,8 @@ type TransferAction struct {
OutputTokens []*token.Token
// ZK Proof that shows that the transfer is correct
Proof []byte
// Metadata contains the action's metadata
Metadata map[string][]byte
}

// NewTransfer returns the TransferAction that matches the passed arguments
Expand All @@ -128,7 +131,9 @@ func NewTransfer(inputs []string, inputCommitments []*math.G1, outputs []*math.G
Inputs: inputs,
InputCommitments: inputCommitments,
OutputTokens: tokens,
Proof: proof}, nil
Proof: proof,
Metadata: map[string][]byte{},
}, nil
}

// GetInputs returns the inputs in the TransferAction
Expand Down Expand Up @@ -204,9 +209,9 @@ func (t *TransferAction) IsGraphHiding() bool {
}

// GetMetadata returns metadata of the TransferAction
// zkatdlog TransferAction does not carry any metadata
func (t *TransferAction) GetMetadata() []byte {
return nil
// in zkatdlog it returns the claim pre-image
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change comment

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

func (t *TransferAction) GetMetadata() map[string][]byte {
return t.Metadata
}

func getTokenData(tokens []*token.Token) []*math.G1 {
Expand Down
103 changes: 87 additions & 16 deletions token/core/zkatdlog/crypto/validator/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,6 @@ func (v *Validator) VerifyTokenRequestFromRaw(getState driver.GetStateFnc, bindi
return v.VerifyTokenRequest(backend, backend, binding, tr)
}

type Signature struct {
metadata map[string][]byte // metadata may include for example the preimage of an htlc script
}

func (s *Signature) Metadata() map[string][]byte {
return s.metadata
}

func (v *Validator) VerifyTokenRequest(ledger driver.Ledger, signatureProvider driver.SignatureProvider, binding string, tr *driver.TokenRequest) ([]interface{}, error) {
if err := v.verifyAuditorSignature(signatureProvider); err != nil {
return nil, errors.Wrapf(err, "failed to verifier auditor's signature [%s]", binding)
Expand All @@ -174,25 +166,104 @@ func (v *Validator) VerifyTokenRequest(ledger driver.Ledger, signatureProvider d
actions = append(actions, action)
}
for _, action := range ta {
actions = append(actions, action)
transferAction := action.(*transfer.TransferAction)
act, err := AddMetadataToTransferAction(transferAction, ledger, signatureProvider)
if err != nil {
return nil, errors.Wrap(err, "failed adding metadata to transfer action")
}
actions = append(actions, act)
}

return actions, nil
}

func AddMetadataToTransferAction(action *transfer.TransferAction, ledger driver.Ledger, signatureProvider driver.SignatureProvider) (*transfer.TransferAction, error) {
for _, sig := range signatureProvider.Signatures() {
claim := &htlc.ClaimSignature{}
if err = json.Unmarshal(sig, claim); err != nil {
if err := json.Unmarshal(sig, claim); err != nil {
continue
}
if len(claim.Preimage) == 0 || len(claim.RecipientSignature) == 0 {
return nil, errors.New("expected a valid claim preImage and recipient signature")
}
actions = append(actions, &Signature{
metadata: map[string][]byte{
"claimPreimage": claim.Preimage,
},
})
b, err := IsItAnExchangeClaimTransferAction(action, ledger)
if err != nil {
return nil, err
}
if b {
if len(action.Metadata) == 0 {
return nil, errors.Errorf("cannot find htlc pre-image, no metadata")
}
value, ok := action.Metadata[htlc.ClaimPreImage]
if !ok {
return nil, errors.Errorf("cannot find htlc pre-image, missing metadata entry")
}
if !bytes.Equal(value, claim.Preimage) {
return nil, errors.Errorf("invalid action, cannot match htlc pre-image with metadata [%x]!=[%x]", value, claim.Preimage)
}
}
}
return action, nil
}

return actions, nil
func IsItAnExchangeClaimTransferAction(action *transfer.TransferAction, ledger driver.Ledger) (bool, error) {
if action.NumOutputs() != 1 {
logger.Debugf("Number of outputs is %d", action.NumOutputs())
return false, nil
}
out, ok := action.GetOutputs()[0].(*token.Token)
if !ok {
return false, errors.New("invalid transfer action output")
}
if out.IsRedeem() {
logger.Debugf("this is a redeem")
return false, nil
}

var inputTokens []*token.Token
inputs, err := action.GetInputs()
if err != nil {
return false, errors.Wrapf(err, "failed to retrieve inputs to spend")
}
for _, in := range inputs {
bytes, err := ledger.GetState(in)
if err != nil {
return false, errors.Wrapf(err, "failed to retrieve input to spend [%s]", in)
}
if len(bytes) == 0 {
return false, errors.Errorf("input to spend [%s] does not exists", in)
}
tok := &token.Token{}
err = tok.Deserialize(bytes)
if err != nil {
return false, errors.Wrapf(err, "failed to deserialize input to spend [%s]", in)
}
inputTokens = append(inputTokens, tok)
}

if len(inputTokens) != 1 {
logger.Debugf("Number of inputs is %d", len(inputs))
return false, nil
}
inOwner, err := identity.UnmarshallRawOwner(inputTokens[0].Owner)
if err != nil {
return false, errors.Wrap(err, "failed to unmarshall input raw owner")
}
if inOwner.Type != htlc.ScriptType {
logger.Debugf("script recipient does not match the output owner")
return false, nil
}
script := &htlc.Script{}
err = json.Unmarshal(inOwner.Identity, script)
if err != nil {
return false, errors.Wrap(err, "failed to unmarshall into script")
}
if !script.Recipient.Equal(out.Owner) {
logger.Debugf("script recipient does not match the output owner")
return false, nil
}
logger.Debugf("this is an exchange claim")
return true, nil
}

func (v *Validator) unmarshalTransferActions(raw [][]byte) ([]driver.TransferAction, error) {
Expand Down
4 changes: 4 additions & 0 deletions token/core/zkatdlog/nogh/sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package nogh
import (
math "github.com/IBM/mathlib"
"github.com/hyperledger-labs/fabric-smart-client/platform/view/view"
"github.com/hyperledger-labs/fabric-token-sdk/token/core/common"
"github.com/hyperledger-labs/fabric-token-sdk/token/core/identity"
"github.com/hyperledger-labs/fabric-token-sdk/token/core/interop"
"github.com/hyperledger-labs/fabric-token-sdk/token/core/zkatdlog/crypto/token"
Expand Down Expand Up @@ -82,6 +83,9 @@ func (s *Service) Transfer(txID string, wallet driver.OwnerWallet, ids []*token3
return nil, nil, errors.Wrapf(err, "failed to generate zkatdlog transfer action for txid [%s]", txID)
}

// add transfer action's metadata
common.SetTransferActionMetadata(opts.Attributes, transfer.Metadata)

// prepare metadata
var outputMetadataRaw [][]byte
for _, information := range outputMetadata {
Expand Down
4 changes: 2 additions & 2 deletions token/driver/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,6 @@ type TransferAction interface {
// IsGraphHiding returns true if the action is graph hiding
// TODO: Deprecated. This should be checked using the public parameters
IsGraphHiding() bool
// GetMetadata returns the metadata of the action
GetMetadata() []byte
// GetMetadata returns the action's metadata
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a dot at the end of the comment?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we usually don't have it. No?

GetMetadata() map[string][]byte
}
Loading