Skip to content

Commit

Permalink
Add the cipher test suite
Browse files Browse the repository at this point in the history
  • Loading branch information
Senyoret1 committed Jun 20, 2018
1 parent 2107932 commit 9e82c7d
Show file tree
Hide file tree
Showing 21 changed files with 7,272 additions and 1 deletion.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ gopherjs-tool.exe
gopherjs-tool
skycoin.js
skycoin.js.map

# dependencies
/node_modules

# temp files
/coverage
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ go:
install:
- go get -t ./...
- make install-linters
- npm install
- npm install --global source-map-support
- go get github.com/gopherjs/gopherjs
- cd $GOPATH/src/github.com/gopherjs/gopherjs/node-syscall/
Expand All @@ -20,6 +21,7 @@ install:
script:
- make check
- make build-js-min
- make test-suite-ts
- NODE_PATH=$(npm root --global) make test-js

notifications:
Expand Down
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,16 @@ build-js-min: ## Build /skycoin/skycoin.go. The result is minified and saved in
go build -o gopherjs-tool vendor/github.com/gopherjs/gopherjs/tool.go
GOOS=linux ./gopherjs-tool build skycoin/skycoin.go -m

test-js:
test-js: ## Run the Go tests using JavaScript
go build -o gopherjs-tool vendor/github.com/gopherjs/gopherjs/tool.go
./gopherjs-tool test ./skycoin/ -v

test-suite-ts: ## Run the ts version of the cipher test suite. Use a small number of test cases
npm run test

test-suite-ts-extensive: ## Run the ts version of the cipher test suite. All the test cases
npm run test-extensive

test:
go test ./... -timeout=10m -cover

Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ created starting from [mobile/api.go](mobile/api.go).

### Running tests

#### Gopherjs tests

gopherjs tests can be run with

