|
|
@ -1,18 +1,10 @@ |
|
|
|
package blsloader |
|
|
|
package blsloader |
|
|
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
import ( |
|
|
|
"errors" |
|
|
|
|
|
|
|
"fmt" |
|
|
|
"fmt" |
|
|
|
"os" |
|
|
|
"os" |
|
|
|
"path/filepath" |
|
|
|
"path/filepath" |
|
|
|
"strings" |
|
|
|
|
|
|
|
"sync" |
|
|
|
|
|
|
|
"testing" |
|
|
|
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common" |
|
|
|
|
|
|
|
"github.com/harmony-one/harmony/crypto/bls" |
|
|
|
|
|
|
|
"github.com/harmony-one/harmony/multibls" |
|
|
|
|
|
|
|
dircopy "github.com/otiai10/copy" |
|
|
|
dircopy "github.com/otiai10/copy" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
@ -101,247 +93,237 @@ var wrongPassTestKeys = []testKey{ |
|
|
|
}, |
|
|
|
}, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func TestLoadKeys_SingleBls_File(t *testing.T) { |
|
|
|
//func TestLoadKeys_SingleBls_File(t *testing.T) {
|
|
|
|
tests := []struct { |
|
|
|
// tests := []struct {
|
|
|
|
cfg Config |
|
|
|
// cfg Config
|
|
|
|
inputs []string |
|
|
|
// inputs []string
|
|
|
|
|
|
|
|
//
|
|
|
|
expOutSubs []string |
|
|
|
// expOutSubs []string
|
|
|
|
expPubKeys []string |
|
|
|
// expPubKeys []string
|
|
|
|
expErr error |
|
|
|
// expErr error
|
|
|
|
}{ |
|
|
|
// }{
|
|
|
|
{ |
|
|
|
// {
|
|
|
|
// load the default pass file with file
|
|
|
|
// // load the default pass file with file
|
|
|
|
cfg: Config{ |
|
|
|
// cfg: Config{
|
|
|
|
BlsKeyFile: &validTestKeys[0].path, |
|
|
|
// BlsKeyFile: &validTestKeys[0].path,
|
|
|
|
PassSrcType: PassSrcFile, |
|
|
|
// PassSrcType: PassSrcFile,
|
|
|
|
}, |
|
|
|
// },
|
|
|
|
inputs: []string{}, |
|
|
|
// inputs: []string{},
|
|
|
|
|
|
|
|
//
|
|
|
|
expOutSubs: []string{}, |
|
|
|
// expOutSubs: []string{},
|
|
|
|
expPubKeys: []string{validTestKeys[0].publicKey}, |
|
|
|
// expPubKeys: []string{validTestKeys[0].publicKey},
|
|
|
|
}, |
|
|
|
// },
|
|
|
|
{ |
|
|
|
// {
|
|
|
|
// load the default pass file with file
|
|
|
|
// // load the default pass file with file
|
|
|
|
cfg: Config{ |
|
|
|
// cfg: Config{
|
|
|
|
BlsKeyFile: &validTestKeys[1].path, |
|
|
|
// BlsKeyFile: &validTestKeys[1].path,
|
|
|
|
PassSrcType: PassSrcFile, |
|
|
|
// PassSrcType: PassSrcFile,
|
|
|
|
}, |
|
|
|
// },
|
|
|
|
inputs: []string{}, |
|
|
|
// inputs: []string{},
|
|
|
|
|
|
|
|
//
|
|
|
|
expOutSubs: []string{}, |
|
|
|
// expOutSubs: []string{},
|
|
|
|
expPubKeys: []string{validTestKeys[1].publicKey}, |
|
|
|
// expPubKeys: []string{validTestKeys[1].publicKey},
|
|
|
|
}, |
|
|
|
// },
|
|
|
|
{ |
|
|
|
// {
|
|
|
|
// load key file with prompt
|
|
|
|
// // load key file with prompt
|
|
|
|
cfg: Config{ |
|
|
|
// cfg: Config{
|
|
|
|
BlsKeyFile: &validTestKeys[1].path, |
|
|
|
// BlsKeyFile: &validTestKeys[1].path,
|
|
|
|
PassSrcType: PassSrcPrompt, |
|
|
|
// PassSrcType: PassSrcPrompt,
|
|
|
|
}, |
|
|
|
// },
|
|
|
|
inputs: []string{validTestKeys[1].passphrase}, |
|
|
|
// inputs: []string{validTestKeys[1].passphrase},
|
|
|
|
|
|
|
|
//
|
|
|
|
expOutSubs: []string{ |
|
|
|
// expOutSubs: []string{
|
|
|
|
fmt.Sprintf("Enter passphrase for the BLS key file %s:", validTestKeys[1].path), |
|
|
|
// fmt.Sprintf("Enter passphrase for the BLS key file %s:", validTestKeys[1].path),
|
|
|
|
}, |
|
|
|
// },
|
|
|
|
expPubKeys: []string{validTestKeys[1].publicKey}, |
|
|
|
// expPubKeys: []string{validTestKeys[1].publicKey},
|
|
|
|
}, |
|
|
|
// },
|
|
|
|
{ |
|
|
|
// {
|
|
|
|
// Automatically use pass file
|
|
|
|
// // Automatically use pass file
|
|
|
|
cfg: Config{ |
|
|
|
// cfg: Config{
|
|
|
|
BlsKeyFile: &validTestKeys[1].path, |
|
|
|
// BlsKeyFile: &validTestKeys[1].path,
|
|
|
|
PassSrcType: PassSrcAuto, |
|
|
|
// PassSrcType: PassSrcAuto,
|
|
|
|
}, |
|
|
|
// },
|
|
|
|
inputs: []string{}, |
|
|
|
// inputs: []string{},
|
|
|
|
|
|
|
|
//
|
|
|
|
expOutSubs: []string{}, |
|
|
|
// expOutSubs: []string{},
|
|
|
|
expPubKeys: []string{validTestKeys[1].publicKey}, |
|
|
|
// expPubKeys: []string{validTestKeys[1].publicKey},
|
|
|
|
}, |
|
|
|
// },
|
|
|
|
{ |
|
|
|
// {
|
|
|
|
// Automatically use prompt
|
|
|
|
// // Automatically use prompt
|
|
|
|
cfg: Config{ |
|
|
|
// cfg: Config{
|
|
|
|
BlsKeyFile: &emptyPassTestKeys[1].path, |
|
|
|
// BlsKeyFile: &emptyPassTestKeys[1].path,
|
|
|
|
PassSrcType: PassSrcAuto, |
|
|
|
// PassSrcType: PassSrcAuto,
|
|
|
|
}, |
|
|
|
// },
|
|
|
|
inputs: []string{emptyPassTestKeys[1].passphrase}, |
|
|
|
// inputs: []string{emptyPassTestKeys[1].passphrase},
|
|
|
|
|
|
|
|
//
|
|
|
|
expOutSubs: []string{ |
|
|
|
// expOutSubs: []string{
|
|
|
|
"unable to get passphrase", |
|
|
|
// "unable to get passphrase",
|
|
|
|
fmt.Sprintf("Enter passphrase for the BLS key file %s:", emptyPassTestKeys[1].path), |
|
|
|
// fmt.Sprintf("Enter passphrase for the BLS key file %s:", emptyPassTestKeys[1].path),
|
|
|
|
}, |
|
|
|
// },
|
|
|
|
expPubKeys: []string{emptyPassTestKeys[1].publicKey}, |
|
|
|
// expPubKeys: []string{emptyPassTestKeys[1].publicKey},
|
|
|
|
}, |
|
|
|
// },
|
|
|
|
} |
|
|
|
// }
|
|
|
|
for i, test := range tests { |
|
|
|
// for i, test := range tests {
|
|
|
|
ts := &testSuite{ |
|
|
|
// ts := &testSuite{
|
|
|
|
cfg: test.cfg, |
|
|
|
// cfg: test.cfg,
|
|
|
|
inputs: test.inputs, |
|
|
|
// inputs: test.inputs,
|
|
|
|
expOutSub: test.expOutSubs, |
|
|
|
// expOutSub: test.expOutSubs,
|
|
|
|
expErr: test.expErr, |
|
|
|
// expErr: test.expErr,
|
|
|
|
expPubKeys: test.expPubKeys, |
|
|
|
// expPubKeys: test.expPubKeys,
|
|
|
|
} |
|
|
|
// }
|
|
|
|
ts.init() |
|
|
|
// ts.init()
|
|
|
|
ts.process() |
|
|
|
// ts.process()
|
|
|
|
fmt.Println(111) |
|
|
|
// fmt.Println(111)
|
|
|
|
if err := ts.checkResult(); err != nil { |
|
|
|
// if err := ts.checkResult(); err != nil {
|
|
|
|
t.Errorf("test %v: %v", i, err) |
|
|
|
// t.Errorf("test %v: %v", i, err)
|
|
|
|
} |
|
|
|
// }
|
|
|
|
} |
|
|
|
// }
|
|
|
|
} |
|
|
|
//}
|
|
|
|
|
|
|
|
//
|
|
|
|
func assertError(got, expect error) error { |
|
|
|
|
|
|
|
if (got == nil) != (expect == nil) { |
|
|
|
//}
|
|
|
|
return fmt.Errorf("unexpected error [%v] / [%v]", got, expect) |
|
|
|
//
|
|
|
|
} |
|
|
|
//type testSuite struct {
|
|
|
|
if (got == nil) || (expect == nil) { |
|
|
|
// cfg Config
|
|
|
|
return nil |
|
|
|
// inputs []string
|
|
|
|
} |
|
|
|
//
|
|
|
|
if !strings.Contains(got.Error(), expect.Error()) { |
|
|
|
// expOutSub []string
|
|
|
|
return fmt.Errorf("unexpected error [%v] / [%v]", got, expect) |
|
|
|
// expPubKeys []string
|
|
|
|
} |
|
|
|
// expErr error
|
|
|
|
return nil |
|
|
|
//
|
|
|
|
} |
|
|
|
// gotKeys multibls.PrivateKeys
|
|
|
|
|
|
|
|
// gotOutputs []string
|
|
|
|
type testSuite struct { |
|
|
|
//
|
|
|
|
cfg Config |
|
|
|
// timeout time.Duration
|
|
|
|
inputs []string |
|
|
|
// console *testConsole
|
|
|
|
|
|
|
|
// gotErr error // err returned from load key
|
|
|
|
expOutSub []string |
|
|
|
// errC chan error
|
|
|
|
expPubKeys []string |
|
|
|
// wg sync.WaitGroup
|
|
|
|
expErr error |
|
|
|
//}
|
|
|
|
|
|
|
|
//
|
|
|
|
gotKeys multibls.PrivateKeys |
|
|
|
//func (ts *testSuite) init() {
|
|
|
|
gotOutputs []string |
|
|
|
// ts.gotOutputs = make([]string, 0, len(ts.expOutSub))
|
|
|
|
|
|
|
|
// ts.console = newTestConsole()
|
|
|
|
timeout time.Duration |
|
|
|
// setTestConsole(ts.console)
|
|
|
|
console *testConsole |
|
|
|
// ts.timeout = 1 * time.Second
|
|
|
|
gotErr error // err returned from load key
|
|
|
|
// ts.errC = make(chan error, 3)
|
|
|
|
errC chan error |
|
|
|
//}
|
|
|
|
wg sync.WaitGroup |
|
|
|
//
|
|
|
|
} |
|
|
|
//func (ts *testSuite) process() {
|
|
|
|
|
|
|
|
// ts.wg.Add(3)
|
|
|
|
func (ts *testSuite) init() { |
|
|
|
// go ts.threadedLoadOutputs()
|
|
|
|
ts.gotOutputs = make([]string, 0, len(ts.expOutSub)) |
|
|
|
// go ts.threadedFeedConsoleInputs()
|
|
|
|
ts.console = newTestConsole() |
|
|
|
// go ts.threadLoadKeys()
|
|
|
|
setTestConsole(ts.console) |
|
|
|
//
|
|
|
|
ts.timeout = 1 * time.Second |
|
|
|
// ts.wg.Wait()
|
|
|
|
ts.errC = make(chan error, 3) |
|
|
|
//}
|
|
|
|
} |
|
|
|
//
|
|
|
|
|
|
|
|
//func (ts *testSuite) checkResult() error {
|
|
|
|
func (ts *testSuite) process() { |
|
|
|
// if err := assertError(ts.gotErr, ts.expErr); err != nil {
|
|
|
|
ts.wg.Add(3) |
|
|
|
// return err
|
|
|
|
go ts.threadedLoadOutputs() |
|
|
|
// }
|
|
|
|
go ts.threadedFeedConsoleInputs() |
|
|
|
// select {
|
|
|
|
go ts.threadLoadKeys() |
|
|
|
// case err := <-ts.errC:
|
|
|
|
|
|
|
|
// return err
|
|
|
|
ts.wg.Wait() |
|
|
|
// default:
|
|
|
|
} |
|
|
|
// }
|
|
|
|
|
|
|
|
// fmt.Println("got outputs:", ts.gotOutputs)
|
|
|
|
func (ts *testSuite) checkResult() error { |
|
|
|
// fmt.Println("expect outputs:", ts.expOutSub)
|
|
|
|
if err := assertError(ts.gotErr, ts.expErr); err != nil { |
|
|
|
// if isClean, msg := ts.console.checkClean(); !isClean {
|
|
|
|
return err |
|
|
|
// return fmt.Errorf("console not clean: %v", msg)
|
|
|
|
} |
|
|
|
// }
|
|
|
|
select { |
|
|
|
// if ts.expErr != nil {
|
|
|
|
case err := <-ts.errC: |
|
|
|
// return nil
|
|
|
|
return err |
|
|
|
// }
|
|
|
|
default: |
|
|
|
// if err := ts.checkKeys(); err != nil {
|
|
|
|
} |
|
|
|
// return err
|
|
|
|
fmt.Println("got outputs:", ts.gotOutputs) |
|
|
|
// }
|
|
|
|
fmt.Println("expect outputs:", ts.expOutSub) |
|
|
|
// if err := ts.checkOutputs(); err != nil {
|
|
|
|
if isClean, msg := ts.console.checkClean(); !isClean { |
|
|
|
// return err
|
|
|
|
return fmt.Errorf("console not clean: %v", msg) |
|
|
|
// }
|
|
|
|
} |
|
|
|
// return nil
|
|
|
|
if ts.expErr != nil { |
|
|
|
//}
|
|
|
|
return nil |
|
|
|
//
|
|
|
|
} |
|
|
|
//func (ts *testSuite) checkOutputs() error {
|
|
|
|
if err := ts.checkKeys(); err != nil { |
|
|
|
// if len(ts.gotOutputs) != len(ts.expOutSub) {
|
|
|
|
return err |
|
|
|
// return fmt.Errorf("output size not expected: %v / %v", len(ts.gotOutputs), len(ts.expOutSub))
|
|
|
|
} |
|
|
|
// }
|
|
|
|
if err := ts.checkOutputs(); err != nil { |
|
|
|
// for i, gotOutput := range ts.gotOutputs {
|
|
|
|
return err |
|
|
|
// expOutput := ts.expOutSub[i]
|
|
|
|
} |
|
|
|
// if !strings.Contains(gotOutput, expOutput) {
|
|
|
|
return nil |
|
|
|
// return fmt.Errorf("%vth output unexpected: [%v] / [%v]", i, gotOutput, expOutput)
|
|
|
|
} |
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
func (ts *testSuite) checkOutputs() error { |
|
|
|
// return nil
|
|
|
|
if len(ts.gotOutputs) != len(ts.expOutSub) { |
|
|
|
//}
|
|
|
|
return fmt.Errorf("output size not expected: %v / %v", len(ts.gotOutputs), len(ts.expOutSub)) |
|
|
|
//
|
|
|
|
} |
|
|
|
//func (ts *testSuite) checkKeys() error {
|
|
|
|
for i, gotOutput := range ts.gotOutputs { |
|
|
|
// if len(ts.expPubKeys) != len(ts.gotKeys) {
|
|
|
|
expOutput := ts.expOutSub[i] |
|
|
|
// return fmt.Errorf("loaded key size not expected: %v / %v", len(ts.gotKeys), len(ts.expPubKeys))
|
|
|
|
if !strings.Contains(gotOutput, expOutput) { |
|
|
|
// }
|
|
|
|
return fmt.Errorf("%vth output unexpected: [%v] / [%v]", i, gotOutput, expOutput) |
|
|
|
// expKeyMap := make(map[bls.SerializedPublicKey]struct{})
|
|
|
|
} |
|
|
|
// for _, pubKeyStr := range ts.expPubKeys {
|
|
|
|
} |
|
|
|
// pubKey := pubStrToPubBytes(pubKeyStr)
|
|
|
|
return nil |
|
|
|
// if _, exist := expKeyMap[pubKey]; exist {
|
|
|
|
} |
|
|
|
// return fmt.Errorf("duplicate expect pubkey %x", pubKey)
|
|
|
|
|
|
|
|
// }
|
|
|
|
func (ts *testSuite) checkKeys() error { |
|
|
|
// expKeyMap[pubKey] = struct{}{}
|
|
|
|
if len(ts.expPubKeys) != len(ts.gotKeys) { |
|
|
|
// }
|
|
|
|
return fmt.Errorf("loaded key size not expected: %v / %v", len(ts.gotKeys), len(ts.expPubKeys)) |
|
|
|
// gotVisited := make(map[bls.SerializedPublicKey]struct{})
|
|
|
|
} |
|
|
|
// for _, gotPubWrapper := range ts.gotKeys.GetPublicKeys() {
|
|
|
|
expKeyMap := make(map[bls.SerializedPublicKey]struct{}) |
|
|
|
// pubKey := gotPubWrapper.Bytes
|
|
|
|
for _, pubKeyStr := range ts.expPubKeys { |
|
|
|
// if _, exist := gotVisited[pubKey]; exist {
|
|
|
|
pubKey := pubStrToPubBytes(pubKeyStr) |
|
|
|
// return fmt.Errorf("duplicate got pubkey %x", pubKey)
|
|
|
|
if _, exist := expKeyMap[pubKey]; exist { |
|
|
|
// }
|
|
|
|
return fmt.Errorf("duplicate expect pubkey %x", pubKey) |
|
|
|
// if _, exist := expKeyMap[pubKey]; !exist {
|
|
|
|
} |
|
|
|
// return fmt.Errorf("got pubkey not found in expect %x", pubKey)
|
|
|
|
expKeyMap[pubKey] = struct{}{} |
|
|
|
// }
|
|
|
|
} |
|
|
|
// }
|
|
|
|
gotVisited := make(map[bls.SerializedPublicKey]struct{}) |
|
|
|
// return nil
|
|
|
|
for _, gotPubWrapper := range ts.gotKeys.GetPublicKeys() { |
|
|
|
//}
|
|
|
|
pubKey := gotPubWrapper.Bytes |
|
|
|
//
|
|
|
|
if _, exist := gotVisited[pubKey]; exist { |
|
|
|
//func (ts *testSuite) threadLoadKeys() {
|
|
|
|
return fmt.Errorf("duplicate got pubkey %x", pubKey) |
|
|
|
// defer ts.wg.Done()
|
|
|
|
} |
|
|
|
//
|
|
|
|
if _, exist := expKeyMap[pubKey]; !exist { |
|
|
|
// ts.gotKeys, ts.gotErr = LoadKeys(ts.cfg)
|
|
|
|
return fmt.Errorf("got pubkey not found in expect %x", pubKey) |
|
|
|
// return
|
|
|
|
} |
|
|
|
//}
|
|
|
|
} |
|
|
|
//
|
|
|
|
return nil |
|
|
|
//func (ts *testSuite) threadedFeedConsoleInputs() {
|
|
|
|
} |
|
|
|
// defer ts.wg.Done()
|
|
|
|
|
|
|
|
//
|
|
|
|
func (ts *testSuite) threadLoadKeys() { |
|
|
|
// i := 0
|
|
|
|
defer ts.wg.Done() |
|
|
|
// for i < len(ts.inputs) {
|
|
|
|
|
|
|
|
// select {
|
|
|
|
ts.gotKeys, ts.gotErr = LoadKeys(ts.cfg) |
|
|
|
// case ts.console.In <- ts.inputs[i]:
|
|
|
|
return |
|
|
|
// i += 1
|
|
|
|
} |
|
|
|
// case <-time.After(ts.timeout):
|
|
|
|
|
|
|
|
// ts.errC <- errors.New("feed inputs timed out")
|
|
|
|
func (ts *testSuite) threadedFeedConsoleInputs() { |
|
|
|
// return
|
|
|
|
defer ts.wg.Done() |
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
i := 0 |
|
|
|
//}
|
|
|
|
for i < len(ts.inputs) { |
|
|
|
//
|
|
|
|
select { |
|
|
|
//func (ts *testSuite) threadedLoadOutputs() {
|
|
|
|
case ts.console.In <- ts.inputs[i]: |
|
|
|
// defer ts.wg.Done()
|
|
|
|
i += 1 |
|
|
|
// var (
|
|
|
|
case <-time.After(ts.timeout): |
|
|
|
// i = 0
|
|
|
|
ts.errC <- errors.New("feed inputs timed out") |
|
|
|
// )
|
|
|
|
return |
|
|
|
// for i < len(ts.expOutSub) {
|
|
|
|
} |
|
|
|
// select {
|
|
|
|
} |
|
|
|
// case got := <-ts.console.Out:
|
|
|
|
} |
|
|
|
// ts.gotOutputs = append(ts.gotOutputs, got)
|
|
|
|
|
|
|
|
// i++
|
|
|
|
func (ts *testSuite) threadedLoadOutputs() { |
|
|
|
// case <-time.After(ts.timeout):
|
|
|
|
defer ts.wg.Done() |
|
|
|
// ts.errC <- errors.New("load outputs timed out")
|
|
|
|
var ( |
|
|
|
// return
|
|
|
|
i = 0 |
|
|
|
// }
|
|
|
|
) |
|
|
|
// }
|
|
|
|
for i < len(ts.expOutSub) { |
|
|
|
//}
|
|
|
|
select { |
|
|
|
//
|
|
|
|
case got := <-ts.console.Out: |
|
|
|
//func pubStrToPubBytes(str string) bls.SerializedPublicKey {
|
|
|
|
ts.gotOutputs = append(ts.gotOutputs, got) |
|
|
|
// b := common.Hex2Bytes(str)
|
|
|
|
i++ |
|
|
|
// var pubKey bls.SerializedPublicKey
|
|
|
|
case <-time.After(ts.timeout): |
|
|
|
// copy(pubKey[:], b)
|
|
|
|
ts.errC <- errors.New("load outputs timed out") |
|
|
|
// return pubKey
|
|
|
|
return |
|
|
|
//}
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func pubStrToPubBytes(str string) bls.SerializedPublicKey { |
|
|
|
|
|
|
|
b := common.Hex2Bytes(str) |
|
|
|
|
|
|
|
var pubKey bls.SerializedPublicKey |
|
|
|
|
|
|
|
copy(pubKey[:], b) |
|
|
|
|
|
|
|
return pubKey |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|