Skip to content
This repository has been archived by the owner on Dec 15, 2021. It is now read-only.

Commit

Permalink
Merge pull request #9 from stellar/sep10signers
Browse files Browse the repository at this point in the history
Add tests for SEP10 Signer Support
  • Loading branch information
msfeldstein authored Jan 26, 2020
2 parents e532e17 + bc40202 commit cdb8db7
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 3 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
reports
reports
junit.xml
148 changes: 148 additions & 0 deletions cases/sep10.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ import { fetch } from "./util/fetchShim";
import JWT from "jsonwebtoken";
import TOML from "toml";
import StellarSDK from "stellar-sdk";
import friendbot from "./util/friendbot";
import getSep10Token from "./util/sep10";

// Friendbot usage makes this very slow. Need to create an account pool at
// the beginning and reuse them.
jest.setTimeout(100000);
const url = process.env.DOMAIN;
const account = "GCQJX6WGG7SSFU2RBO5QANTFXY7C5GTTFJDCBAAO42JCCFIMZ7PEBURP";
const secret = "SAUOSXXF7ZDO5PKHRFR445DRKZ66Q5HIM2HIPQGWBTUKJZQAOP3VGH3L";
const keyPair = StellarSDK.Keypair.fromSecret(secret);
const server = new StellarSDK.Server("https://horizon-testnet.stellar.org");

describe("SEP10", () => {
let toml;
Expand Down Expand Up @@ -187,4 +193,146 @@ describe("SEP10", () => {
});
});
});

describe("signers support", () => {
afterAll(async () => {
console.log("DESTROY ALL FRIENDS");
await friendbot.destroyAllFriends();
});

/**
* Removing the masterWeight for an account means that it can
* no longer sign for itself. This should mean that it can't
* get a token with its own signature.
*/
it("fails for an account that can't sign for itself", async () => {
const accountA = StellarSDK.Keypair.random();
await friendbot(accountA);
const accountData = await server.loadAccount(accountA.publicKey());
const transaction = new StellarSDK.TransactionBuilder(accountData, {
fee: StellarSDK.BASE_FEE,
networkPassphrase: StellarSDK.Networks.TESTNET
})
.addOperation(
StellarSDK.Operation.setOptions({
masterWeight: 0
})
)
.setTimeout(30)
.build();
transaction.sign(accountA);
await server.submitTransaction(transaction);
const token = await getSep10Token(url, accountA, [accountA]);
expect(token).toBeFalsy();
});

it("succeeds for a signer of an account", async () => {
const userAccount = StellarSDK.Keypair.random();
const signerAccount = StellarSDK.Keypair.random();
await Promise.all([friendbot(userAccount), friendbot(signerAccount)]);
const accountData = await server.loadAccount(userAccount.publicKey());
const transaction = new StellarSDK.TransactionBuilder(accountData, {
fee: StellarSDK.BASE_FEE,
networkPassphrase: StellarSDK.Networks.TESTNET
})
.addOperation(
StellarSDK.Operation.setOptions({
lowThreshold: 1,
medThreshold: 1,
highThreshold: 1,
signer: {
ed25519PublicKey: signerAccount.publicKey(),
weight: 1
}
})
)
.setTimeout(30)
.build();
transaction.sign(userAccount);
await server.submitTransaction(transaction);
const token = await getSep10Token(url, userAccount, [signerAccount]);
expect(token).toBeTruthy();
});

/**
* In this test case, since we have a signer with only half the required
* weight of the thresholds, a malicious actor might try to sign twice
* with the same key hoping the server doesn't de-duplicate signers, and
* count its weight twice.
*/
it("fails when trying to reuse the same signer to gain weight", async () => {
const userAccount = StellarSDK.Keypair.random();
const signerAccount = StellarSDK.Keypair.random();
await Promise.all([friendbot(userAccount), friendbot(signerAccount)]);
const accountData = await server.loadAccount(userAccount.publicKey());
const transaction = new StellarSDK.TransactionBuilder(accountData, {
fee: StellarSDK.BASE_FEE,
networkPassphrase: StellarSDK.Networks.TESTNET
})
.addOperation(
StellarSDK.Operation.setOptions({
lowThreshold: 2,
medThreshold: 2,
highThreshold: 2,
signer: {
ed25519PublicKey: signerAccount.publicKey(),
weight: 1
}
})
)
.setTimeout(30)
.build();
transaction.sign(userAccount);
await server.submitTransaction(transaction);
const token = await getSep10Token(url, userAccount, [
signerAccount,
signerAccount
]);
expect(token).toBeFalsy();
});

it("succeeds with multiple signers", async () => {
const userAccount = StellarSDK.Keypair.random();
const signerAccount1 = StellarSDK.Keypair.random();
const signerAccount2 = StellarSDK.Keypair.random();
await Promise.all([
friendbot(userAccount),
friendbot(signerAccount1),
friendbot(signerAccount2)
]);
const accountData = await server.loadAccount(userAccount.publicKey());
const transaction = new StellarSDK.TransactionBuilder(accountData, {
fee: StellarSDK.BASE_FEE,
networkPassphrase: StellarSDK.Networks.TESTNET
})
.addOperation(
StellarSDK.Operation.setOptions({
lowThreshold: 2,
medThreshold: 2,
highThreshold: 2,
signer: {
ed25519PublicKey: signerAccount1.publicKey(),
weight: 1
}
})
)
.addOperation(
StellarSDK.Operation.setOptions({
signer: {
ed25519PublicKey: signerAccount2.publicKey(),
weight: 1
}
})
)
.setTimeout(30)
.build();
transaction.sign(userAccount);
await server.submitTransaction(transaction);
const token = await getSep10Token(url, userAccount, [
signerAccount1,
signerAccount2
]);
expect(token).toBeTruthy();
});
});
});
36 changes: 36 additions & 0 deletions cases/util/friendbot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { fetch } from "./fetchShim";
import StellarSdk from "stellar-sdk";

