Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 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
34 changes: 17 additions & 17 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -104,27 +104,27 @@ clean:
docker network prune -f
docker container prune -f
docker volume prune -f
rm -rf ./integration/token/fungible/dlog/cmd/
rm -rf ./integration/token/fungible/dlog/out/
rm -rf ./integration/token/fungible/dlog/testdata/
rm -rf ./integration/token/fungible/dlogx/cmd/
rm -rf ./integration/token/fungible/dloghsm/cmd/
rm -rf ./integration/token/fungible/dlogx/out/
rm -rf ./integration/token/fungible/dloghsm/out/
rm -rf ./integration/token/fungible/dloghsm/testdata/
rm -rf ./integration/token/fungible/dlogstress/cmd/
rm -rf ./integration/token/fungible/dlogstress/out/
rm -rf ./integration/token/fungible/dlogstress/testdata/
rm -rf ./integration/token/fungible/fabtoken/cmd/
rm -rf ./integration/token/fungible/fabtoken/out/
rm -rf ./integration/token/fungible/fabtoken/testdata/
rm -rf ./integration/token/fungible/odlog/cmd/
rm -rf ./integration/token/fungible/ofabtoken/cmd/
rm -rf ./integration/token/fungible/mixed/cmd/
rm -rf ./integration/token/nft/dlog/cmd/
rm -rf ./integration/token/nft/fabtoken/cmd/
rm -rf ./integration/token/nft/odlog/cmd/
rm -rf ./integration/token/nft/ofabtoken/cmd/
rm -rf ./integration/token/dvp/dlog/cmd/
rm -rf ./integration/token/dvp/fabtoken/cmd/
rm -rf ./integration/token/interop/fabtoken/cmd/
rm -rf ./integration/token/interop/dlog/cmd/
rm -rf ./integration/token/fungible/update/cmd/
rm -rf ./integration/token/fungible/odlog/out/
rm -rf ./integration/token/fungible/ofabtoken/out/
rm -rf ./integration/token/fungible/mixed/out/
rm -rf ./integration/token/nft/dlog/out/
rm -rf ./integration/token/nft/fabtoken/out/
rm -rf ./integration/token/nft/odlog/out/
rm -rf ./integration/token/nft/ofabtoken/out/
rm -rf ./integration/token/dvp/dlog/out/
rm -rf ./integration/token/dvp/fabtoken/out/
rm -rf ./integration/token/interop/fabtoken/out/
rm -rf ./integration/token/interop/dlog/out/
rm -rf ./integration/token/fungible/update/out/
rm -rf ./integration/token/fungible/update/testdata/

.PHONY: clean-fabric-peer-images
Expand Down
35 changes: 35 additions & 0 deletions cmd/tokengen/cobra/pp/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,38 @@ func GetCertificatesFromDir(dir string) ([][]byte, error) {

return content, nil
}

