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

txnbuild: update challenge tx helpers for SEP-10 v1.3.0 #2071

Merged
merged 34 commits into from
Jan 29, 2020
Merged
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
7f8d793
txnbuild: update challenge tx helpers for sep-10 changes
leighmcculloch Dec 17, 2019
1bd551f
feedback from @ire-and-curses
leighmcculloch Dec 18, 2019
4fccf79
Merge branch 'master' into sep10prop
leighmcculloch Dec 20, 2019
ad17003
Add examples of using Horizon during verification
leighmcculloch Dec 21, 2019
c3a7169
Simplify the interface and make it easier to implement a check correctly
leighmcculloch Dec 21, 2019
828d6ec
Make example comments clearer
leighmcculloch Dec 21, 2019
3aacce3
Make the example more realistic by handling account not existing
leighmcculloch Dec 21, 2019
2432aed
Reduce dupe code
leighmcculloch Dec 21, 2019
b051ebc
Improve comments
leighmcculloch Dec 21, 2019
ab75f08
Merge branch 'master' into sep10prop
leighmcculloch Dec 21, 2019
3ca7923
Merge branch 'master' into sep10prop
leighmcculloch Jan 15, 2020
b419bad
add test
leighmcculloch Jan 15, 2020
56097e4
update comments
leighmcculloch Jan 15, 2020
fe76f9e
Add clarifying comment to deprecated func
leighmcculloch Jan 16, 2020
6492759
Add tests for VerifyChallengeTxThreshold
leighmcculloch Jan 16, 2020
846e396
Add check that some signers are provided
leighmcculloch Jan 16, 2020
a83ffec
Merge branch 'master' into sep10prop
leighmcculloch Jan 16, 2020
f20703f
Remove dependency on clients/horizon
leighmcculloch Jan 16, 2020
b7bec9f
Remove addition of protocols/horizon dependency
leighmcculloch Jan 21, 2020
731c0d4
Change how the signer data is copied from horizon to txnbuild
leighmcculloch Jan 22, 2020
d53c0b7
Fix the order of the signers that are outputted
leighmcculloch Jan 22, 2020
0a9dbc8
Moved SignerSummary to its own file
leighmcculloch Jan 22, 2020
99529e7
Fix bug in weight >= threshold check
leighmcculloch Jan 22, 2020
e2519cf
Fix tests failing due to slice ordering
leighmcculloch Jan 22, 2020
d3420d8
Fix test expectation
leighmcculloch Jan 22, 2020
2a9e88d
Merge branch 'master' into sep10prop
leighmcculloch Jan 24, 2020
330f692
Improve deprecated comment
leighmcculloch Jan 27, 2020
30a4ef9
Restructured some of the challenge transaction verification process t…
leighmcculloch Jan 28, 2020
3fedc4c
Remove unnecessary word in comment
leighmcculloch Jan 28, 2020
916a4cf
More consistent variable names
leighmcculloch Jan 28, 2020
fb8198b
Preserve the order of client signers throughout the whole process
leighmcculloch Jan 28, 2020
2a903e0
Add test proving duplicate signers in request are not included in errors
leighmcculloch Jan 28, 2020
0914d38
Add tests to all functions to ensure server key missing will fail, an…
leighmcculloch Jan 28, 2020
a7e3838
More meaningful error message if signer is a seed
leighmcculloch Jan 28, 2020
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
60 changes: 47 additions & 13 deletions txnbuild/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -546,34 +546,63 @@ func VerifyChallengeTxSigners(challengeTx, serverAccountID, network string, sign
return nil, errors.New("no signers provided")
}

// Read the transaction which validates its structure.
tx, _, err := ReadChallengeTx(challengeTx, serverAccountID, network)
if err != nil {
return nil, err
}

// Ensure the server account ID is an address and not a seed.
serverKP, err := keypair.ParseAddress(serverAccountID)
if err != nil {
return nil, err
}

// Remove the server signer from the signers list if it is present. It's
// important when verifying signers of a challenge transaction that we only
// verify and return client signers. If an account has the server as a
// signer the server should not play a part in the authentication of the
// client.
clientSigners := make([]string, 0, len(signers))
// Deduplicate the client signers and ensure the server is not included
// anywhere we check or output the list of signers.
clientSignersSet := map[string]struct{}{}
for _, signer := range signers {
// Ignore the server signer if it is in the signers list. It's
// important when verifying signers of a challenge transaction that we
// only verify and return client signers. If an account has the server
// as a signer the server should not play a part in the authentication
// of the client.
if signer == serverKP.Address() {
continue
}
clientSignersSet[signer] = struct{}{}
}
clientSigners := make([]string, 0, len(clientSignersSet))
for signer := range clientSignersSet {
clientSigners = append(clientSigners, signer)
}

signersFound, err := verifyTxSignatures(tx, clientSigners...)
// Verify that all the transaction's signers (server and client) in one
leighmcculloch marked this conversation as resolved.
Show resolved Hide resolved
// hit. We do this in one hit here even though the server signature was
// checked in the ReadChallengeTx to ensure that every signature and signer
// are consumed only once on the transaction.
allSigners := append([]string{serverKP.Address()}, clientSigners...)
allSignersFound, err := verifyTxSignatures(tx, allSigners...)
if err != nil {
return nil, err
}
if len(signersFound) != len(tx.xdrEnvelope.Signatures)-1 {

// Remove the server from the list of signers found.
signersFound := make([]string, 0, len(allSignersFound)-1)
for _, signer := range allSignersFound {
if signer == serverKP.Address() {
continue
}
signersFound = append(signersFound, signer)
}

// Confirm we found at least one client signer.
if len(signersFound) == 0 {
return nil, errors.Errorf("transaction not signed by %s", strings.Join(clientSigners, ", "))
}

// Confirm all signatures were consumed by a signer.
if len(allSignersFound) != len(tx.xdrEnvelope.Signatures) {
return signersFound, errors.Errorf("transaction has unrecognized signatures")
}

Expand Down Expand Up @@ -602,7 +631,10 @@ func VerifyChallengeTx(challengeTx, serverAccountID, network string) (bool, erro

// verifyTxSignature checks if a transaction has been signed by the provided Stellar account.
func verifyTxSignature(tx Transaction, signer string) error {
_, err := verifyTxSignatures(tx, signer)
signersFound, err := verifyTxSignatures(tx, signer)
if len(signersFound) == 0 {
return errors.Errorf("transaction not signed by %s", signer)
}
return err
}

Expand All @@ -620,27 +652,29 @@ func verifyTxSignatures(tx Transaction, signers ...string) ([]string, error) {
}

// find and verify signatures
signatureUsed := map[int]bool{}
signersFound := map[string]struct{}{}
for _, signer := range signers {
kp, err := keypair.ParseAddress(signer)
if err != nil {
return nil, err
}

for _, decSig := range tx.xdrEnvelope.Signatures {
for i, decSig := range tx.xdrEnvelope.Signatures {
if signatureUsed[i] {
continue
}
if decSig.Hint != kp.Hint() {
continue
}
err := kp.Verify(txHash[:], decSig.Signature)
if err == nil {
signatureUsed[i] = true
signersFound[signer] = struct{}{}
break
}
}
}
if len(signersFound) == 0 {
return nil, errors.Errorf("transaction not signed by %s", strings.Join(signers, ", "))
}

signersFoundList := make([]string, 0, len(signersFound))
for _, signer := range signers {
Expand Down