const friends = [];
async function friendbot(keyPair) {
const response = await fetch(
`https://friendbot.stellar.org/?addr=${keyPair.publicKey()}`
);
friends.push(keyPair);
expect(response.status).toEqual(200);
}

friendbot.destroyAllFriends = async function() {
if (friends.length === 0) return;
const accountData = await server.loadAccount(friends[0].publicKey());
const transactionBuilder = new StellarSDK.TransactionBuilder(accountData, {
fee: StellarSDK.BASE_FEE,
networkPassphrase: StellarSDK.Networks.TESTNET
});
friends.forEach(keyPair => {
transactionBuilder.addOperation(
StellarSdk.Operations.accountMerge({
destination: "GAIH3ULLFQ4DGSECF2AR555KZ4KNDGEKN4AFI4SU2M7B43MGK3QJZNSR",
source: keyPair.publicKey()
})
);
});

const tx = transactionBuilder.setTimeout(30).build();
friends.forEach(keyPair => {
tx.sign(keyPair);
});
await server.submitTransaction(tx);
};

export default friendbot;
7 changes: 5 additions & 2 deletions cases/util/sep10.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import TOML from "toml";
import StellarSDK from "stellar-sdk";
import { fetch } from "./fetchShim";

export default async function getSep10Token(domain, keyPair) {
export default async function getSep10Token(domain, keyPair, signers) {
if (!signers) signers = [keyPair];
let response = await fetch(domain + "/.well-known/stellar.toml");
const text = await response.text();
const toml = TOML.parse(text);
Expand All @@ -14,7 +15,9 @@ export default async function getSep10Token(domain, keyPair) {
json.transaction,
json.network_passphrase
);
tx.sign(keyPair);
signers.forEach(keyPair => {
tx.sign(keyPair);
});
let resp = await fetch(toml.WEB_AUTH_ENDPOINT, {
method: "POST",
headers: {
Expand Down

0 comments on commit cdb8db7

Please sign in to comment.