// LoadExtras parses strings in the format "key:file_path" and returns a map
// where keys are the extracted keys and values are the file contents as []byte.
func LoadExtras(extraFiles []string) (map[string][]byte, error) {
result := make(map[string][]byte, len(extraFiles))

for _, entry := range extraFiles {
// Split on the first colon to get key and filepath
parts := strings.SplitN(entry, "=", 2)
if len(parts) != 2 {
return nil, errors.Errorf("invalid format %q: expected key:filepath", entry)
Copy link
Contributor

Choose a reason for hiding this comment

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

it looks like it's actually expecting key=filepath instead of key:filepath (the : is also in the comment above the function)

}

key := parts[0]
filepath := parts[1]

// Check for empty key or filepath
if key == "" {
return nil, errors.Errorf("empty key in entry %q", entry)
}
if filepath == "" {
return nil, errors.Errorf("empty filepath for key %q", key)
}

// Read the file
content, err := os.ReadFile(filepath)
if err != nil {
return nil, errors.Wrapf(err, "failed to read file for key %q (path: %s)", key, filepath)
}

result[key] = content
}

return result, nil
}
177 changes: 177 additions & 0 deletions cmd/tokengen/cobra/pp/common/common_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/*
Copyright IBM Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package common

import (
"os"
"path/filepath"
"testing"
)

func TestLoadExtras(t *testing.T) {
// Create a temporary directory for test files
tempDir := t.TempDir()

// Test case 1: Successfully load multiple files
t.Run("success_multiple_files", func(t *testing.T) {
// Create test files
file1Path := filepath.Join(tempDir, "test1.json")
file1Content := []byte(`{"key": "value1"}`)
if err := os.WriteFile(file1Path, file1Content, 0644); err != nil {
t.Fatalf("failed to create test file: %v", err)
}

file2Path := filepath.Join(tempDir, "test2.json")
file2Content := []byte(`{"key": "value2"}`)
if err := os.WriteFile(file2Path, file2Content, 0644); err != nil {
t.Fatalf("failed to create test file: %v", err)
}

extraFiles := []string{
"foo=" + file1Path,
"bar=" + file2Path,
}

result, err := LoadExtras(extraFiles)
if err != nil {
t.Fatalf("expected no error, got: %v", err)
}

if len(result) != 2 {
t.Errorf("expected 2 entries, got %d", len(result))
}

if string(result["foo"]) != string(file1Content) {
t.Errorf("expected %q for foo, got %q", string(file1Content), string(result["foo"]))
}

if string(result["bar"]) != string(file2Content) {
t.Errorf("expected %q for bar, got %q", string(file2Content), string(result["bar"]))
}
})

// Test case 2: Empty input slice
t.Run("empty_input", func(t *testing.T) {
extraFiles := []string{}

result, err := LoadExtras(extraFiles)
if err != nil {
t.Fatalf("expected no error, got: %v", err)
}

if len(result) != 0 {
t.Errorf("expected empty map, got %d entries", len(result))
}
})

// Test case 3: File does not exist
t.Run("file_not_found", func(t *testing.T) {
extraFiles := []string{
"missing=" + filepath.Join(tempDir, "nonexistent.json"),
}

result, err := LoadExtras(extraFiles)
if err == nil {
t.Fatal("expected error for missing file, got nil")
}

if result != nil {
t.Errorf("expected nil result on error, got: %v", result)
}
})

// Test case 4: Invalid format - no colon
t.Run("invalid_format_no_colon", func(t *testing.T) {
extraFiles := []string{"foobar"}

result, err := LoadExtras(extraFiles)
if err == nil {
t.Fatal("expected error for invalid format, got nil")
}

if result != nil {
t.Errorf("expected nil result on error, got: %v", result)
}
})

// Test case 5: Invalid format - empty key
t.Run("invalid_format_empty_key", func(t *testing.T) {
extraFiles := []string{"=" + filepath.Join(tempDir, "test.json")}

result, err := LoadExtras(extraFiles)
if err == nil {
t.Fatal("expected error for empty key, got nil")
}

if result != nil {
t.Errorf("expected nil result on error, got: %v", result)
}
})

// Test case 6: Invalid format - empty filepath
t.Run("invalid_format_empty_filepath", func(t *testing.T) {
extraFiles := []string{"key="}

result, err := LoadExtras(extraFiles)
if err == nil {
t.Fatal("expected error for empty filepath, got nil")
}

if result != nil {
t.Errorf("expected nil result on error, got: %v", result)
}
})

// Test case 7: Filepath with colons (e.g., Windows paths or URLs)
t.Run("filepath_with_colons", func(t *testing.T) {
filePath := filepath.Join(tempDir, "test.json")
fileContent := []byte("content")
if err := os.WriteFile(filePath, fileContent, 0644); err != nil {
t.Fatalf("failed to create test file: %v", err)
}

// Simulate a key with filepath that might have colons
extraFiles := []string{
"mykey=" + filePath,
}

result, err := LoadExtras(extraFiles)
if err != nil {
t.Fatalf("expected no error, got: %v", err)
}

if string(result["mykey"]) != string(fileContent) {
t.Errorf("expected %q, got %q", string(fileContent), string(result["mykey"]))
}
})

// Test case 8: Binary file content
t.Run("binary_content", func(t *testing.T) {
filePath := filepath.Join(tempDir, "binary.dat")
binaryContent := []byte{0x00, 0x01, 0x02, 0xFF, 0xFE, 0xFD}
if err := os.WriteFile(filePath, binaryContent, 0644); err != nil {
t.Fatalf("failed to create test file: %v", err)
}

extraFiles := []string{"binary=" + filePath}

result, err := LoadExtras(extraFiles)
if err != nil {
t.Fatalf("expected no error, got: %v", err)
}

if len(result["binary"]) != len(binaryContent) {
t.Errorf("expected length %d, got %d", len(binaryContent), len(result["binary"]))
}

for i, b := range binaryContent {
if result["binary"][i] != b {
t.Errorf("byte mismatch at index %d: expected %x, got %x", i, b, result["binary"][i])
}
}
})
}
18 changes: 15 additions & 3 deletions cmd/tokengen/cobra/pp/fabtokenv1/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"github.com/hyperledger-labs/fabric-token-sdk/cmd/tokengen/cobra/pp/cc"
"github.com/hyperledger-labs/fabric-token-sdk/cmd/tokengen/cobra/pp/common"
"github.com/hyperledger-labs/fabric-token-sdk/integration/nwo/token/generators/crypto/fabtokenv1"
v1 "github.com/hyperledger-labs/fabric-token-sdk/token/core/fabtoken/v1/setup"
setupv1 "github.com/hyperledger-labs/fabric-token-sdk/token/core/fabtoken/v1/setup"
"github.com/hyperledger-labs/fabric-token-sdk/token/driver"

"github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors"
Expand All @@ -34,6 +34,8 @@ var (
Auditors []string
// Version allows the caller of tokengen to override the version number put in the public params
Version uint
// Extras allows the caller to add extra parameters to the public parameters
Extras []string
)

// Cmd returns the Cobra Command for Version
Expand All @@ -45,6 +47,8 @@ func Cmd() *cobra.Command {
flags.StringSliceVarP(&Auditors, "auditors", "a", nil, "list of auditor MSP directories containing the corresponding auditor certificate")
flags.StringSliceVarP(&Issuers, "issuers", "s", nil, "list of issuer MSP directories containing the corresponding issuer certificate")
flags.UintVarP(&Version, "version", "v", 0, "allows the caller of tokengen to override the version number put in the public params")
flags.StringArrayVarP(&Extras, "extra", "x", []string{}, "extra data in key=value format, where is the path to a file containing the data to load and store in the key")

return cobraCommand
}

Expand Down Expand Up @@ -92,18 +96,26 @@ type GeneratorArgs struct {
// Gen generates the public parameters for the FabToken driver
func Gen(args *GeneratorArgs) ([]byte, error) {
// Setup
ver := v1.ProtocolV1
ver := setupv1.ProtocolV1
if Version != 0 {
ver = driver.TokenDriverVersion(Version)
}
pp, err := v1.SetupWithVersion(v1.DefaultPrecision, ver)
pp, err := setupv1.WithVersion(setupv1.DefaultPrecision, ver)
if err != nil {
return nil, errors.Wrap(err, "failed setting up public parameters")
}
if err := common.SetupIssuersAndAuditors(pp, args.Auditors, args.Issuers); err != nil {
return nil, err
}

// load extras
pp.ExtraData, err = common.LoadExtras(Extras)
if err != nil {
return nil, errors.Wrap(err, "failed loading extras")
}

// validate

// warn in case no issuers are specified
if len(pp.Issuers()) == 0 {
fmt.Println("No issuers specified. The public parameters allow anyone to create tokens.")
Expand Down
17 changes: 14 additions & 3 deletions cmd/tokengen/cobra/pp/zkatdlognoghv1/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
"github.com/hyperledger-labs/fabric-token-sdk/cmd/tokengen/cobra/pp/common"
"github.com/hyperledger-labs/fabric-token-sdk/cmd/tokengen/cobra/pp/idemix"
"github.com/hyperledger-labs/fabric-token-sdk/integration/nwo/token/generators/crypto/zkatdlognoghv1"
v1 "github.com/hyperledger-labs/fabric-token-sdk/token/core/zkatdlog/nogh/v1/setup"
setupv1 "github.com/hyperledger-labs/fabric-token-sdk/token/core/zkatdlog/nogh/v1/setup"
"github.com/hyperledger-labs/fabric-token-sdk/token/driver"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -64,6 +64,8 @@ var (
Aries bool
// Version allows the caller of tokengen to override the version number put in the public params
Version uint
// Extras allows the caller to add extra parameters to the public parameters
Extras []string
)

// Cmd returns the Cobra Command for Version
Expand All @@ -79,6 +81,7 @@ func Cmd() *cobra.Command {
flags.UintVarP(&Exponent, "exponent", "e", 2, "exponent is used to define the maximum quantity a token can contain as Base^Exponent")
flags.BoolVarP(&Aries, "aries", "r", false, "flag to indicate that aries should be used as backend for idemix")
flags.UintVarP(&Version, "version", "v", 0, "allows the caller of tokengen to override the version number put in the public params")
flags.StringArrayVarP(&Extras, "extra", "x", []string{}, "extra data in key=value format, where is the path to a file containing the data to load and store in the key")

return cobraCommand
}
Expand Down Expand Up @@ -134,17 +137,25 @@ func Gen(args *GeneratorArgs) ([]byte, error) {
curveID = math3.BLS12_381_BBS_GURVY
}
// todo range is hardcoded, to be changed
ver := v1.ProtocolV1
ver := setupv1.ProtocolV1
if args.Version != 0 {
ver = driver.TokenDriverVersion(args.Version)
}
pp, err := v1.SetupWithVersion(64, ipkBytes, curveID, ver)
pp, err := setupv1.WithVersion(64, ipkBytes, curveID, ver)
if err != nil {
return nil, errors.Wrap(err, "failed setting up public parameters")
}
if err := common.SetupIssuersAndAuditors(pp, args.Auditors, args.Issuers); err != nil {
return nil, errors.Wrap(err, "failed to setup issuer and auditors")
}

// load extras
pp.ExtraData, err = common.LoadExtras(Extras)
if err != nil {
return nil, errors.Wrap(err, "failed loading extras")
}

// validate
if err := pp.Validate(); err != nil {
return nil, errors.Wrapf(err, "failed to validate public parameters")
}
Expand Down
Loading
Loading