```sh
Expand All @@ -50,6 +52,22 @@ npm install --global source-map-support

and make sure `NODE_PATH` is set to the value of `npm root --global` in your environment.

#### TS cipher test suite

The repository includes a TypeScript version of the cipher test suite, originally written in Go in
the Skycoin main repository. Because the tests take a significant amount of time to complete in
JavaScript/TypeScript, the test suite can be run with a limited number of cases with

```sh
make test-suite-ts
```

The test suite can be run with all test cases using

```sh
make test-suite-ts-extensive
```

### Formatting

All `.go` source files should be formatted `goimports`. You can do this with:
Expand Down
49 changes: 49 additions & 0 deletions karma.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/0.13/config/configuration-file.html

module.exports = function (config) {

var cipherParamIndex = process.argv.indexOf('--mode');
// check if command line has cipher parameter with not empty value
if (cipherParamIndex > -1 && (cipherParamIndex + 1) < process.argv.length && process.argv[cipherParamIndex + 1]) {
var cipherMode = process.argv[cipherParamIndex + 1];
}

config.set({
basePath: '',
frameworks: ['jasmine', 'karma-typescript'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-read-json'),
require('karma-typescript')
],
files: [
'tests/*.spec.ts',
{ pattern: 'tests/test-fixtures/*.golden', included: false },
{ pattern: 'tests/*.ts', included: true },
{ pattern: 'skycoin.js', included: true }
],
preprocessors: {
"**/*.ts": "karma-typescript"
},
client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
reporters: ['progress', 'kjhtml', 'karma-typescript'],
karmaTypescriptConfig: {
bundlerOptions: {
constants: {
"TESTING_MODE": cipherMode
}
}
},
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['ChromeHeadless', 'Chrome'],
singleRun: false
});
};
24 changes: 24 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "skycoin-lite",
"version": "0.0.0",
"scripts": {
"test": "karma start karma.conf.js -sm=false --watch=false --browsers ChromeHeadless --browserNoActivityTimeout=180000",
"test-extensive": "karma start karma.conf.js -sm=false --watch=false --browsers ChromeHeadless --browserNoActivityTimeout=180000 --mode 1"
},
"private": true,
"devDependencies": {
"@types/jasmine": "~2.5.53",
"@types/jasminewd2": "~2.0.2",
"@types/node": "~6.0.60",
"jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.1.0",
"karma": "~2.0.0",
"karma-chrome-launcher": "~2.1.1",
"karma-cli": "~1.0.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"karma-read-json": "^1.1.0",
"karma-typescript": "3.0.12",
"typescript": "~2.4.2"
}
}
190 changes: 190 additions & 0 deletions tests/cipher.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
import { readJSON } from 'karma-read-json';

import { Address, testCases, convertAsciiToHexa } from './utils'

declare var CipherExtras;
declare var Cipher;

declare var TESTING_MODE: string;

describe('CipherProvider Lib', () => {
const fixturesPath = 'tests/test-fixtures/';
const addressesFileName = 'many-addresses.golden';
const inputHashesFileName = 'input-hashes.golden';

const seedSignaturesFiles = [
'seed-0000.golden', 'seed-0001.golden', 'seed-0002.golden',
'seed-0003.golden', 'seed-0004.golden', 'seed-0005.golden',
'seed-0006.golden', 'seed-0007.golden', 'seed-0008.golden',
'seed-0009.golden', 'seed-0010.golden'
];

const extensiveMode = '1';

const testSettings = TESTING_MODE == extensiveMode
? { addressCount: 1000, seedFilesCount: 11 }
: { addressCount: 30, seedFilesCount: 1 };

describe('generate address', () => {
const addressFixtureFile = readJSON(fixturesPath + addressesFileName);
const expectedAddresses = addressFixtureFile.keys.slice(0, testSettings.addressCount);
let seed = convertAsciiToHexa(atob(addressFixtureFile.seed));
let generatedAddress;

testCases(expectedAddresses, (address: any) => {
it('should generate many address correctly', done => {
generatedAddress = generateAddress(seed);
seed = generatedAddress.next_seed;

const convertedAddress = {
address: generatedAddress.address,
public: generatedAddress.public_key,
secret: generatedAddress.secret_key
};

expect(convertedAddress).toEqual(address);
done();
});

it('should pass the verification', done => {
verifyAddress(generatedAddress);
done();
});
});
});

describe('seed signatures', () => {
const inputHashes = readJSON(fixturesPath + inputHashesFileName).hashes;

testCases(seedSignaturesFiles.slice(0, testSettings.seedFilesCount), (fileName: string) => {
describe(`should pass the verification for ${fileName}`, () => {
let seedKeys;
let actualAddresses;
let testData: { signature: string, public_key: string, hash: string, secret_key: string, address: string }[] = [];

beforeAll(() => {
const signaturesFixtureFile = readJSON(fixturesPath + fileName);
const seed = convertAsciiToHexa(atob(signaturesFixtureFile.seed));
seedKeys = signaturesFixtureFile.keys;

actualAddresses = generateAddresses(seed, seedKeys);
testData = getSeedTestData(inputHashes, seedKeys, actualAddresses);
});

it('should check number of signatures and hashes', done => {
const result = seedKeys.some(key => key.signatures.length !== inputHashes.length);

expect(result).toEqual(false);
done();
});

it('should generate many address correctly', done => {
actualAddresses.forEach((address, index) => {
expect(address.address).toEqual(seedKeys[index].address);
expect(address.public_key).toEqual(seedKeys[index].public);
expect(address.secret_key).toEqual(seedKeys[index].secret);
});

done();
});

it('address should pass the verification', done => {
verifyAddresses(actualAddresses);
done();
});

it(`should verify signature correctly`, done => {
testData.forEach(data => {
const result = CipherExtras.VerifySignature(data.public_key, data.signature, data.hash);
expect(result).toBeUndefined();
done();
});
});

it(`should check signature correctly`, done => {
testData.forEach(data => {
const result = CipherExtras.ChkSig(data.address, data.hash, data.signature);
expect(result).toBeUndefined();
done();
});
});

it(`should verify signed hash correctly`, done => {
testData.forEach(data => {
const result = CipherExtras.VerifySignedHash(data.signature, data.hash);
expect(result).toBeUndefined();
done();
});
});

it(`should generate public key correctly`, done => {
testData.forEach(data => {
const pubKey = CipherExtras.PubKeyFromSig(data.signature, data.hash);
expect(pubKey).toBeTruthy();
expect(pubKey === data.public_key).toBeTruthy();
done();
});
});

it(`sign hash should be created`, done => {
testData.forEach(data => {
const sig = CipherExtras.SignHash(data.hash, data.secret_key);
expect(sig).toBeTruthy();
done();
});
});
});
});
});
});

function getSeedTestData(inputHashes, seedKeys, actualAddresses) {
const data = [];

for (let seedIndex = 0; seedIndex < seedKeys.length; seedIndex++) {
for (let hashIndex = 0; hashIndex < inputHashes.length; hashIndex++) {
data.push({
signature: seedKeys[seedIndex].signatures[hashIndex],
public_key: actualAddresses[seedIndex].public_key,
secret_key: actualAddresses[seedIndex].secret_key,
address: actualAddresses[seedIndex].address,
hash: inputHashes[hashIndex]
});
}
}

return data;
}

function generateAddresses(seed: string, keys: any[]): Address[] {
return keys.map(() => {
const generatedAddress = generateAddress(seed);
seed = generatedAddress.next_seed;

return generatedAddress;
});
}

function generateAddress(seed: string): Address {
const address = Cipher.GenerateAddresses(seed);
return {
address: address.Address,
public_key: address.Public,
secret_key: address.Secret,
next_seed: address.NextSeed
};
}

function verifyAddress(address) {
const addressFromPubKey = CipherExtras.AddressFromPubKey(address.public_key);
const addressFromSecKey = CipherExtras.AddressFromSecKey(address.secret_key);

expect(addressFromPubKey && addressFromSecKey && addressFromPubKey === addressFromSecKey).toBe(true);

expect(CipherExtras.VerifySeckey(address.secret_key)).toBe(1);
expect(CipherExtras.VerifyPubkey(address.public_key)).toBe(1);
}

function verifyAddresses(addresses) {
addresses.forEach(address => verifyAddress(address));
}
14 changes: 14 additions & 0 deletions tests/test-fixtures/input-hashes.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"hashes": [
"66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925",
"72cd6e8422c407fb6d098690f1130b7ded7ec2f7f5e1d30bd9d521f015363793",
"1a964cd59841a8a64cf5a6f52da4a963c10fa92983f8694c8ee9a04294dafc92",
"cb142a76adc0893535989da9123848d3c1e97e49de10d86dc3a11a9db9e9b826",
"cc156b421b317e1a8ebfae0018a7dce45b0bfd9604dee57b333e3402350d8caf",
"528b5643c9f042faec41b0c31d341cdbc8531ded12d1d2b2851dd498967913eb",
"ad647b800dc8e21560da7643ee0b8979b22743492bc4bd04ac33d1c6ef3d6ba0",
"2e56c7beb552c2eff3b1ba5955614a8b264475f73a942b523190ea22857497b7",
"d8b005640029bf705a026ddb62f6e79500660044aa8fcf583cdd77c3017add03",
"e9f77b0528611d961c0825a93a3ad3e5be71d3fb5c6376cd87714a0d04098996"
]
}
Loading

0 comments on commit 9e82c7d

Please sign in to comment.