Skip to content

upgradability: key rotation of the auditor public key #1026

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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ jobs:
tests: [
dlog-fabric-t1,
dlog-fabric-t2,
dlog-fabric-t2.1,
dlog-fabric-t3,
dlog-fabric-t4,
dlog-fabric-t5,
Expand Down
5 changes: 2 additions & 3 deletions cmd/tokengen/cobra/pp/dlog/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (

"github.com/hyperledger-labs/fabric-token-sdk/cmd/tokengen/cobra/pp/common"
v1 "github.com/hyperledger-labs/fabric-token-sdk/token/core/zkatdlog/nogh/v1/setup"
"github.com/hyperledger-labs/fabric-token-sdk/token/driver"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -90,10 +89,10 @@ func Update(args *UpdateArgs) error {
// Clear auditor and issuers if provided, and add them again.
// If not provided, do not change them.
if len(args.Auditors) > 0 {
pp.Auditor = []byte{}
pp.SetAuditors(nil)
}
if len(args.Issuers) > 0 {
pp.IssuerIDs = []driver.Identity{}
pp.SetIssuers(nil)
}
if err := common.SetupIssuersAndAuditors(pp, args.Auditors, args.Issuers); err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion cmd/tokengen/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ func validateOutputEquivalent(gt *WithT, tempOutput, auditorsMSPdir, issuersMSPd
gt.Expect(err).NotTo(HaveOccurred())
gt.Expect(auditors[0]).To(Equal(auditor))

issuers := pp.IssuerIDs
issuers := pp.Issuers()
issuer, err := common.GetX509Identity(issuersMSPdir)
gt.Expect(err).NotTo(HaveOccurred())
gt.Expect(issuers[0]).To(BeEquivalentTo(issuer))
Expand Down
4 changes: 4 additions & 0 deletions fungible.mk
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ integration-tests-dlog-fabric-t1:
integration-tests-dlog-fabric-t2:
make integration-tests-dlog-fabric TEST_FILTER="T2"

.PHONY: integration-tests-dlog-fabric-t2.1
integration-tests-dlog-fabric-t2.1:
make integration-tests-dlog-fabric TEST_FILTER="T2.1"

.PHONY: integration-tests-dlog-fabric-t3
integration-tests-dlog-fabric-t3:
make integration-tests-dlog-fabric TEST_FILTER="T3"
Expand Down
19 changes: 16 additions & 3 deletions integration/token/fungible/dlog/dlog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,26 @@ var _ = Describe("EndToEnd", func() {
ts, selector := newTestSuite(t.CommType, Aries|WebEnabled, t.ReplicationFactor, "", "alice", "bob", "charlie")
BeforeEach(ts.Setup)
AfterEach(ts.TearDown)
It("Update public params", Label("T2"), func() {
It("Update public params (new auditor and issuer)", Label("T2"), func() {
fungible.TestPublicParamsUpdate(
ts.II,
"newAuditor",
fungible.PrepareUpdatedPublicParams(ts.II, "newAuditor", "default"),
fungible.PrepareUpdatedPublicParams(ts.II, "newAuditor", "newIssuer", "default", false),
"default",
false,
selector,
false,
)
})
It("Update public params (append new auditor and issuer)", Label("T2.1"), func() {
fungible.TestPublicParamsUpdate(
ts.II,
"newAuditor",
fungible.PrepareUpdatedPublicParams(ts.II, "newAuditor", "newIssuer", "default", true),
"default",
false,
selector,
true,
)
})
It("Test Identity Revocation", Label("T3"), func() { fungible.TestRevokeIdentity(ts.II, "auditor", selector) })
Expand All @@ -65,10 +77,11 @@ var _ = Describe("EndToEnd", func() {
fungible.TestPublicParamsUpdate(
ts.II,
"newIssuer",
fungible.PrepareUpdatedPublicParams(ts.II, "newIssuer", "default"),
fungible.PrepareUpdatedPublicParams(ts.II, "newIssuer", "newIssuer", "default", false),
"default",
true,
selector,
false,
)
})
})
Expand Down
2 changes: 1 addition & 1 deletion integration/token/fungible/fabtoken/fabtoken_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func UpdatePublicParams(network *integration.Infrastructure, selector *token2.Re
ppBytes, err := publicParam.Serialize()
Expect(err).NotTo(HaveOccurred())

fungible.TestPublicParamsUpdate(network, "newAuditor", ppBytes, "default", false, selector)
fungible.TestPublicParamsUpdate(network, "newAuditor", ppBytes, "default", false, selector, false)
}

func newTestSuite(commType fsc.P2PCommunicationType, factor int, names ...string) (*token2.TestSuite, *token2.ReplicaSelector) {
Expand Down
61 changes: 43 additions & 18 deletions integration/token/fungible/support.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,23 +93,41 @@ func IssueCash(network *integration.Infrastructure, wallet string, typ token.Typ
}

func IssueSuccessfulCash(network *integration.Infrastructure, wallet string, typ token.Type, amount uint64, receiver *token3.NodeReference, auditor *token3.NodeReference, anonymous bool, issuer *token3.NodeReference, finalities ...*token3.NodeReference) string {
return issueCashForTMSID(network, wallet, typ, amount, receiver, auditor, anonymous, issuer, nil, finalities, []string{})
return issueCashForTMSID(network, wallet, typ, amount, receiver, auditor, anonymous, issuer, nil, finalities, false, []string{})
}

func IssueCashForTMSID(network *integration.Infrastructure, wallet string, typ token.Type, amount uint64, receiver *token3.NodeReference, auditor *token3.NodeReference, anonymous bool, issuer *token3.NodeReference, tmsId *token2.TMSID, expectedErrorMsgs ...string) string {
return issueCashForTMSID(network, wallet, typ, amount, receiver, auditor, anonymous, issuer, tmsId, []*token3.NodeReference{}, expectedErrorMsgs)
}

func issueCashForTMSID(network *integration.Infrastructure, wallet string, typ token.Type, amount uint64, receiver *token3.NodeReference, auditor *token3.NodeReference, anonymous bool, issuer *token3.NodeReference, tmsId *token2.TMSID, endorsers []*token3.NodeReference, expectedErrorMsgs []string) string {
return issueCashForTMSID(network, wallet, typ, amount, receiver, auditor, anonymous, issuer, tmsId, []*token3.NodeReference{}, false, expectedErrorMsgs)
}

func IssueCashWithNoAuditorSigVerification(network *integration.Infrastructure, wallet string, typ token.Type, amount uint64, receiver *token3.NodeReference, auditor *token3.NodeReference, anonymous bool, issuer *token3.NodeReference, expectedErrorMsgs ...string) string {
return issueCashForTMSID(network, wallet, typ, amount, receiver, auditor, anonymous, issuer, nil, []*token3.NodeReference{}, true, expectedErrorMsgs)
}

func issueCashForTMSID(
network *integration.Infrastructure,
wallet string,
typ token.Type,
amount uint64,
receiver *token3.NodeReference,
auditor *token3.NodeReference,
anonymous bool,
issuer *token3.NodeReference,
tmsId *token2.TMSID,
endorsers []*token3.NodeReference,
skipAuditorSignatureVerification bool,
expectedErrorMsgs []string,
) string {
txIDBoxed, err := network.Client(issuer.ReplicaName()).CallView("issue", common.JSONMarshall(&views.IssueCash{
Anonymous: anonymous,
Auditor: auditor.Id(),
IssuerWallet: wallet,
TokenType: typ,
Quantity: amount,
Recipient: network.Identity(receiver.Id()),
RecipientEID: receiver.Id(),
TMSID: tmsId,
Anonymous: anonymous,
Auditor: auditor.Id(),
IssuerWallet: wallet,
TokenType: typ,
Quantity: amount,
Recipient: network.Identity(receiver.Id()),
RecipientEID: receiver.Id(),
TMSID: tmsId,
SkipAuditorSignatureVerification: skipAuditorSignatureVerification,
}))

topology.ToOptions(network.FscPlatform.Peers[0].Options).Endorser()
Expand Down Expand Up @@ -1369,10 +1387,10 @@ func MultiSigSpendCashForTMSID(network *integration.Infrastructure, sender *toke

}

func PrepareUpdatedPublicParams(network *integration.Infrastructure, auditor string, networkName string) []byte {
func PrepareUpdatedPublicParams(network *integration.Infrastructure, auditor string, issuer string, networkName string, appendIdentities bool) []byte {
tms := GetTMSByNetworkName(network, networkName)
auditorId := GetAuditorIdentity(tms, auditor)
issuerId := GetIssuerIdentity(tms, "newIssuer")
issuerId := GetIssuerIdentity(tms, issuer)

tokenPlatform, ok := network.Ctx.PlatformsByName["token"].(*tplatform.Platform)
Expect(ok).To(BeTrue(), "failed to get token platform from context")
Expand All @@ -1389,6 +1407,8 @@ func PrepareUpdatedPublicParams(network *integration.Infrastructure, auditor str
Serialize() ([]byte, error)
SetIssuers(identities []driver.Identity)
SetAuditors(identities []driver.Identity)
AddAuditor(identity2 driver.Identity)
AddIssuer(identity2 driver.Identity)
}
var pp PP
switch genericPP.Identifier {
Expand All @@ -1399,12 +1419,17 @@ func PrepareUpdatedPublicParams(network *integration.Infrastructure, auditor str
pp, err = fabtokenv1.NewPublicParamsFromBytes(ppBytes, fabtokenv1.PublicParameters)
Expect(err).NotTo(HaveOccurred())
default:
Expect(false).To(BeTrue(), "unknown pp identitfier [%s]", genericPP.Identifier)
Expect(false).To(BeTrue(), "unknown pp identifier [%s]", genericPP.Identifier)
}

Expect(pp.Validate()).NotTo(HaveOccurred())
pp.SetAuditors([]driver.Identity{auditorId})
pp.SetIssuers([]driver.Identity{issuerId})
if appendIdentities {
pp.AddAuditor(auditorId)
pp.AddIssuer(issuerId)
} else {
pp.SetAuditors([]driver.Identity{auditorId})
pp.SetIssuers([]driver.Identity{issuerId})
}

// Serialize
ppBytes, err = pp.Serialize()
Expand Down
16 changes: 13 additions & 3 deletions integration/token/fungible/tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -847,15 +847,14 @@ func TestSelector(network *integration.Infrastructure, auditorId string, sel *to
TransferCash(network, alice, "", "USD", 160, bob, auditor, "insufficient funds, only [150] tokens of type [USD] are available")
}

func TestPublicParamsUpdate(network *integration.Infrastructure, newAuditorID string, ppBytes []byte, networkName string, issuerAsAuditor bool, sel *token3.ReplicaSelector) {
func TestPublicParamsUpdate(network *integration.Infrastructure, newAuditorID string, ppBytes []byte, networkName string, issuerAsAuditor bool, sel *token3.ReplicaSelector, updateWithAppend bool) {
newAuditor := sel.Get(newAuditorID)
tms := GetTMSByNetworkName(network, networkName)
newIssuer := sel.Get("newIssuer")
issuer := sel.Get("issuer")
alice := sel.Get("alice")
manager := sel.Get("manager")
auditor := sel.Get("auditor")
errorMessage := "is not in issuers"
if issuerAsAuditor {
auditor = issuer
}
Expand Down Expand Up @@ -886,7 +885,18 @@ func TestPublicParamsUpdate(network *integration.Infrastructure, newAuditorID st
Expect(txId).NotTo(BeEmpty())
CheckBalance(network, alice, "", "USD", 220)
CheckHolding(network, alice, "", "USD", 110, newAuditor)
IssueCash(network, "", "USD", 110, alice, newAuditor, true, issuer, errorMessage)
if updateWithAppend {
IssueCash(network, "", "USD", 110, alice, newAuditor, true, issuer)
} else {
IssueCash(network, "", "USD", 110, alice, newAuditor, true, issuer, "is not in issuers")
}
if newAuditorID != "auditor" {
if updateWithAppend {
IssueCash(network, "", "USD", 110, alice, auditor, true, newIssuer)
} else {
IssueCashWithNoAuditorSigVerification(network, "", "USD", 110, alice, auditor, true, newIssuer, "is not in auditors")
}
}

CheckOwnerWalletIDs(network, manager, "manager.id1", "manager.id2", "manager.id3")
}
Expand Down
8 changes: 7 additions & 1 deletion integration/token/fungible/views/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ type IssueCash struct {
RecipientWalletID string
// RecipientEID is the expected enrolment id of the recipient
RecipientEID string
// SkipAuditorSignatureVerification set to true to skip the verification of the auditor signature during endorsement collection
SkipAuditorSignatureVerification bool
}

type IssueCashView struct {
Expand Down Expand Up @@ -116,7 +118,11 @@ func (p *IssueCashView) Call(context view.Context) (interface{}, error) {
// Before completing, all recipients receive the approved transaction.
// Depending on the token driver implementation, the recipient's signature might or might not be needed to make
// the token transaction valid.
_, err = context.RunView(ttx.NewCollectEndorsementsView(tx))
var eOpts []ttx.EndorsementsOpt
if p.SkipAuditorSignatureVerification {
eOpts = append(eOpts, ttx.WithSkipAuditorSignatureVerification())
}
_, err = context.RunView(ttx.NewCollectEndorsementsView(tx, eOpts...))
assert.NoError(err, "failed to sign issue transaction for "+tx.ID())

// Sanity checks:
Expand Down
Loading