Add measurement of validator status fetching operations

This commit is contained in:
Jim McDonald 2020-10-09 16:07:42 +01:00
parent 7196a90d29
commit 469e6a02a3
No known key found for this signature in database
GPG Key ID: 89CEB61B2AD2A5E7
30 changed files with 3385 additions and 9 deletions

View File

@ -1,4 +1,6 @@
Development
- add measurement of validator status fetching operations
- increase maximum block receipt delay metric from 4s to 12s
- add internal ability to list names of all active scheduler jobs
- ensure duplicated attestations are only counted as 1 in block proposal score
- ensure genesis attesters are scheduled appropriately

View File

@ -499,6 +499,7 @@ func startAccountManager(ctx context.Context, monitor metrics.Service, eth2Clien
accountManager, err = dirkaccountmanager.New(ctx,
dirkaccountmanager.WithLogLevel(logLevel(viper.GetString("accountmanager.dirk.log-level"))),
dirkaccountmanager.WithMonitor(monitor.(metrics.AccountManagerMonitor)),
dirkaccountmanager.WithClientMonitor(monitor.(metrics.ClientMonitor)),
dirkaccountmanager.WithValidatorsProvider(eth2Client.(eth2client.ValidatorsProvider)),
dirkaccountmanager.WithEndpoints(viper.GetStringSlice("accountmanager.dirk.endpoints")),
dirkaccountmanager.WithAccountPaths(viper.GetStringSlice("accountmanager.dirk.accounts")),

View File

@ -15,10 +15,13 @@ package mock
import (
"context"
"encoding/hex"
"errors"
"strings"
"time"
eth2client "github.com/attestantio/go-eth2-client"
api "github.com/attestantio/go-eth2-client/api/v1"
spec "github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/prysmaticlabs/go-bitfield"
)
@ -74,6 +77,19 @@ func (m *SlotsPerEpochProvider) SlotsPerEpoch(ctx context.Context) (uint64, erro
return m.slotsPerEpoch, nil
}
// ErroringSlotsPerEpochProvider is a mock for eth2client.SlotsPerEpochProvider.
type ErroringSlotsPerEpochProvider struct{}
// NewErroringSlotsPerEpochProvider returns a mock slots per epoch provider that errors.
func NewErroringSlotsPerEpochProvider() eth2client.SlotsPerEpochProvider {
return &ErroringSlotsPerEpochProvider{}
}
// SlotsPerEpoch is a mock.
func (m *ErroringSlotsPerEpochProvider) SlotsPerEpoch(ctx context.Context) (uint64, error) {
return 0, errors.New("error")
}
// AttestationSubmitter is a mock for eth2client.AttestationSubmitter.
type AttestationSubmitter struct{}
@ -269,3 +285,471 @@ func (m *BeaconBlockProposalProvider) BeaconBlockProposal(ctx context.Context, s
return block, nil
}
// BeaconProposerDomainProvider is a mock for eth2client.BeaconProposerDomainProvider.
type BeaconProposerDomainProvider struct{}
// NewBeaconProposerDomainProvider returns a mock beacon proposer domain provider.
func NewBeaconProposerDomainProvider() eth2client.BeaconProposerDomainProvider {
return &BeaconProposerDomainProvider{}
}
// BeaconProposerDomain is a mock.
func (m *BeaconProposerDomainProvider) BeaconProposerDomain(ctx context.Context) ([]byte, error) {
return []byte{0x00, 0x00, 0x00, 0x00}, nil
}
// ErroringBeaconProposerDomainProvider is a mock for eth2client.BeaconProposerDomainProvider.
type ErroringBeaconProposerDomainProvider struct{}
// NewErroringBeaconProposerDomainProvider returns a mock beacon proposer domain provider that errors.
func NewErroringBeaconProposerDomainProvider() eth2client.BeaconProposerDomainProvider {
return &ErroringBeaconProposerDomainProvider{}
}
// BeaconProposerDomain is a mock.
func (m *ErroringBeaconProposerDomainProvider) BeaconProposerDomain(ctx context.Context) ([]byte, error) {
return nil, errors.New("error")
}
// BeaconAttesterDomainProvider is a mock for eth2client.BeaconAttesterDomainProvider.
type BeaconAttesterDomainProvider struct{}
// NewBeaconAttesterDomainProvider returns a mock beacon attester domain provider.
func NewBeaconAttesterDomainProvider() eth2client.BeaconAttesterDomainProvider {
return &BeaconAttesterDomainProvider{}
}
// BeaconAttesterDomain is a mock.
func (m *BeaconAttesterDomainProvider) BeaconAttesterDomain(ctx context.Context) ([]byte, error) {
return []byte{0x01, 0x00, 0x00, 0x00}, nil
}
// ErroringBeaconAttesterDomainProvider is a mock for eth2client.BeaconAttesterDomainProvider.
type ErroringBeaconAttesterDomainProvider struct{}
// NewErroringBeaconAttesterDomainProvider returns a mock beacon attester domain provider that errors.
func NewErroringBeaconAttesterDomainProvider() eth2client.BeaconAttesterDomainProvider {
return &ErroringBeaconAttesterDomainProvider{}
}
// BeaconAttesterDomain is a mock.
func (m *ErroringBeaconAttesterDomainProvider) BeaconAttesterDomain(ctx context.Context) ([]byte, error) {
return nil, errors.New("error")
}
// RANDAODomainProvider is a mock for eth2client.RANDAODomainProvider.
type RANDAODomainProvider struct{}
// NewRANDAODomainProvider returns a mock RANDAO domain provider.
func NewRANDAODomainProvider() eth2client.RANDAODomainProvider {
return &RANDAODomainProvider{}
}
// RANDAODomain is a mock.
func (m *RANDAODomainProvider) RANDAODomain(ctx context.Context) ([]byte, error) {
return []byte{0x02, 0x00, 0x00, 0x00}, nil
}
// ErroringRANDAODomainProvider is a mock for eth2client.RANDAODomainProvider.
type ErroringRANDAODomainProvider struct{}
// NewErroringRANDAODomainProvider returns a mock RANDAO domain provider that errors.
func NewErroringRANDAODomainProvider() eth2client.RANDAODomainProvider {
return &ErroringRANDAODomainProvider{}
}
// RANDAODomain is a mock.
func (m *ErroringRANDAODomainProvider) RANDAODomain(ctx context.Context) ([]byte, error) {
return nil, errors.New("error")
}
// DepositDomainProvider is a mock for eth2client.DepositDomainProvider.
type DepositDomainProvider struct{}
// NewDepositDomainProvider returns a mock deposit domain provider.
func NewDepositDomainProvider() eth2client.DepositDomainProvider {
return &DepositDomainProvider{}
}
// DepositDomain is a mock.
func (m *DepositDomainProvider) DepositDomain(ctx context.Context) ([]byte, error) {
return []byte{0x03, 0x00, 0x00, 0x00}, nil
}
// ErroringDepositDomainProvider is a mock for eth2client.DepositDomainProvider.
type ErroringDepositDomainProvider struct{}
// NewErroringDepositDomainProvider returns a mock deposit domain provider that errors.
func NewErroringDepositDomainProvider() eth2client.DepositDomainProvider {
return &DepositDomainProvider{}
}
// DepositDomain is a mock.
func (m *ErroringDepositDomainProvider) DepositDomain(ctx context.Context) ([]byte, error) {
return nil, errors.New("error")
}
// VoluntaryExitDomainProvider is a mock for eth2client.VoluntaryExitDomainProvider.
type VoluntaryExitDomainProvider struct{}
// NewVoluntaryExitDomainProvider returns a mock voluntary exit domain provider.
func NewVoluntaryExitDomainProvider() eth2client.VoluntaryExitDomainProvider {
return &VoluntaryExitDomainProvider{}
}
// VoluntaryExitDomain is a mock.
func (m *VoluntaryExitDomainProvider) VoluntaryExitDomain(ctx context.Context) ([]byte, error) {
return []byte{0x04, 0x00, 0x00, 0x00}, nil
}
// ErroringVoluntaryExitDomainProvider is a mock for eth2client.VoluntaryExitDomainProvider.
type ErroringVoluntaryExitDomainProvider struct{}
// NewErroringVoluntaryExitDomainProvider returns a mock voluntary exit domain provider that errors.
func NewErroringVoluntaryExitDomainProvider() eth2client.VoluntaryExitDomainProvider {
return &VoluntaryExitDomainProvider{}
}
// VoluntaryExitDomain is a mock.
func (m *ErroringVoluntaryExitDomainProvider) VoluntaryExitDomain(ctx context.Context) ([]byte, error) {
return nil, errors.New("error")
}
// SelectionProofDomainProvider is a mock for eth2client.SelectionProofDomainProvider.
type SelectionProofDomainProvider struct{}
// NewSelectionProofDomainProvider returns a mock selection proof domain provider.
func NewSelectionProofDomainProvider() eth2client.SelectionProofDomainProvider {
return &SelectionProofDomainProvider{}
}
// SelectionProofDomain is a mock.
func (m *SelectionProofDomainProvider) SelectionProofDomain(ctx context.Context) ([]byte, error) {
return []byte{0x05, 0x00, 0x00, 0x00}, nil
}
// ErroringSelectionProofDomainProvider is a mock for eth2client.SelectionProofDomainProvider.
type ErroringSelectionProofDomainProvider struct{}
// NewErroringSelectionProofDomainProvider returns a mock selection proof domain provider that errors.
func NewErroringSelectionProofDomainProvider() eth2client.SelectionProofDomainProvider {
return &ErroringSelectionProofDomainProvider{}
}
// SelectionProofDomain is a mock.
func (m *ErroringSelectionProofDomainProvider) SelectionProofDomain(ctx context.Context) ([]byte, error) {
return nil, errors.New("error")
}
// AggregateAndProofDomainProvider is a mock for eth2client.AggregateAndProofDomainProvider.
type AggregateAndProofDomainProvider struct{}
// NewAggregateAndProofDomainProvider returns a mock aggregate and proof domain provider.
func NewAggregateAndProofDomainProvider() eth2client.AggregateAndProofDomainProvider {
return &AggregateAndProofDomainProvider{}
}
// AggregateAndProofDomain is a mock.
func (m *AggregateAndProofDomainProvider) AggregateAndProofDomain(ctx context.Context) ([]byte, error) {
return []byte{0x06, 0x00, 0x00, 0x00}, nil
}
// ErroringAggregateAndProofDomainProvider is a mock for eth2client.AggregateAndProofDomainProvider.
type ErroringAggregateAndProofDomainProvider struct{}
// NewErroringAggregateAndProofDomainProvider returns a mock aggregate and proof domain provider that errors.
func NewErroringAggregateAndProofDomainProvider() eth2client.AggregateAndProofDomainProvider {
return &ErroringAggregateAndProofDomainProvider{}
}
// AggregateAndProofDomain is a mock.
func (m *ErroringAggregateAndProofDomainProvider) AggregateAndProofDomain(ctx context.Context) ([]byte, error) {
return nil, errors.New("error")
}
// SignatureDomainProvider is a mock for eth2client.SignatureDomainProvider.
type SignatureDomainProvider struct{}
// NewSignatureDomainProvider returns a mock signature domain provider.
func NewSignatureDomainProvider() eth2client.SignatureDomainProvider {
return &SignatureDomainProvider{}
}
// SignatureDomain is a mock.
func (m *SignatureDomainProvider) SignatureDomain(ctx context.Context, domain []byte, epoch uint64) ([]byte, error) {
var signatureDomain [32]byte
// Put the domain in the first four bytes, to differentiate signatures.
copy(signatureDomain[:], domain)
return signatureDomain[:], nil
}
// ErroringSignatureDomainProvider is a mock for eth2client.SignatureDomainProvider.
type ErroringSignatureDomainProvider struct{}
// NewErroringSignatureDomainProvider returns a mock signature domain provider that errors.
func NewErroringSignatureDomainProvider() eth2client.SignatureDomainProvider {
return &SignatureDomainProvider{}
}
// SignatureDomain is a mock.
func (m *ErroringSignatureDomainProvider) SignatureDomain(ctx context.Context, domain []byte, epoch uint64) ([]byte, error) {
return nil, errors.New("error")
}
// ValidatorsProvider is a mock for eth2client.ValidatorsProvider.
type ValidatorsProvider struct{}
// NewValidatorsProvider returns a mock validators provider.
func NewValidatorsProvider() eth2client.ValidatorsProvider {
return &ValidatorsProvider{}
}
func _byte(input string) []byte {
res, _ := hex.DecodeString(strings.TrimPrefix(input, "0x"))
return res
}
func _epochValidator(index uint64, pubKey string, withdrwalCredentials string) *api.Validator {
return &api.Validator{
Index: index,
Balance: 32000000000,
State: api.ValidatorStateActiveOngoing,
Validator: &spec.Validator{
PublicKey: _byte(pubKey),
WithdrawalCredentials: _byte(withdrwalCredentials),
EffectiveBalance: 32000000,
Slashed: false,
ActivationEligibilityEpoch: 0,
ActivationEpoch: 0,
ExitEpoch: 0xffffffffffffffff,
WithdrawableEpoch: 0xffffffffffffffff,
},
}
}
// Validators is a mock.
func (m *ValidatorsProvider) Validators(ctx context.Context, stateID string, validators []eth2client.ValidatorIDProvider) (map[uint64]*api.Validator, error) {
return map[uint64]*api.Validator{
0: _epochValidator(0,
"0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c",
"0x00fad2a6bfb0e7f1f0f45460944fbd8dfa7f37da06a4d13b3983cc90bb46963b"),
1: _epochValidator(1,
"0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b",
"0x00ec7ef7780c9d151597924036262dd28dc60e1228f4da6fecf9d402cb3f3594"),
2: _epochValidator(2,
"0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b",
"0x0036085c6c608e6d048505b04402568c36cce1e025722de44f9c3685a5c80fa6"),
3: _epochValidator(3,
"0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e",
"0x005a7de495bcec04d3b5e74ae09ffe493a9dd06d7dcbf18c78455571e87d901a"),
4: _epochValidator(4,
"0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e",
"0x004a28c193c65c91b7ebb5b5d14ffa7f75dc48ad4bc66de82f70fc55a2df1215"),
5: _epochValidator(5,
"0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34",
"0x005856ab195b61df2ff5d6ab2fa36f30dab45e42cfa1aaef3ffd899f29bd8641"),
6: _epochValidator(6,
"0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373",
"0x001c5d9bedbad1b7aff3b80e887e65b3357a695b70b6ee0625c2b2f6f86449f8"),
7: _epochValidator(7,
"0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac",
"0x001414bfc6dacca55f974ec910893c8617f9c99da897534c637b50e9fc695323"),
8: _epochValidator(8,
"0xa6d310dbbfab9a22450f59993f87a4ce5db6223f3b5f1f30d2c4ec718922d400e0b3c7741de8e59960f72411a0ee10a7",
"0x00ed09b6181e6f97365e221e70aeebcb2604011d8c4326f3b98ce8d79b031ae8"),
9: _epochValidator(9,
"0x9893413c00283a3f9ed9fd9845dda1cea38228d22567f9541dccc357e54a2d6a6e204103c92564cbc05f4905ac7c493a",
"0x001fe05baa70dd29ce85f694898bb6de3bcde158a825db56906b54141b2a728d"),
10: _epochValidator(10,
"0x876dd4705157eb66dc71bc2e07fb151ea53e1a62a0bb980a7ce72d15f58944a8a3752d754f52f4a60dbfc7b18169f268",
"0x00aa2cfedd0160868d0901664e9d2eac1275dd658e109fabe11c7ad87a07fc0c"),
11: _epochValidator(11,
"0xaec922bd7a9b7b1dc21993133b586b0c3041c1e2e04b513e862227b9d7aecaf9444222f7e78282a449622ffc6278915d",
"0x0076f08e6f40cf14992b7e4f524ea0cf7e1c6fd7dd5200b564c96fc099d601aa"),
12: _epochValidator(12,
"0x9314c6de0386635e2799af798884c2ea09c63b9f079e572acc00b06a7faccce501ea4dfc0b1a23b8603680a5e3481327",
"0x004a581b2ef2b79652a19d3332f6574b0213ddbd179480edbf7ff490823fd5c7"),
13: _epochValidator(13,
"0x903e2989e7442ee0a8958d020507a8bd985d3974f5e8273093be00db3935f0500e141b252bd09e3728892c7a8443863c",
"0x0040c37a4dafa560a7665394aa7502e113ecfbdb72c1ef92826db24601889b87"),
14: _epochValidator(14,
"0x84398f539a64cbe01cfcd8c485ea51cd6657b94df93ee9b5dc61e1f18f69da6ca9d4dba63c956a81c68d5d4d4277a60f",
"0x0047381e2716b14a79e1f102669c615eb3542e9230ed7712b21f305ecc1a43d5"),
15: _epochValidator(15,
"0x872c61b4a7f8510ec809e5b023f5fdda2105d024c470ddbbeca4bc74e8280af0d178d749853e8f6a841083ac1b4db98f",
"0x0020dd5f2223831fce8d1c8fd4148943c9917e1d3a92191651892dc56448451c"),
16: _epochValidator(16,
"0x8f467e5723deac7659e1ca273e28410cbaa6d495ab66ae77014f4cd21c64b6b5ab9987c9b5537fe0279bd063fe609be7",
"0x00b24fc624e56a5ed42a9639691e27e34b783c7237030367bd17cbef65fa6ccf"),
17: _epochValidator(17,
"0x8dde8306920812b32def3b663f7c540b49180345d3bcb8d3770790b7dc80030ebc06497feebd1bcf017d918f00bfa88f",
"0x0018e4071970526ed149970747c6b858307be8b60aa7440ad93c1f351af62923"),
18: _epochValidator(18,
"0xab8d3a9bcc160e518fac0756d3e192c74789588ed4a2b1debf0c78f78479ca8edb05b12ce21103076df6af4eb8756ff9",
"0x00bb019106332edfed624b40e410561513e9fb9e285cbc56a450d499a2b13769"),
19: _epochValidator(19,
"0x8d5d3672a233db513df7ad1e8beafeae99a9f0199ed4d949bbedbb6f394030c0416bd99b910e14f73c65b6a11fe6b62e",
"0x004218c29533321c9aae659d8b2148b87693d6b1eee8e119805e5298f8bf0a33"),
20: _epochValidator(20,
"0xa1c76af1545d7901214bb6be06be5d9e458f8e989c19373a920f0018327c83982f6a2ac138260b8def732cb366411ddc",
"0x0004e3d99964ee8b0b6ed11833ba55fbf7bf80fe8f4e45c4d00a3d4ff6d73c0c"),
21: _epochValidator(21,
"0x8dd74e1bb5228fc1fca274fda02b971c1003a4f409bbdfbcfec6426bf2f52addcbbebccdbf45eee6ae11eb5b5ee7244d",
"0x00037233059d7c629c79ddb7d94b0ef1275ebe55ed20fb80a414548be9ec890a"),
22: _epochValidator(22,
"0x954eb88ed1207f891dc3c28fa6cfdf8f53bf0ed3d838f3476c0900a61314d22d4f0a300da3cd010444dd5183e35a593c",
"0x0056a7b95fd200d2997155b525eacda73baae3f3196a48fb9a513ddd1e7247c3"),
23: _epochValidator(23,
"0xaf344fce60dbd5fb850070e6e76a065e1a32485245ef4f413135a86ae703da88407c5d01c71f6bb06a151ff96cca7191",
"0x005bdba6a856b0df016f8cbad0f9c02a517e2ff2f5db19187e6d1ba155d4b2e5"),
24: _epochValidator(24,
"0xae241af60691fda1cf8ca44d49573c55818c53b6141800cca2d488b9a3fba71c0f869179fff50c084657831fbeb42bf4",
"0x000cc62d0bf911cfba5320da6e1d7407ff744427f74e855fc2444357788d6830"),
25: _epochValidator(25,
"0x96746aaba64dc87835ba709332f4d5d7837ada092b439c49d251aecf92aab5dc132e917bf6f59799bc093f976a7bc021",
"0x006badd5d911c8565362da6e00dde8d2dda73fb9127d5ba26849ae0a0636172b"),
26: _epochValidator(26,
"0xb9d1d914df3d4565465c3fd52b5b96e637f9980570cabf5b5d4aadf5a329ac36ad672819d997e735f5052e28b1f0c104",
"0x00f53dc973d5288e8070cf79ac0168443f3a2703e83f600e6197067aa02ca662"),
27: _epochValidator(27,
"0x963528adb5322c2e2c54dc296ffddd2861bb103cbf64646781dfa8a3c2d8a8eda7079d2b3e95600028c44365afbf8879",
"0x00fa4e26953e907b1ed8032bdd02c9869dbbf521f3cb7bac1c8112ccf45c1d3a"),
28: _epochValidator(28,
"0xb245d63d3f9d8ea1807a629fcb1b328cb4d542f35a3d5bc478be0df389dddd712fc4c816ba3fede9a96320ae6b24a7d8",
"0x00a68cdbfc1e865255d8e436d7bc7fc63c87b5c9c247c9e5de34d4fc26a1adc9"),
29: _epochValidator(29,
"0xa98ed496c2f464226500a6ce04602ff9ef133ed6316f372f6c744aee165149f7e578b12780e0eacec307ae6907351d99",
"0x002f6d1f79f89a308365af4dbb8a850918db7844165b36e43c64e1a35b4af0b2"),
30: _epochValidator(30,
"0xae00fc3de831b09661a0ac02873c45c84cb2b58cffb6430a3f607e4c3fa1e0932397f11307cd169cdc6f79c463527260",
"0x00e6ef2894304bc790c9e6b3a75815f10ceea391d8ebb9a27e07bf54360e9b3d"),
31: _epochValidator(31,
"0xa4855c83d868f772a579133d9f23818008417b743e8447e235d8eb78b1d8f8a9f63f98c551beb7de254400f89592314d",
"0x0077c6a139204cbdaae840e0beb43b384c35182aabbc1104207b6a5a626fe75b"),
}, nil
}
// ValidatorsWithoutBalanceProvider is a mock for eth2client.ValidatorsProvider with eth2client.ValidatorsWithoutBalanceProvider.
type ValidatorsWithoutBalanceProvider struct{}
// NewValidatorsWithoutBalanceProvider returns a mock validators provider.
func NewValidatorsWithoutBalanceProvider() eth2client.ValidatorsProvider {
return &ValidatorsWithoutBalanceProvider{}
}
// Validators is a mock.
func (m *ValidatorsWithoutBalanceProvider) Validators(ctx context.Context, stateID string, validators []eth2client.ValidatorIDProvider) (map[uint64]*api.Validator, error) {
return map[uint64]*api.Validator{
0: _epochValidator(0,
"0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c",
"0x00fad2a6bfb0e7f1f0f45460944fbd8dfa7f37da06a4d13b3983cc90bb46963b"),
1: _epochValidator(1,
"0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b",
"0x00ec7ef7780c9d151597924036262dd28dc60e1228f4da6fecf9d402cb3f3594"),
2: _epochValidator(2,
"0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b",
"0x0036085c6c608e6d048505b04402568c36cce1e025722de44f9c3685a5c80fa6"),
3: _epochValidator(3,
"0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e",
"0x005a7de495bcec04d3b5e74ae09ffe493a9dd06d7dcbf18c78455571e87d901a"),
4: _epochValidator(4,
"0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e",
"0x004a28c193c65c91b7ebb5b5d14ffa7f75dc48ad4bc66de82f70fc55a2df1215"),
5: _epochValidator(5,
"0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34",
"0x005856ab195b61df2ff5d6ab2fa36f30dab45e42cfa1aaef3ffd899f29bd8641"),
6: _epochValidator(6,
"0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373",
"0x001c5d9bedbad1b7aff3b80e887e65b3357a695b70b6ee0625c2b2f6f86449f8"),
7: _epochValidator(7,
"0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac",
"0x001414bfc6dacca55f974ec910893c8617f9c99da897534c637b50e9fc695323"),
8: _epochValidator(8,
"0xa6d310dbbfab9a22450f59993f87a4ce5db6223f3b5f1f30d2c4ec718922d400e0b3c7741de8e59960f72411a0ee10a7",
"0x00ed09b6181e6f97365e221e70aeebcb2604011d8c4326f3b98ce8d79b031ae8"),
9: _epochValidator(9,
"0x9893413c00283a3f9ed9fd9845dda1cea38228d22567f9541dccc357e54a2d6a6e204103c92564cbc05f4905ac7c493a",
"0x001fe05baa70dd29ce85f694898bb6de3bcde158a825db56906b54141b2a728d"),
10: _epochValidator(10,
"0x876dd4705157eb66dc71bc2e07fb151ea53e1a62a0bb980a7ce72d15f58944a8a3752d754f52f4a60dbfc7b18169f268",
"0x00aa2cfedd0160868d0901664e9d2eac1275dd658e109fabe11c7ad87a07fc0c"),
11: _epochValidator(11,
"0xaec922bd7a9b7b1dc21993133b586b0c3041c1e2e04b513e862227b9d7aecaf9444222f7e78282a449622ffc6278915d",
"0x0076f08e6f40cf14992b7e4f524ea0cf7e1c6fd7dd5200b564c96fc099d601aa"),
12: _epochValidator(12,
"0x9314c6de0386635e2799af798884c2ea09c63b9f079e572acc00b06a7faccce501ea4dfc0b1a23b8603680a5e3481327",
"0x004a581b2ef2b79652a19d3332f6574b0213ddbd179480edbf7ff490823fd5c7"),
13: _epochValidator(13,
"0x903e2989e7442ee0a8958d020507a8bd985d3974f5e8273093be00db3935f0500e141b252bd09e3728892c7a8443863c",
"0x0040c37a4dafa560a7665394aa7502e113ecfbdb72c1ef92826db24601889b87"),
14: _epochValidator(14,
"0x84398f539a64cbe01cfcd8c485ea51cd6657b94df93ee9b5dc61e1f18f69da6ca9d4dba63c956a81c68d5d4d4277a60f",
"0x0047381e2716b14a79e1f102669c615eb3542e9230ed7712b21f305ecc1a43d5"),
15: _epochValidator(15,
"0x872c61b4a7f8510ec809e5b023f5fdda2105d024c470ddbbeca4bc74e8280af0d178d749853e8f6a841083ac1b4db98f",
"0x0020dd5f2223831fce8d1c8fd4148943c9917e1d3a92191651892dc56448451c"),
16: _epochValidator(16,
"0x8f467e5723deac7659e1ca273e28410cbaa6d495ab66ae77014f4cd21c64b6b5ab9987c9b5537fe0279bd063fe609be7",
"0x00b24fc624e56a5ed42a9639691e27e34b783c7237030367bd17cbef65fa6ccf"),
17: _epochValidator(17,
"0x8dde8306920812b32def3b663f7c540b49180345d3bcb8d3770790b7dc80030ebc06497feebd1bcf017d918f00bfa88f",
"0x0018e4071970526ed149970747c6b858307be8b60aa7440ad93c1f351af62923"),
18: _epochValidator(18,
"0xab8d3a9bcc160e518fac0756d3e192c74789588ed4a2b1debf0c78f78479ca8edb05b12ce21103076df6af4eb8756ff9",
"0x00bb019106332edfed624b40e410561513e9fb9e285cbc56a450d499a2b13769"),
19: _epochValidator(19,
"0x8d5d3672a233db513df7ad1e8beafeae99a9f0199ed4d949bbedbb6f394030c0416bd99b910e14f73c65b6a11fe6b62e",
"0x004218c29533321c9aae659d8b2148b87693d6b1eee8e119805e5298f8bf0a33"),
20: _epochValidator(20,
"0xa1c76af1545d7901214bb6be06be5d9e458f8e989c19373a920f0018327c83982f6a2ac138260b8def732cb366411ddc",
"0x0004e3d99964ee8b0b6ed11833ba55fbf7bf80fe8f4e45c4d00a3d4ff6d73c0c"),
21: _epochValidator(21,
"0x8dd74e1bb5228fc1fca274fda02b971c1003a4f409bbdfbcfec6426bf2f52addcbbebccdbf45eee6ae11eb5b5ee7244d",
"0x00037233059d7c629c79ddb7d94b0ef1275ebe55ed20fb80a414548be9ec890a"),
22: _epochValidator(22,
"0x954eb88ed1207f891dc3c28fa6cfdf8f53bf0ed3d838f3476c0900a61314d22d4f0a300da3cd010444dd5183e35a593c",
"0x0056a7b95fd200d2997155b525eacda73baae3f3196a48fb9a513ddd1e7247c3"),
23: _epochValidator(23,
"0xaf344fce60dbd5fb850070e6e76a065e1a32485245ef4f413135a86ae703da88407c5d01c71f6bb06a151ff96cca7191",
"0x005bdba6a856b0df016f8cbad0f9c02a517e2ff2f5db19187e6d1ba155d4b2e5"),
24: _epochValidator(24,
"0xae241af60691fda1cf8ca44d49573c55818c53b6141800cca2d488b9a3fba71c0f869179fff50c084657831fbeb42bf4",
"0x000cc62d0bf911cfba5320da6e1d7407ff744427f74e855fc2444357788d6830"),
25: _epochValidator(25,
"0x96746aaba64dc87835ba709332f4d5d7837ada092b439c49d251aecf92aab5dc132e917bf6f59799bc093f976a7bc021",
"0x006badd5d911c8565362da6e00dde8d2dda73fb9127d5ba26849ae0a0636172b"),
26: _epochValidator(26,
"0xb9d1d914df3d4565465c3fd52b5b96e637f9980570cabf5b5d4aadf5a329ac36ad672819d997e735f5052e28b1f0c104",
"0x00f53dc973d5288e8070cf79ac0168443f3a2703e83f600e6197067aa02ca662"),
27: _epochValidator(27,
"0x963528adb5322c2e2c54dc296ffddd2861bb103cbf64646781dfa8a3c2d8a8eda7079d2b3e95600028c44365afbf8879",
"0x00fa4e26953e907b1ed8032bdd02c9869dbbf521f3cb7bac1c8112ccf45c1d3a"),
28: _epochValidator(28,
"0xb245d63d3f9d8ea1807a629fcb1b328cb4d542f35a3d5bc478be0df389dddd712fc4c816ba3fede9a96320ae6b24a7d8",
"0x00a68cdbfc1e865255d8e436d7bc7fc63c87b5c9c247c9e5de34d4fc26a1adc9"),
29: _epochValidator(29,
"0xa98ed496c2f464226500a6ce04602ff9ef133ed6316f372f6c744aee165149f7e578b12780e0eacec307ae6907351d99",
"0x002f6d1f79f89a308365af4dbb8a850918db7844165b36e43c64e1a35b4af0b2"),
30: _epochValidator(30,
"0xae00fc3de831b09661a0ac02873c45c84cb2b58cffb6430a3f607e4c3fa1e0932397f11307cd169cdc6f79c463527260",
"0x00e6ef2894304bc790c9e6b3a75815f10ceea391d8ebb9a27e07bf54360e9b3d"),
31: _epochValidator(31,
"0xa4855c83d868f772a579133d9f23818008417b743e8447e235d8eb78b1d8f8a9f63f98c551beb7de254400f89592314d",
"0x0077c6a139204cbdaae840e0beb43b384c35182aabbc1104207b6a5a626fe75b"),
}, nil
}
// ValidatorsWithoutBalance is a mock.
func (m *ValidatorsWithoutBalanceProvider) ValidatorsWithoutBalance(ctx context.Context, stateID string, validators []eth2client.ValidatorIDProvider) (map[uint64]*api.Validator, error) {
res, err := m.Validators(ctx, stateID, validators)
if err != nil {
return nil, err
}
for _, validator := range res {
validator.Balance = 0
}
return res, nil
}

View File

@ -14,8 +14,11 @@
package dirk
import (
"context"
eth2client "github.com/attestantio/go-eth2-client"
"github.com/attestantio/vouch/services/metrics"
nullmetrics "github.com/attestantio/vouch/services/metrics/null"
"github.com/pkg/errors"
"github.com/rs/zerolog"
)
@ -23,6 +26,7 @@ import (
type parameters struct {
logLevel zerolog.Level
monitor metrics.AccountManagerMonitor
clientMonitor metrics.ClientMonitor
endpoints []string
accountPaths []string
clientCert []byte
@ -63,6 +67,13 @@ func WithMonitor(monitor metrics.AccountManagerMonitor) Parameter {
})
}
// WithClientMonitor sets the client monitor for the module.
func WithClientMonitor(clientMonitor metrics.ClientMonitor) Parameter {
return parameterFunc(func(p *parameters) {
p.clientMonitor = clientMonitor
})
}
// WithEndpoints sets the endpoints to communicate with dirk.
func WithEndpoints(endpoints []string) Parameter {
return parameterFunc(func(p *parameters) {
@ -157,7 +168,9 @@ func WithSignatureDomainProvider(provider eth2client.SignatureDomainProvider) Pa
// parseAndCheckParameters parses and checks parameters to ensure that mandatory parameters are present and correct.
func parseAndCheckParameters(params ...Parameter) (*parameters, error) {
parameters := parameters{
logLevel: zerolog.GlobalLevel(),
logLevel: zerolog.GlobalLevel(),
monitor: nullmetrics.New(context.Background()),
clientMonitor: nullmetrics.New(context.Background()),
}
for _, p := range params {
if params != nil {
@ -168,10 +181,13 @@ func parseAndCheckParameters(params ...Parameter) (*parameters, error) {
if parameters.monitor == nil {
return nil, errors.New("no monitor specified")
}
if parameters.endpoints == nil {
if parameters.clientMonitor == nil {
return nil, errors.New("no client monitor specified")
}
if len(parameters.endpoints) == 0 {
return nil, errors.New("no endpoints specified")
}
if parameters.accountPaths == nil {
if len(parameters.accountPaths) == 0 {
return nil, errors.New("no account paths specified")
}
if parameters.clientCert == nil {

View File

@ -22,6 +22,7 @@ import (
"strconv"
"strings"
"sync"
"time"
eth2client "github.com/attestantio/go-eth2-client"
api "github.com/attestantio/go-eth2-client/api/v1"
@ -40,6 +41,7 @@ import (
type Service struct {
mutex sync.RWMutex
monitor metrics.AccountManagerMonitor
clientMonitor metrics.ClientMonitor
endpoints []*dirk.Endpoint
accountPaths []string
credentials credentials.TransportCredentials
@ -93,6 +95,9 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
}
endpoints = append(endpoints, dirk.NewEndpoint(endpointParts[0], uint32(port)))
}
if len(endpoints) == 0 {
return nil, errors.New("no valid endpoints specified")
}
slotsPerEpoch, err := parameters.slotsPerEpochProvider.SlotsPerEpoch(ctx)
if err != nil {
@ -121,6 +126,7 @@ func New(ctx context.Context, params ...Parameter) (*Service, error) {
s := &Service{
monitor: parameters.monitor,
clientMonitor: parameters.clientMonitor,
endpoints: endpoints,
accountPaths: parameters.accountPaths,
credentials: credentials,
@ -159,12 +165,24 @@ func (s *Service) UpdateAccountsState(ctx context.Context) error {
var validators map[uint64]*api.Validator
var err error
if validatorsWithoutBalanceProvider, isProvider := s.validatorsProvider.(eth2client.ValidatorsWithoutBalanceProvider); isProvider {
started := time.Now()
validators, err = validatorsWithoutBalanceProvider.ValidatorsWithoutBalance(ctx, "head", validatorIDs)
if service, isService := s.validatorsProvider.(eth2client.Service); isService {
s.clientMonitor.ClientOperation(service.Address(), "validators without balance", err == nil, time.Since(started))
} else {
s.clientMonitor.ClientOperation("<unknown>", "validators without balance", err == nil, time.Since(started))
}
if err != nil {
return errors.Wrap(err, "failed to obtain validators without balances")
}
} else {
started := time.Now()
validators, err = s.validatorsProvider.Validators(ctx, "head", validatorIDs)
if service, isService := s.validatorsProvider.(eth2client.Service); isService {
s.clientMonitor.ClientOperation(service.Address(), "validators", err == nil, time.Since(started))
} else {
s.clientMonitor.ClientOperation("<unknown>", "validators", err == nil, time.Since(started))
}
if err != nil {
return errors.Wrap(err, "failed to obtain validators")
}
@ -352,13 +370,14 @@ func accountPathsToVerificationRegexes(paths []string) []*regexp.Regexp {
if len(parts) == 1 {
parts = append(parts, ".*")
}
parts[1] = strings.TrimPrefix(parts[1], "^")
var specifier string
if strings.HasSuffix(parts[1], "$") {
specifier = fmt.Sprintf("^%s/%s", parts[0], parts[1])
} else {
specifier = fmt.Sprintf("^%s/%s$", parts[0], parts[1])
if len(parts[1]) == 0 {
parts[1] = ".*"
}
parts[0] = strings.TrimPrefix(parts[0], "^")
parts[0] = strings.TrimSuffix(parts[0], "$")
parts[1] = strings.TrimPrefix(parts[1], "^")
parts[1] = strings.TrimSuffix(parts[1], "$")
specifier := fmt.Sprintf("^%s/%s$", parts[0], parts[1])
regex, err := regexp.Compile(specifier)
if err != nil {
log.Warn().Str("specifier", specifier).Err(err).Msg("Invalid path regex")

View File

@ -0,0 +1,333 @@
// Copyright © 2020 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package dirk
import (
"context"
"fmt"
"math/rand"
"regexp"
"testing"
"time"
"github.com/attestantio/dirk/testing/daemon"
api "github.com/attestantio/go-eth2-client/api/v1"
"github.com/attestantio/vouch/mock"
nullmetrics "github.com/attestantio/vouch/services/metrics/null"
"github.com/attestantio/vouch/testing/logger"
"github.com/attestantio/vouch/testing/resources"
"github.com/rs/zerolog"
"github.com/stretchr/testify/require"
e2types "github.com/wealdtech/go-eth2-types/v2"
keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4"
hd "github.com/wealdtech/go-eth2-wallet-hd/v2"
scratch "github.com/wealdtech/go-eth2-wallet-store-scratch"
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
)
func TestFetchAccountsForWallet(t *testing.T) {
ctx := context.Background()
require.NoError(t, e2types.InitBLS())
wallets := setupTestWallets(ctx, t,
[]*walletDef{
{
name: "wallet1",
seed: []byte{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
},
accountNames: []string{"account1", "account2", "account3"},
},
})
// Test with wallet regex.
s, err := setupService(ctx, t, []string{"localhost:12345"}, []string{"wallet1", "wallet2"})
require.NoError(t, err)
validatingAccounts := make(map[[48]byte]*ValidatingAccount)
for account := range wallets[0].Accounts(ctx) {
var key [48]byte
copy(key[:], account.PublicKey().Marshal())
validatingAccounts[key] = &ValidatingAccount{
account: account,
}
}
verificationRegexes := make([]*regexp.Regexp, 0)
verificationRegexes = append(verificationRegexes, regexp.MustCompile("wallet1"))
s.fetchAccountsForWallet(ctx, wallets[0], validatingAccounts, verificationRegexes)
for _, validatingAccount := range validatingAccounts {
require.NotNil(t, validatingAccount.accountManager)
}
// Test with single account regex.
capture := logger.NewLogCapture()
s, err = setupService(ctx, t, []string{"localhost:12345"}, []string{"wallet1", "wallet2"})
require.NoError(t, err)
validatingAccounts = make(map[[48]byte]*ValidatingAccount)
for account := range wallets[0].Accounts(ctx) {
var key [48]byte
copy(key[:], account.PublicKey().Marshal())
validatingAccounts[key] = &ValidatingAccount{
account: account,
}
}
verificationRegexes = make([]*regexp.Regexp, 0)
verificationRegexes = append(verificationRegexes, regexp.MustCompile("1$"))
s.fetchAccountsForWallet(ctx, wallets[0], validatingAccounts, verificationRegexes)
fetched := 0
for _, validatingAccount := range validatingAccounts {
if validatingAccount.accountManager != nil {
fetched++
}
}
require.Equal(t, 1, fetched)
capture.AssertHasEntry(t, "Received unwanted account from server; ignoring")
}
func TestAccountPathsToVerificationRegexes(t *testing.T) {
tests := []struct {
name string
paths []string
regexes []*regexp.Regexp
logEntry string
}{
{
name: "Empty",
},
{
name: "InvalidPath",
paths: []string{"/account1"},
logEntry: "Invalid path",
},
{
name: "Wallet",
paths: []string{"wallet1"},
regexes: []*regexp.Regexp{regexp.MustCompile("^wallet1/.*$")},
},
{
name: "WalletTrailing",
paths: []string{"wallet1/"},
regexes: []*regexp.Regexp{regexp.MustCompile("^wallet1/.*$")},
},
{
name: "Account",
paths: []string{"wallet1/acc"},
regexes: []*regexp.Regexp{regexp.MustCompile("^wallet1/acc$")},
},
{
name: "WalletRegex",
paths: []string{"wallet[0123]/a.*b[abc]{1}"},
regexes: []*regexp.Regexp{regexp.MustCompile("^wallet[0123]/a.*b[abc]{1}$")},
},
{
name: "AccountRegex",
paths: []string{"wallet1/a.*b[abc]{1}"},
regexes: []*regexp.Regexp{regexp.MustCompile("^wallet1/a.*b[abc]{1}$")},
},
{
name: "AccountRegexEndAnchor",
paths: []string{"wallet1/a.*b[abc]{1}$"},
regexes: []*regexp.Regexp{regexp.MustCompile("^wallet1/a.*b[abc]{1}$")},
},
{
name: "AccountRegexStartAnchor",
paths: []string{"^wallet1/a.*b[abc]{1}"},
regexes: []*regexp.Regexp{regexp.MustCompile("^wallet1/a.*b[abc]{1}$")},
},
{
name: "AccountRegexFullAnchor",
paths: []string{"^wallet1/a.*b[abc]{1}$"},
regexes: []*regexp.Regexp{regexp.MustCompile("^wallet1/a.*b[abc]{1}$")},
},
{
name: "InvalidRegex",
paths: []string{"wallet1/a.***"},
logEntry: "Invalid path regex",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
capture := logger.NewLogCapture()
// Need to set up the service to set the module-wide logging.
_, err := setupService(context.Background(), t, []string{"localhost:123456"}, []string{"wallet1"})
require.NoError(t, err)
regexes := accountPathsToVerificationRegexes(test.paths)
require.Equal(t, len(test.regexes), len(regexes))
for i := range test.regexes {
require.Equal(t, test.regexes[i], regexes[i])
}
if test.logEntry != "" {
capture.AssertHasEntry(t, test.logEntry)
}
})
}
}
func TestAccounts(t *testing.T) {
tests := []struct {
name string
accounts map[[48]byte]*ValidatingAccount
expected int
}{
{
name: "Empty",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
s, err := setupService(context.Background(), t, []string{"localhost:123456"}, []string{"wallet1"})
require.NoError(t, err)
// Manually add accounts.
s.accounts = test.accounts
accounts, err := s.Accounts(context.Background())
require.NoError(t, err)
require.Equal(t, test.expected, len(accounts))
})
}
}
func TestUpdateAccountsState(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
rand.Seed(time.Now().UnixNano())
// #nosec G404
port := 1024 + rand.Intn(15359)
_, _, err := daemon.New(ctx, "", 1, port)
require.NoError(t, err)
s, err := setupService(context.Background(), t, []string{fmt.Sprintf("signer-test01:%d", port)}, []string{"Wallet 1", "Wallet 2"})
require.NoError(t, err)
accounts, err := s.Accounts(ctx)
require.NoError(t, err)
require.Equal(t, 16, len(accounts))
// Manually clear out the accounts state.
for _, account := range s.accounts {
account.state = api.ValidatorStateUnknown
}
// Confirm that validators are unknown (hence not returned).
accounts, err = s.Accounts(ctx)
require.NoError(t, err)
require.Equal(t, 0, len(accounts))
// Update and re-check.
require.NoError(t, s.UpdateAccountsState(ctx))
accounts, err = s.Accounts(ctx)
require.NoError(t, err)
require.Equal(t, 16, len(accounts))
}
func TestUpdateAccountsStateWithoutBalances(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
rand.Seed(time.Now().UnixNano())
// #nosec G404
port := 1024 + rand.Intn(15359)
_, _, err := daemon.New(ctx, "", 1, port)
require.NoError(t, err)
s, err := New(ctx,
WithLogLevel(zerolog.TraceLevel),
WithMonitor(nullmetrics.New(context.Background())),
WithClientMonitor(nullmetrics.New(context.Background())),
WithEndpoints([]string{fmt.Sprintf("signer-test01:%d", port)}),
WithAccountPaths([]string{"Wallet 1", "Wallet 2"}),
WithClientCert([]byte(resources.ClientTest01Crt)),
WithClientKey([]byte(resources.ClientTest01Key)),
WithCACert([]byte(resources.CACrt)),
WithValidatorsProvider(mock.NewValidatorsWithoutBalanceProvider()),
WithSlotsPerEpochProvider(mock.NewSlotsPerEpochProvider(32)),
WithBeaconProposerDomainProvider(mock.NewBeaconProposerDomainProvider()),
WithBeaconAttesterDomainProvider(mock.NewBeaconAttesterDomainProvider()),
WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
)
require.NoError(t, err)
accounts, err := s.Accounts(ctx)
require.NoError(t, err)
require.Equal(t, 16, len(accounts))
// Manually clear out the accounts state.
for _, account := range s.accounts {
account.state = api.ValidatorStateUnknown
}
// Confirm that validators are unknown (hence not returned).
accounts, err = s.Accounts(ctx)
require.NoError(t, err)
require.Equal(t, 0, len(accounts))
// Update and re-check.
require.NoError(t, s.UpdateAccountsState(ctx))
accounts, err = s.Accounts(ctx)
require.NoError(t, err)
require.Equal(t, 16, len(accounts))
}
func setupService(ctx context.Context, t *testing.T, endpoints []string, accountPaths []string) (*Service, error) {
return New(ctx,
WithLogLevel(zerolog.TraceLevel),
WithMonitor(nullmetrics.New(context.Background())),
WithClientMonitor(nullmetrics.New(context.Background())),
WithEndpoints(endpoints),
WithAccountPaths(accountPaths),
WithClientCert([]byte(resources.ClientTest01Crt)),
WithClientKey([]byte(resources.ClientTest01Key)),
WithCACert([]byte(resources.CACrt)),
WithValidatorsProvider(mock.NewValidatorsProvider()),
WithSlotsPerEpochProvider(mock.NewSlotsPerEpochProvider(32)),
WithBeaconProposerDomainProvider(mock.NewBeaconProposerDomainProvider()),
WithBeaconAttesterDomainProvider(mock.NewBeaconAttesterDomainProvider()),
WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
)
}
// walletDef defines a wallet to be created.
type walletDef struct {
name string
seed []byte
accountNames []string
}
// setupTestWallet creates wallets given definitions.
func setupTestWallets(ctx context.Context, t *testing.T, defs []*walletDef) []e2wtypes.Wallet {
store := scratch.New()
encryptor := keystorev4.New()
wallets := make([]e2wtypes.Wallet, 0, len(defs))
for _, def := range defs {
wallet, err := hd.CreateWallet(ctx, def.name, []byte("pass"), store, encryptor, def.seed)
require.NoError(t, err)
require.Nil(t, wallet.(e2wtypes.WalletLocker).Unlock(ctx, []byte("pass")))
for _, accountName := range def.accountNames {
_, err = wallet.(e2wtypes.WalletAccountCreator).CreateAccount(context.Background(), accountName, []byte("pass"))
require.NoError(t, err)
}
wallets = append(wallets, wallet)
}
return wallets
}

View File

@ -0,0 +1,869 @@
// Copyright © 2020 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package dirk_test
import (
"context"
"encoding/hex"
"fmt"
"math/rand"
"strings"
"testing"
"time"
"github.com/attestantio/dirk/testing/daemon"
"github.com/attestantio/vouch/mock"
"github.com/attestantio/vouch/services/accountmanager/dirk"
nullmetrics "github.com/attestantio/vouch/services/metrics/null"
"github.com/attestantio/vouch/testing/logger"
"github.com/attestantio/vouch/testing/resources"
"github.com/rs/zerolog"
"github.com/stretchr/testify/require"
)
func _byte(input string) []byte {
res, _ := hex.DecodeString(strings.TrimPrefix(input, "0x"))
return res
}
func TestService(t *testing.T) {
slotsPerEpochProvider := mock.NewSlotsPerEpochProvider(32)
beaconProposerDomainProvider := mock.NewBeaconProposerDomainProvider()
beaconAttesterDomainProvider := mock.NewBeaconAttesterDomainProvider()
randaoDomainProvider := mock.NewRANDAODomainProvider()
selectionProofDomainProvider := mock.NewSelectionProofDomainProvider()
aggregateAndProofDomainProvider := mock.NewAggregateAndProofDomainProvider()
signatureDomainProvider := mock.NewSignatureDomainProvider()
validatorsProvider := mock.NewValidatorsProvider()
tests := []struct {
name string
params []dirk.Parameter
err string
logEntry string
}{
{
name: "MonitorNil",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nil),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "problem with parameters: no monitor specified",
},
{
name: "ClientMonitorNil",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nil),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "problem with parameters: no client monitor specified",
},
{
name: "EndpointsNil",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "problem with parameters: no endpoints specified",
},
{
name: "EndpointsEmpty",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "problem with parameters: no endpoints specified",
},
{
name: "EndpointsMalformedEndpoint",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{""}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "no valid endpoints specified",
logEntry: "Malformed endpoint",
},
{
name: "EndpointsMalformedPort",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"host:bad"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "no valid endpoints specified",
logEntry: "Malformed port",
},
{
name: "EndpointsInvalidPort",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"host:0"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "no valid endpoints specified",
logEntry: "Invalid port",
},
{
name: "AccountPathsNil",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "problem with parameters: no account paths specified",
},
{
name: "AccountPathsEmpty",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "problem with parameters: no account paths specified",
},
{
name: "ClientCertMissing",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "problem with parameters: no client certificate specified",
},
{
name: "ClientKeyMissing",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "problem with parameters: no client key specified",
},
{
name: "ClientCertKeyMismatch",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.Disabled),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest02Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "failed to build credentials: failed to load client keypair: tls: private key does not match public key",
},
{
name: "ValidatorsProviderMissing",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "problem with parameters: no validators provider specified",
},
{
name: "SlotsPerEpochProviderMissing",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "problem with parameters: no slots per epoch provider specified",
},
{
name: "SlotsPerEpochProviderErrors",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.Disabled),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(mock.NewErroringSlotsPerEpochProvider()),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "failed to obtain slots per epoch: error",
},
{
name: "BeaconProposerDomainProviderMissing",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "problem with parameters: no beacon proposer domain provider specified",
},
{
name: "BeaconProposerDomainProviderErrors",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(mock.NewErroringBeaconProposerDomainProvider()),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "failed to obtain beacon proposer domain: error",
},
{
name: "BeaconAttesterDomainProviderMissing",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "problem with parameters: no beacon attester domain provider specified",
},
{
name: "BeaconAttesterDomainProviderErrors",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(mock.NewErroringBeaconAttesterDomainProvider()),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "failed to obtain beacon attester domain: error",
},
{
name: "RANDAODomainProviderMissing",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "problem with parameters: no RANDAO domain provider specified",
},
{
name: "RANDAODomainProviderErrors",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(mock.NewErroringRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "failed to obtain RANDAO domain: error",
},
{
name: "SelectionProofDomainProviderMissing",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "problem with parameters: no selection proof domain provider specified",
},
{
name: "SelectionProofDomainProviderErrors",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(mock.NewErroringSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "failed to obtain selection proof domain: error",
},
{
name: "AggregateAndProofDomainProviderMissing",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "problem with parameters: no aggregate and proof domain provider specified",
},
{
name: "AggregateAndProofDomainProviderErrors",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(mock.NewErroringAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
err: "failed to obtain aggregate and proof domain: error",
},
{
name: "SignatureDomainProviderMissing",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
},
err: "problem with parameters: no signature domain provider specified",
},
{
name: "Good",
params: []dirk.Parameter{
dirk.WithLogLevel(zerolog.Disabled),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{"localhost:12345", "localhost:12346"}),
dirk.WithAccountPaths([]string{"wallet1", "wallet2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(validatorsProvider),
dirk.WithSlotsPerEpochProvider(slotsPerEpochProvider),
dirk.WithBeaconProposerDomainProvider(beaconProposerDomainProvider),
dirk.WithBeaconAttesterDomainProvider(beaconAttesterDomainProvider),
dirk.WithRANDAODomainProvider(randaoDomainProvider),
dirk.WithSelectionProofDomainProvider(selectionProofDomainProvider),
dirk.WithAggregateAndProofDomainProvider(aggregateAndProofDomainProvider),
dirk.WithSignatureDomainProvider(signatureDomainProvider),
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
capture := logger.NewLogCapture()
_, err := dirk.New(context.Background(), test.params...)
if test.err != "" {
require.EqualError(t, err, test.err)
if test.logEntry != "" {
capture.AssertHasEntry(t, test.logEntry)
}
} else {
require.NoError(t, err)
}
})
}
}
func TestAccounts(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
rand.Seed(time.Now().UnixNano())
// #nosec G404
port := 1024 + rand.Intn(15359)
_, _, err := daemon.New(ctx, "", 1, port)
require.Nil(t, err)
tests := []struct {
name string
accountPaths []string
accounts int
}{
{
name: "Empty",
accountPaths: []string{"None"},
accounts: 0,
},
{
name: "Wallet1",
accountPaths: []string{"Wallet 1"},
accounts: 16,
},
{
name: "Wallet1OddAccounts",
accountPaths: []string{"Wallet 1/Account .*[13579]"},
accounts: 8,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
s, err := dirk.New(context.Background(),
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{fmt.Sprintf("signer-test01:%d", port)}),
dirk.WithAccountPaths(test.accountPaths),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(mock.NewValidatorsProvider()),
dirk.WithSlotsPerEpochProvider(mock.NewSlotsPerEpochProvider(32)),
dirk.WithBeaconProposerDomainProvider(mock.NewBeaconProposerDomainProvider()),
dirk.WithBeaconAttesterDomainProvider(mock.NewBeaconAttesterDomainProvider()),
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
)
require.Nil(t, err)
accounts, err := s.Accounts(ctx)
require.Nil(t, err)
require.Equal(t, test.accounts, len(accounts))
})
}
}
func TestAccountsByIndex(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
rand.Seed(time.Now().UnixNano())
// #nosec G404
port := 1024 + rand.Intn(15359)
_, _, err := daemon.New(ctx, "", 1, port)
require.Nil(t, err)
tests := []struct {
name string
indices []uint64
accounts int
}{
{
name: "Nil",
accounts: 0,
},
{
name: "Empty",
indices: []uint64{},
accounts: 0,
},
{
name: "All",
indices: []uint64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
accounts: 16,
},
{
name: "Missing",
indices: []uint64{15, 16},
accounts: 1,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
s, err := dirk.New(context.Background(),
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{fmt.Sprintf("signer-test01:%d", port)}),
dirk.WithAccountPaths([]string{"Wallet 1"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(mock.NewValidatorsProvider()),
dirk.WithSlotsPerEpochProvider(mock.NewSlotsPerEpochProvider(32)),
dirk.WithBeaconProposerDomainProvider(mock.NewBeaconProposerDomainProvider()),
dirk.WithBeaconAttesterDomainProvider(mock.NewBeaconAttesterDomainProvider()),
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
)
require.Nil(t, err)
accounts, err := s.AccountsByIndex(ctx, test.indices)
require.Nil(t, err)
require.Equal(t, test.accounts, len(accounts))
})
}
}
func TestAccountsByPubKey(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
rand.Seed(time.Now().UnixNano())
// #nosec G404
port := 1024 + rand.Intn(15359)
_, _, err := daemon.New(ctx, "", 1, port)
require.Nil(t, err)
tests := []struct {
name string
pubKeys [][]byte
accounts int
}{
{
name: "Nil",
accounts: 0,
},
{
name: "Empty",
pubKeys: [][]byte{
_byte(""),
},
accounts: 0,
},
{
name: "All",
pubKeys: [][]byte{
_byte("0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c"),
_byte("0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b"),
_byte("0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b"),
_byte("0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e"),
_byte("0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e"),
_byte("0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34"),
_byte("0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373"),
_byte("0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac"),
_byte("0xa6d310dbbfab9a22450f59993f87a4ce5db6223f3b5f1f30d2c4ec718922d400e0b3c7741de8e59960f72411a0ee10a7"),
_byte("0x9893413c00283a3f9ed9fd9845dda1cea38228d22567f9541dccc357e54a2d6a6e204103c92564cbc05f4905ac7c493a"),
_byte("0x876dd4705157eb66dc71bc2e07fb151ea53e1a62a0bb980a7ce72d15f58944a8a3752d754f52f4a60dbfc7b18169f268"),
_byte("0xaec922bd7a9b7b1dc21993133b586b0c3041c1e2e04b513e862227b9d7aecaf9444222f7e78282a449622ffc6278915d"),
_byte("0x9314c6de0386635e2799af798884c2ea09c63b9f079e572acc00b06a7faccce501ea4dfc0b1a23b8603680a5e3481327"),
_byte("0x903e2989e7442ee0a8958d020507a8bd985d3974f5e8273093be00db3935f0500e141b252bd09e3728892c7a8443863c"),
_byte("0x84398f539a64cbe01cfcd8c485ea51cd6657b94df93ee9b5dc61e1f18f69da6ca9d4dba63c956a81c68d5d4d4277a60f"),
_byte("0x872c61b4a7f8510ec809e5b023f5fdda2105d024c470ddbbeca4bc74e8280af0d178d749853e8f6a841083ac1b4db98f"),
},
accounts: 16,
},
{
name: "Missing",
pubKeys: [][]byte{
_byte("0x872c61b4a7f8510ec809e5b023f5fdda2105d024c470ddbbeca4bc74e8280af0d178d749853e8f6a841083ac1b4db98f"),
_byte("0x8f467e5723deac7659e1ca273e28410cbaa6d495ab66ae77014f4cd21c64b6b5ab9987c9b5537fe0279bd063fe609be7"),
},
accounts: 1,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
s, err := dirk.New(context.Background(),
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{fmt.Sprintf("signer-test01:%d", port)}),
dirk.WithAccountPaths([]string{"Wallet 1"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(mock.NewValidatorsProvider()),
dirk.WithSlotsPerEpochProvider(mock.NewSlotsPerEpochProvider(32)),
dirk.WithBeaconProposerDomainProvider(mock.NewBeaconProposerDomainProvider()),
dirk.WithBeaconAttesterDomainProvider(mock.NewBeaconAttesterDomainProvider()),
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
)
require.Nil(t, err)
accounts, err := s.AccountsByPubKey(ctx, test.pubKeys)
require.Nil(t, err)
require.Equal(t, test.accounts, len(accounts))
})
}
}

View File

@ -0,0 +1,489 @@
// Copyright © 2020 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package dirk_test
import (
"context"
"fmt"
"math/rand"
"testing"
"time"
"github.com/attestantio/dirk/testing/daemon"
api "github.com/attestantio/go-eth2-client/api/v1"
"github.com/attestantio/vouch/mock"
"github.com/attestantio/vouch/services/accountmanager"
"github.com/attestantio/vouch/services/accountmanager/dirk"
nullmetrics "github.com/attestantio/vouch/services/metrics/null"
"github.com/attestantio/vouch/testing/resources"
"github.com/rs/zerolog"
"github.com/stretchr/testify/require"
)
func TestPubKey(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
rand.Seed(time.Now().UnixNano())
// #nosec G404
port := 1024 + rand.Intn(15359)
_, _, err := daemon.New(ctx, "", 1, port)
require.Nil(t, err)
s, err := dirk.New(context.Background(),
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{fmt.Sprintf("signer-test01:%d", port)}),
dirk.WithAccountPaths([]string{"Wallet 1", "Wallet 2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(mock.NewValidatorsProvider()),
dirk.WithSlotsPerEpochProvider(mock.NewSlotsPerEpochProvider(32)),
dirk.WithBeaconProposerDomainProvider(mock.NewBeaconProposerDomainProvider()),
dirk.WithBeaconAttesterDomainProvider(mock.NewBeaconAttesterDomainProvider()),
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
)
require.Nil(t, err)
tests := []struct {
name string
index uint64
expected []byte
}{
{
name: "0",
index: 0,
expected: _byte("0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c"),
},
{
name: "1",
index: 1,
expected: _byte("0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
accounts, err := s.AccountsByIndex(ctx, []uint64{test.index})
require.NoError(t, err)
require.Equal(t, 1, len(accounts))
account := accounts[0]
provider, isProvider := account.(accountmanager.ValidatingAccountPubKeyProvider)
require.True(t, isProvider)
res, err := provider.PubKey(ctx)
require.NoError(t, err)
require.Equal(t, test.expected, res)
})
}
}
func TestState(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
rand.Seed(time.Now().UnixNano())
// #nosec G404
port := 1024 + rand.Intn(15359)
_, _, err := daemon.New(ctx, "", 1, port)
require.Nil(t, err)
s, err := dirk.New(context.Background(),
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{fmt.Sprintf("signer-test01:%d", port)}),
dirk.WithAccountPaths([]string{"Wallet 1", "Wallet 2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(mock.NewValidatorsProvider()),
dirk.WithSlotsPerEpochProvider(mock.NewSlotsPerEpochProvider(32)),
dirk.WithBeaconProposerDomainProvider(mock.NewBeaconProposerDomainProvider()),
dirk.WithBeaconAttesterDomainProvider(mock.NewBeaconAttesterDomainProvider()),
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
)
require.Nil(t, err)
tests := []struct {
name string
index uint64
expected api.ValidatorState
}{
{
name: "0",
index: 0,
expected: api.ValidatorStateActiveOngoing,
},
{
name: "1",
index: 1,
expected: api.ValidatorStateActiveOngoing,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
accounts, err := s.AccountsByIndex(ctx, []uint64{test.index})
require.NoError(t, err)
require.Equal(t, 1, len(accounts))
account := accounts[0]
provider, isProvider := account.(accountmanager.ValidatingAccountStateProvider)
require.True(t, isProvider)
res := provider.State()
require.Equal(t, test.expected, res)
})
}
}
func TestSignSlotSelection(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
rand.Seed(time.Now().UnixNano())
// #nosec G404
port := 1024 + rand.Intn(15359)
_, _, err := daemon.New(ctx, "", 1, port)
require.Nil(t, err)
s, err := dirk.New(context.Background(),
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{fmt.Sprintf("signer-test01:%d", port)}),
dirk.WithAccountPaths([]string{"Wallet 1", "Wallet 2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(mock.NewValidatorsProvider()),
dirk.WithSlotsPerEpochProvider(mock.NewSlotsPerEpochProvider(32)),
dirk.WithBeaconProposerDomainProvider(mock.NewBeaconProposerDomainProvider()),
dirk.WithBeaconAttesterDomainProvider(mock.NewBeaconAttesterDomainProvider()),
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
)
require.Nil(t, err)
tests := []struct {
name string
index uint64
expected []byte
}{
{
name: "0",
index: 0,
expected: _byte("0xa207bbed7d1e43585e5d42e3f09a5179f21a12a33b66ac9af47132c20f9b7b7caaa162420e095664ca3318fe365776e80bd0f9ef1e3b07a2e5340d0c07152234bf18f7596c8d94d72e11961ad8455f08c4417b0019246e24f570a166f86de2c5"),
},
{
name: "1",
index: 1,
expected: _byte("0xa17b1a6decb1503b5b8eacb4ca48e2f1665e43c587088995bb7e2da0738268ad0e1f28519ed79fbb318b9b98c6e8b65805a005bca4c98656fefb9ec6753df29ad6ef92da5e3074c027caaaf738d37fd09e08d8d8f86531bd80cf4152709240f9"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
accounts, err := s.AccountsByIndex(ctx, []uint64{test.index})
require.NoError(t, err)
require.Equal(t, 1, len(accounts))
account := accounts[0]
signer, isSigner := account.(accountmanager.SlotSelectionSigner)
require.True(t, isSigner)
res, err := signer.SignSlotSelection(ctx, 0)
require.NoError(t, err)
require.Equal(t, test.expected, res)
})
}
}
func TestSignRANDAOReveal(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
rand.Seed(time.Now().UnixNano())
// #nosec G404
port := 1024 + rand.Intn(15359)
_, _, err := daemon.New(ctx, "", 1, port)
require.Nil(t, err)
s, err := dirk.New(context.Background(),
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{fmt.Sprintf("signer-test01:%d", port)}),
dirk.WithAccountPaths([]string{"Wallet 1", "Wallet 2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(mock.NewValidatorsProvider()),
dirk.WithSlotsPerEpochProvider(mock.NewSlotsPerEpochProvider(32)),
dirk.WithBeaconProposerDomainProvider(mock.NewBeaconProposerDomainProvider()),
dirk.WithBeaconAttesterDomainProvider(mock.NewBeaconAttesterDomainProvider()),
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
)
require.Nil(t, err)
tests := []struct {
name string
index uint64
expected []byte
}{
{
name: "0",
index: 0,
expected: _byte("0xb990eeca35dadda689f5561ac39bba9a27a0c41c40bd1ce584595ba2a44782a89e2630ced7b1fc348b2408d15fa6746c177c5227625e39031e6be1536387ae33e21ec3de6d1d0b46bada1b99b621f8d40eab81882400c028716b22d31999b177"),
},
{
name: "1",
index: 1,
expected: _byte("0x840c144974632f09084b91ec7be5044c3fe9dd0dc7ce1031c0c78911807e264f36cb4fee0ddccf0ca93bada5d102cfb7118e6b75b5ecc5e18648a29f21f70727f3587b8d34bc7474d926fab4fb30eae4436153c336e6eb290d3d1cdd88ee9a58"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
accounts, err := s.AccountsByIndex(ctx, []uint64{test.index})
require.NoError(t, err)
require.Equal(t, 1, len(accounts))
account := accounts[0]
signer, isSigner := account.(accountmanager.RANDAORevealSigner)
require.True(t, isSigner)
res, err := signer.SignRANDAOReveal(ctx, 0)
require.NoError(t, err)
require.Equal(t, test.expected, res)
})
}
}
func TestSignBeaconBlockProposal(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
rand.Seed(time.Now().UnixNano())
// #nosec G404
port := 1024 + rand.Intn(15359)
_, _, err := daemon.New(ctx, "", 1, port)
require.Nil(t, err)
s, err := dirk.New(context.Background(),
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{fmt.Sprintf("signer-test01:%d", port)}),
dirk.WithAccountPaths([]string{"Wallet 1", "Wallet 2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(mock.NewValidatorsProvider()),
dirk.WithSlotsPerEpochProvider(mock.NewSlotsPerEpochProvider(32)),
dirk.WithBeaconProposerDomainProvider(mock.NewBeaconProposerDomainProvider()),
dirk.WithBeaconAttesterDomainProvider(mock.NewBeaconAttesterDomainProvider()),
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
)
require.Nil(t, err)
tests := []struct {
name string
index uint64
expected []byte
}{
{
name: "0",
index: 0,
expected: _byte("0xb02d15b68bb30bd2a9233db1fc31b6cd2e67692567d9af536acb4d6359d7e0246a975674bb12cdf6911a8301f3abf8c506473ba278ee0a09381482100b02c97e1b4901cb34c9b0f26cef892d3416d3b31a29fe190f392b2239392448e333dbb1"),
},
{
name: "1",
index: 1,
expected: _byte("0x87d7292ddc920c83057ae9034a8c02f828a2f793ddada099f23269cecf0c27372797b49088dcf4275bb603b8ad2a6edb08ebea42b7b5cce90ef22307926b0dd03e5591154c4f712830e5819a0614ada3de3b21d820c3e33322407f3b9d096396"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
accounts, err := s.AccountsByIndex(ctx, []uint64{test.index})
require.NoError(t, err)
require.Equal(t, 1, len(accounts))
account := accounts[0]
signer, isSigner := account.(accountmanager.BeaconBlockSigner)
require.True(t, isSigner)
res, err := signer.SignBeaconBlockProposal(ctx,
1,
1,
[]byte("0x0000000000000000000000000000000000000000000000000000000000000000"),
[]byte("0x0000000000000000000000000000000000000000000000000000000000000000"),
[]byte("0x0000000000000000000000000000000000000000000000000000000000000000"),
)
require.NoError(t, err)
require.Equal(t, test.expected, res)
})
}
}
func TestBeaconAttestationsSigner(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
rand.Seed(time.Now().UnixNano())
// #nosec G404
port := 1024 + rand.Intn(15359)
_, _, err := daemon.New(ctx, "", 1, port)
require.Nil(t, err)
s, err := dirk.New(context.Background(),
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{fmt.Sprintf("signer-test01:%d", port)}),
dirk.WithAccountPaths([]string{"Wallet 1", "Wallet 2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(mock.NewValidatorsProvider()),
dirk.WithSlotsPerEpochProvider(mock.NewSlotsPerEpochProvider(32)),
dirk.WithBeaconProposerDomainProvider(mock.NewBeaconProposerDomainProvider()),
dirk.WithBeaconAttesterDomainProvider(mock.NewBeaconAttesterDomainProvider()),
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
)
require.Nil(t, err)
tests := []struct {
name string
index uint64
expected []byte
}{
{
name: "0",
index: 0,
expected: _byte("0x960b865e07da42f20bef229c21d0e61f5e5028271695910736b6787cc501d0b46a5be62ef22a5d63a10168cf19c46b86004454c54f3fa432e92defd55d867ea84a918c4826f769302d3aee6b66c1bb9bb6fc92262c4abdd58560e14ce33d696c"),
},
{
name: "1",
index: 1,
expected: _byte("0xb51bdd3cec570d7e23b9b0ac2c93626759d6802a98c181d40750df1d64292f986b62228b948875b152289498dae36a6f0898ed142903eda3321ba96356b470b381ecd5f497b8f81b75d302649989ed31d1d09aab6d8930e7fe2858e92705e9ea"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
accounts, err := s.AccountsByIndex(ctx, []uint64{test.index})
require.NoError(t, err)
require.Equal(t, 1, len(accounts))
account := accounts[0]
signer, isSigner := account.(accountmanager.BeaconAttestationSigner)
require.True(t, isSigner)
res, err := signer.SignBeaconAttestation(ctx,
1,
1,
[]byte("0x0000000000000000000000000000000000000000000000000000000000000000"),
0,
[]byte("0x0000000000000000000000000000000000000000000000000000000000000000"),
1,
[]byte("0x0000000000000000000000000000000000000000000000000000000000000000"),
)
require.NoError(t, err)
require.Equal(t, test.expected, res)
})
}
}
func TestAggregateAndProofsigner(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
rand.Seed(time.Now().UnixNano())
// #nosec G404
port := 1024 + rand.Intn(15359)
_, _, err := daemon.New(ctx, "", 1, port)
require.Nil(t, err)
s, err := dirk.New(context.Background(),
dirk.WithLogLevel(zerolog.TraceLevel),
dirk.WithMonitor(nullmetrics.New(context.Background())),
dirk.WithClientMonitor(nullmetrics.New(context.Background())),
dirk.WithEndpoints([]string{fmt.Sprintf("signer-test01:%d", port)}),
dirk.WithAccountPaths([]string{"Wallet 1", "Wallet 2"}),
dirk.WithClientCert([]byte(resources.ClientTest01Crt)),
dirk.WithClientKey([]byte(resources.ClientTest01Key)),
dirk.WithCACert([]byte(resources.CACrt)),
dirk.WithValidatorsProvider(mock.NewValidatorsProvider()),
dirk.WithSlotsPerEpochProvider(mock.NewSlotsPerEpochProvider(32)),
dirk.WithBeaconProposerDomainProvider(mock.NewBeaconProposerDomainProvider()),
dirk.WithBeaconAttesterDomainProvider(mock.NewBeaconAttesterDomainProvider()),
dirk.WithRANDAODomainProvider(mock.NewRANDAODomainProvider()),
dirk.WithSelectionProofDomainProvider(mock.NewSelectionProofDomainProvider()),
dirk.WithAggregateAndProofDomainProvider(mock.NewAggregateAndProofDomainProvider()),
dirk.WithSignatureDomainProvider(mock.NewSignatureDomainProvider()),
)
require.Nil(t, err)
tests := []struct {
name string
index uint64
expected []byte
}{
{
name: "0",
index: 0,
expected: _byte("0xafd6b2ed80506b63e964820aba6523735d6156d4f2e3d53c88075f22b2a48447d6f083952e7d6c315a96dfde35b6959616591ac9d8b2d7f1c423b7f257e6f5eb4406b97b55270a9101cca809e76c7759aaf1235b028aa23da118697dfb9c34c5"),
},
{
name: "1",
index: 1,
expected: _byte("0xa006085be92bb0ee2cf2bba3da0d5e21630efb7e32a5e4fa7ca742ea0bd273f76a6336ef3a9817200bddbc0b4a6dbecf1303d9804806fa38ee05b7d5cfbba6e851c37ca587d66df935c296e6210db69f8b4c96f5e590cb83c7f82c06aee1d4c3"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
accounts, err := s.AccountsByIndex(ctx, []uint64{test.index})
require.NoError(t, err)
require.Equal(t, 1, len(accounts))
account := accounts[0]
signer, isSigner := account.(accountmanager.AggregateAndProofSigner)
require.True(t, isSigner)
res, err := signer.SignAggregateAndProof(ctx,
1,
_byte("0x0000000000000000000000000000000000000000000000000000000000000000"),
)
require.NoError(t, err)
require.Equal(t, test.expected, res)
})
}
}

74
testing/logger/capture.go Normal file
View File

@ -0,0 +1,74 @@
// Copyright © 2020 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package logger
import (
"fmt"
"strings"
"sync"
"testing"
"github.com/rs/zerolog"
zerologger "github.com/rs/zerolog/log"
"github.com/stretchr/testify/assert"
)
// LogCapture allows testing code to query log output.
type LogCapture struct {
mu sync.Mutex
// entries []*LogEntry
entries []string
}
//type LogEntry struct {
// Level zerolog.Level
// Msg string
//}
// NewLogCapture captures logs for querying.
func NewLogCapture() *LogCapture {
c := &LogCapture{
//entries: make([]*LogEntry, 0),
entries: make([]string, 0),
}
zerologger.Logger = zerologger.Logger.Hook(c)
return c
}
// Run is the hook to capture log entries. It also stops the entry from being printed.
func (c *LogCapture) Run(e *zerolog.Event, level zerolog.Level, msg string) {
c.mu.Lock()
defer c.mu.Unlock()
c.entries = append(c.entries, msg)
// c.entries = append(c.entries, &LogEntry{
// Level: level,
// Msg: msg,
// })
e.Discard()
}
// AssertHasEntry checks if there is a log entry with the given string.
func (c *LogCapture) AssertHasEntry(t *testing.T, msg string) {
c.mu.Lock()
defer c.mu.Unlock()
for i := range c.entries {
if c.entries[i] == msg {
return
}
// if c.entries[i].Msg == msg {
// return true
// }
}
assert.Fail(t, fmt.Sprintf("Missing log message %q", msg), strings.Join(c.entries, "\n"))
}

View File

@ -0,0 +1,4 @@
# Testing certificates
This directory holds certificates and keys for creating and using during testing.

View File

@ -0,0 +1,16 @@
-----BEGIN X509 CRL-----
MIICmjCBgwIBATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDEx1UZXN0aW5nIGNl
cnRpZmljYXRlIGF1dGhvcml0eRcNMjAwNzE0MTkxMTQ1WhgPMjExOTA3MTQxOTEx
NDNaMACgIzAhMB8GA1UdIwQYMBaAFPIpwPTZ6iEk+UgUei98/a22XdQaMA0GCSqG
SIb3DQEBCwUAA4ICAQC8ELE2LUXnMrJe3uO5G9IaNFv1k3lkLTsEWcbMPhdfJYP9
y8Tq4SWobIKywE0u2DuXDtF/ZxygfiQTXsCbO9PpOD6UIeszM3bycLWfYOeGjkfi
XYZNoVjA19qAPXvuKTo2N0omZARZ0hjRhZomXchW0w6Fxjj8/xA0Asii68XAuu6q
weRInI5wccVV79oKnRO1cWAj8E0OmaDMUMXrcATaVCsDdmyMRP3zTmgsAftS9QD8
DQ/kahPyMLlri8erR2cuQZhPONsQ9CEdo6DkqV+FPoNS6/a/0R/x0x3+WjpTOkFe
QcGj6USR/w8BwoVcjICp18VRwbS3bRT5tnItOp2/i8MV4dO9+KgiFag9bkbc8RxL
I4Vn6MaqaZcbdWeUux2zjWckI+kI5v80gwwLAUpP+wOSv9brwnvsXuAfWjfEtvzc
oTRlxLGCYEDNPxkVMTQ3oFYZPe25sQ7M5OAKgW2P2NW061jsjnLOW9gfZfCiaA+h
5I6EqYEI1K0aAOT70LAWLU1BNZMRDZqNdZD1OS9KIe3StX6dnYbGumzAbMLCmZwk
1C+VJThRKm3RcqGezxyqjTSUkT0Ek7Ok7Fn156Uu5LB2hTKva747IUQkDTv7/BOD
IaVPMOgcgWye6CRz8nRi9LW2m2UqjB/6EL7RLN2feiLE1A79t42sa2GdoI51eA==
-----END X509 CRL-----

View File

@ -0,0 +1,30 @@
-----BEGIN CERTIFICATE-----
MIIFEjCCAvqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDEx1UZXN0
aW5nIGNlcnRpZmljYXRlIGF1dGhvcml0eTAgFw0yMDA3MTQxOTExNDVaGA8yMTE5
MDcxNDE5MTE0M1owKDEmMCQGA1UEAxMdVGVzdGluZyBjZXJ0aWZpY2F0ZSBhdXRo
b3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKzi9DSBPK5b/K
TegB+2bQx6ExAn0goLtDAo+r0mypqWZ876ADWrG8E2dz0VTqLsT1BoSzjnlWWAn1
kWCbMvTgx3X11NVhnAMhSQPU9wuIi1sy2azaK2lTv9HCg17Q+8E/jl7BB/qlKgJ8
TtpwTlmoB7atCn4Gk2T3vvjbkDUhZyGBV0khqHBvj4E4zC8a7NgycE2kYZibLkVn
jAZwOKshU764S/ICgHAj/IP9WD50mXPXVGsa6Aje7eqydtRWpS2vvi56IPZJKPcW
CsqUCx6g0+IkUNj73NAzn0UAhgdO9PvNKuTyFzUfEpTI2HCPFzgc3pC/g6CVm47V
14KMX4uRqNyVeNYeiOP6vrJcnqu3/OTzWAYSTeII3Fqwp3m9niLMM1drWcZIUIxT
ymeUV6MQe4f49w4CwkUnpJI7FxUgBls2ar4QBzRJlj0LCP7Ri/rzjvvjmEzejZnZ
sk54z/H2zo0c2mHtxmF06abqByEpx7r5Z8uHunQH+2r8ZACNFFTX72tojVKYs45L
y6qPI/X48MuYIabi6KNDEElt2ykoYCitZ+GlIzyOR0mBxAt0TXE7QTj5xWOTWqgk
lllWuoizApUDDWbzDDANmaybB7eweVszZr8QIi7GQ8S/yO3C+Th+HBt6gw3A67br
F4rNJ6Ql/lf6fQBxNXnJgj6EhTQCZQIDAQABo0UwQzAOBgNVHQ8BAf8EBAMCAQYw
EgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU8inA9NnqIST5SBR6L3z9rbZd
1BowDQYJKoZIhvcNAQELBQADggIBAEMXJAHbRG9o4t2yuPDYqxSRo6df9wzgdFiH
FMEWuJidUn3a+RKepa6YN4BgaA9yygUm5DvMkyzUjL/hdfJ+9ORu5Sdbxe+/O1H4
nL/C1i+3p++L4ZpoNAX/jbnMmWnsGOc8qnoAw+9L3MYeTIK5r27xBTvRCnKvr5me
ynL5Tka6UYXigWxcZ+u1tvN/q/4OQ5R8vHSyPo5g4Vl7CNYQnLZewGS2B1u4f7sA
+Xw+Pelhbt6b2XyA0dO4O5JlXaHS0E+OZU8UDdbr0SL+byKBUd6ZqVLl3JnsH/Nh
bgvTZssaP0HN+deiOwTsJRJZFXtjn2MSyjWwcVTmMTJrjpcLnlTPBd/FB0L/m6W3
U5Fq9yR2h4EzyX3ZHTh+QF5G2f178WVLM99G8ZfQUiUYbEm62J1ulPfd5jN8yH3d
w5o+dHY+xMLOXjVNKv4oI5Q+2XGFAD+ACWJwvfUsN7F6MDW+5PjKaGz7fvoe4g/T
w7jsEKYyNdFQuArHZVTUALQUWLTIMJPiSQ1Qh8r0E/VH7bMw973jLeQizklz6vEw
fm+IPsuBZZDxcbeps2pW5VzxTU2q2Aww0AoucreSnPgZelk8U0WAuS3afqNjCCsd
630H9+Ssr3qrRX7iNRpLL2itWxduURi7ff4wJyDXsCIPVGAe/zyPuYKy2xdvwQcK
qN0RjB5h
-----END CERTIFICATE-----

View File

@ -0,0 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
MIIJKwIBAAKCAgEAys4vQ0gTyuW/yk3oAftm0MehMQJ9IKC7QwKPq9JsqalmfO+g
A1qxvBNnc9FU6i7E9QaEs455VlgJ9ZFgmzL04Md19dTVYZwDIUkD1PcLiItbMtms
2itpU7/RwoNe0PvBP45ewQf6pSoCfE7acE5ZqAe2rQp+BpNk977425A1IWchgVdJ
Iahwb4+BOMwvGuzYMnBNpGGYmy5FZ4wGcDirIVO+uEvyAoBwI/yD/Vg+dJlz11Rr
GugI3u3qsnbUVqUtr74ueiD2SSj3FgrKlAseoNPiJFDY+9zQM59FAIYHTvT7zSrk
8hc1HxKUyNhwjxc4HN6Qv4OglZuO1deCjF+LkajclXjWHojj+r6yXJ6rt/zk81gG
Ek3iCNxasKd5vZ4izDNXa1nGSFCMU8pnlFejEHuH+PcOAsJFJ6SSOxcVIAZbNmq+
EAc0SZY9Cwj+0Yv6847745hM3o2Z2bJOeM/x9s6NHNph7cZhdOmm6gchKce6+WfL
h7p0B/tq/GQAjRRU1+9raI1SmLOOS8uqjyP1+PDLmCGm4uijQxBJbdspKGAorWfh
pSM8jkdJgcQLdE1xO0E4+cVjk1qoJJZZVrqIswKVAw1m8wwwDZmsmwe3sHlbM2a/
ECIuxkPEv8jtwvk4fhwbeoMNwOu26xeKzSekJf5X+n0AcTV5yYI+hIU0AmUCAwEA
AQKCAgEAyl58IvMlbO1dOA4NWQz4R5Usb69AFPLOacuAeb/71kDHmBu03CP//uCN
9rAHv7bzqlzaxiGBSnuHVJfAgp2SZUojly7NzhzTsr8dJ8FsrNACLPew1/NBouRh
92sHjhnpd/Yk7xF7Npx45nn41uAX7ufjjUBPCVjDA8R4pv97RN2YPWxP+VoO+AOG
uppk1sVH5uzRTRpmIVNGxlCfjBPAD/107oo57+0h+YbcXk1T5R3Kzi/awHqRf4KB
E5wnvl4M/LUVw6BoohBSnpgeFSQTaACGRB64pnps91YSkLctS8iCCvSmiDxIMb1k
4hW4G9DbmVMttS0vbJpRKWlnR5N/vAypcTsIPBe8K3SSBOXLv11wces2pwjjw5UE
z6qYIAm8X1uV+jvnXVKotelW9/ZyfvHdch/GHFZrLSBmXpUlG78SuYKmZSzuNJKA
utm+ocXtJ/SUZORDIuhyFoE27NOruk+Jhk5OdrVVa/l+JFwAMr49VGPJlNNViMLs
lxPwtu59GHyNdIK45PXZC8wF30RRL7rImIxJnryiMxBPx5PNI/ZcLLT5jY8Etb2y
2su2y68jR8vgZb8mgH3ME0oLY/H9GR9tcHWfR4Z1X+kJmzouQmfCdWrqHzZbTBp9
R/RLIv32kkwlmoJWYvF/bl29gdafz/ssIyMWHBtD+vUJdsKPBPECggEBAM8gtiRP
1TNYtuRznlVHukZ1Qh4h4+FrKhbmGx9RYovujGsgJxwEIwfhTFlVoPC5mIB0a/FG
8dWWLSk9hhNQmwC7StI/BwVWf4/sIqiHoDjHWo77wEXyc2hmPwboCPx61YdZctau
DWVAwl0EoZHZ/GkdsVUMWLtbSl0/EqxxykGF0zIt3OI2xgxBebxOKHuLzG31DZdQ
oB8fLxCzTe5Ul2yHu19cJ72hI0Ctg+LeIRRzQZ8joeTT7mK4/T9492YT1zgwkKNa
OB1eNeDQ9Z6Du6PKhCth0xn+QPQvWJRrHKSM5kNJ11RYcmET4ctQh6+RSGuHgixH
+5hhAPSW91HgU1cCggEBAPqoYsfv7/y2bEOa4zXEnWSTHT1NecIe6jLsDi67qP71
UEVGUqfChEKVqzCRzAP05NY/BM4QXOWzpX1GRiOePzNCZ98Vu5g0oAKhlyWRgDHG
Y2Ty/qmmIWFHdpRcaEzA56RqzlO63zCuEo45CQx1S9jYDZWky/QEUlsN20chfDD6
fYmnZH2BepBiSCbflxy5U8BT17urEiSo/Hw3cEEt+hWfZh7bcd67Y8A45zI0C3/V
wLPK1YG3hyNSUHtBloFAT/FjNdneJE61Ycnzei3F+BlU4VlmH8O0jw8gxPo3rgvK
LE9KhqMoGAjxvHkK5/zRz2QSykZRhiDAsihjwFNDXqMCggEBAKDMZlreV0ebcbD9
SUgvfR9B3OiDquPPTEemsBuqFPVJZl2sAnCvjXqKn7kizuTTUN84gqw3RXtpMPo5
NyM7inoQ7M83+v1b34Ad8/IeCHbL3TPvoZ8r0AiWiAuWi5Nm0OpYuNyNFv0qPznz
ZHNUZa49TPQXt7ML9jlZw+d4F2qyt/jWvgooN6xAEH/ttWPkbfpXKgv0nbpLfUBb
0v5ZUY0B+qbXZkrDFBkcG60+gTPdHm6rPP3mwcSGlKR4BqiKcqS+nysR2UqDXxR/
ZI+A+WT4zY7YTQh66HYpY30lgoEEmaZXZwGmAHX492vdwti70xsXgilaYKo1dIZt
xOcdXdUCggEBAOrbp2KrAHQLATn/AHE6vjakWTs9Qp6OlOYNo+RJ1Ti+5e1izMN/
UKmKzxH9KelzJo9QENJ7Jm/beW390G5DMfh3ehfepx0gAeU1PwfmYvVAa5UE0XRn
wtMBQKwWQWvZO7IkmRp+9+0GzUARVNcleGG/XkseVDNZcUj7nL/zMgg6TDIUc+Xc
0dhDHlO+IDq7syt746Fl0uQiqiBBWZ7Y04A7EFZNS05kyjwrlQTHGxc2Uw6jOJYI
PkjsMZirhbepaL5GNQjkSaSt8uhkh9AntCUYEOXQ+GZI4dpM3AOO9Db7wbSxoaFy
ScLnra7Ed0W92NJtgLWOYVyC8OtDO8tITn0CggEBAKlpu+rvYA0KcFg3TGlLqoKM
VtbJRYwTfP9C4JVsTU/Bebd9ZtLAjizztlQTZjUJghB1Ro/lvoK4BTJ751wxPeR7
ZgcbOkFPG8VLl9/XH8oBba7lz0rwJ9cVfXFHXRmslPp3S5/06oheaD6gkjI5aTZ8
SgATvSEGsMoTOG9uRh86VMcPIxsL/SH01Kw+i5IW4nMKYRrKMmzAbUalwMI9pmLE
OZw9ZbqGCna9jyugAvUkmlRK7ESLplPP2hD1GI5mUoAaw2QW9c7RMeVA15IbdQ4v
F0F0Jdo/FVaJWHZ7nEJjXwaN2M1jSBT3jspK7cBnUc7Wu/+tFrPvxTo2TcHm93c=
-----END RSA PRIVATE KEY-----

564
testing/resources/certs.go Normal file
View File

@ -0,0 +1,564 @@
// Copyright © 2020 Attestant Limited.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package resources
import (
"io/ioutil"
"path/filepath"
)
// CACrt is the certificate authority certificate.
var CACrt = `-----BEGIN CERTIFICATE-----
MIIFEjCCAvqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDEx1UZXN0
aW5nIGNlcnRpZmljYXRlIGF1dGhvcml0eTAgFw0yMDA3MTQxOTExNDVaGA8yMTE5
MDcxNDE5MTE0M1owKDEmMCQGA1UEAxMdVGVzdGluZyBjZXJ0aWZpY2F0ZSBhdXRo
b3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKzi9DSBPK5b/K
TegB+2bQx6ExAn0goLtDAo+r0mypqWZ876ADWrG8E2dz0VTqLsT1BoSzjnlWWAn1
kWCbMvTgx3X11NVhnAMhSQPU9wuIi1sy2azaK2lTv9HCg17Q+8E/jl7BB/qlKgJ8
TtpwTlmoB7atCn4Gk2T3vvjbkDUhZyGBV0khqHBvj4E4zC8a7NgycE2kYZibLkVn
jAZwOKshU764S/ICgHAj/IP9WD50mXPXVGsa6Aje7eqydtRWpS2vvi56IPZJKPcW
CsqUCx6g0+IkUNj73NAzn0UAhgdO9PvNKuTyFzUfEpTI2HCPFzgc3pC/g6CVm47V
14KMX4uRqNyVeNYeiOP6vrJcnqu3/OTzWAYSTeII3Fqwp3m9niLMM1drWcZIUIxT
ymeUV6MQe4f49w4CwkUnpJI7FxUgBls2ar4QBzRJlj0LCP7Ri/rzjvvjmEzejZnZ
sk54z/H2zo0c2mHtxmF06abqByEpx7r5Z8uHunQH+2r8ZACNFFTX72tojVKYs45L
y6qPI/X48MuYIabi6KNDEElt2ykoYCitZ+GlIzyOR0mBxAt0TXE7QTj5xWOTWqgk
lllWuoizApUDDWbzDDANmaybB7eweVszZr8QIi7GQ8S/yO3C+Th+HBt6gw3A67br
F4rNJ6Ql/lf6fQBxNXnJgj6EhTQCZQIDAQABo0UwQzAOBgNVHQ8BAf8EBAMCAQYw
EgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU8inA9NnqIST5SBR6L3z9rbZd
1BowDQYJKoZIhvcNAQELBQADggIBAEMXJAHbRG9o4t2yuPDYqxSRo6df9wzgdFiH
FMEWuJidUn3a+RKepa6YN4BgaA9yygUm5DvMkyzUjL/hdfJ+9ORu5Sdbxe+/O1H4
nL/C1i+3p++L4ZpoNAX/jbnMmWnsGOc8qnoAw+9L3MYeTIK5r27xBTvRCnKvr5me
ynL5Tka6UYXigWxcZ+u1tvN/q/4OQ5R8vHSyPo5g4Vl7CNYQnLZewGS2B1u4f7sA
+Xw+Pelhbt6b2XyA0dO4O5JlXaHS0E+OZU8UDdbr0SL+byKBUd6ZqVLl3JnsH/Nh
bgvTZssaP0HN+deiOwTsJRJZFXtjn2MSyjWwcVTmMTJrjpcLnlTPBd/FB0L/m6W3
U5Fq9yR2h4EzyX3ZHTh+QF5G2f178WVLM99G8ZfQUiUYbEm62J1ulPfd5jN8yH3d
w5o+dHY+xMLOXjVNKv4oI5Q+2XGFAD+ACWJwvfUsN7F6MDW+5PjKaGz7fvoe4g/T
w7jsEKYyNdFQuArHZVTUALQUWLTIMJPiSQ1Qh8r0E/VH7bMw973jLeQizklz6vEw
fm+IPsuBZZDxcbeps2pW5VzxTU2q2Aww0AoucreSnPgZelk8U0WAuS3afqNjCCsd
630H9+Ssr3qrRX7iNRpLL2itWxduURi7ff4wJyDXsCIPVGAe/zyPuYKy2xdvwQcK
qN0RjB5h
-----END CERTIFICATE-----`
// SignerTest01Crt is the certificate for singer-test01.
var SignerTest01Crt = `-----BEGIN CERTIFICATE-----
MIIEWTCCAkGgAwIBAgIQOmQoybWcXv5kykIKSdE5YjANBgkqhkiG9w0BAQsFADAo
MSYwJAYDVQQDEx1UZXN0aW5nIGNlcnRpZmljYXRlIGF1dGhvcml0eTAgFw0yMDA3
MTQxOTEyNTZaGA8yMTE5MDcxNDE5MTE0MlowGDEWMBQGA1UEAxMNc2lnbmVyLXRl
c3QwMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKyN0GHe1PLPUvrO
jki9BJvx8QaiEyzTtmDv9N0AjsXOfgNlw8qdJ9uWDGEE4YduNIJg1pNqQuKaUedJ
sH4ddnGflVutEFGbC3awXFbOw3FYxNp6pli7E41sDJ1qihxb3E4xInEYDZpkBZkF
AxiujCN2wue7SNuaAc6J8EmUvvONArL1pAiJ7XeSYmx1HsNpkVobq7DMgnNcTr3I
D599RKX6PMpxtyAr+qgPwxXTIOno4AINIcAc3nywubi71SE8112c/fGHNU4Shx1y
hTKnbeE+Rmn5jsOLoknzqDrAkyuT9XNw6r9Nld311furo7MyTK9NX8nRXshI24dP
p9qk4gkCAwEAAaOBjDCBiTAOBgNVHQ8BAf8EBAMCA7gwHQYDVR0lBBYwFAYIKwYB
BQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBRq9vcOi24CL2wXKhfSo1fnuIHt6jAf
BgNVHSMEGDAWgBTyKcD02eohJPlIFHovfP2ttl3UGjAYBgNVHREEETAPgg1zaWdu
ZXItdGVzdDAxMA0GCSqGSIb3DQEBCwUAA4ICAQAV339n2B1/7zF3sRr6ZtTKX8b3
sdZD2uFzla4C/kvPQQertvlO1rTr3EfzEkvvA0X+knMqJ1glVSyVxzz/XFPif8IE
ddfPcHnnj/fObe/SysDv/R1AMlewwXwjPHggpCnNwXvxyE2ryLdSCFbsoSkZocqk
o6J0AxjlnMXXvqHVPEFYbLzMjguhRULpOy8PUX326jcxlBLjVejhwUfv7sS1pwEc
+tVH5IFHSGwGJSCfrnWh2mSkT9sxcGRXTJ2MFXH4iMs6wG9Gx6GoVtBuroXYgzcr
BLDe/5oUd+xNP47sJgYSnaTpGv2/WZnCCGangAjP+0jU6lN5CS861lIADZRmAZVB
1ZVlr0QPQ+Nmod+BM8qdw+kBSz/nCzEfTHrd4n3hBE/cFT4R9NrdekGCg6/GQIYb
sg5mdZkU+gwdpf7nUxyP6bJV6zqPZ1/ZwyRFcRqnXaLST45n2HCb1V754FUgg9jO
FQj4dtUjud7zs2J2KfDAPjXE7CWOpFlUjtDMjnaCyGh5IcRbgWSTm6KEQj38IU6R
wu/ezoj80BkYEP5Q6YOT1pDHUsNQwJW/cSV0ELGkfxovrN9VLRGJR+8uJ6j0wWMk
5cPmnLsvAuLPBO3iY+/w1ZKU40nebTwZL+2MyOAEidbLwqAtOhlsj9f8r0o4XBU0
QQ9lLQoXywGU8bfdgw==
-----END CERTIFICATE-----`
// SignerTest01Key is the certificate for singer-test01.
var SignerTest01Key = `-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEArI3QYd7U8s9S+s6OSL0Em/HxBqITLNO2YO/03QCOxc5+A2XD
yp0n25YMYQThh240gmDWk2pC4ppR50mwfh12cZ+VW60QUZsLdrBcVs7DcVjE2nqm
WLsTjWwMnWqKHFvcTjEicRgNmmQFmQUDGK6MI3bC57tI25oBzonwSZS+840CsvWk
CIntd5JibHUew2mRWhursMyCc1xOvcgPn31Epfo8ynG3ICv6qA/DFdMg6ejgAg0h
wBzefLC5uLvVITzXXZz98Yc1ThKHHXKFMqdt4T5GafmOw4uiSfOoOsCTK5P1c3Dq
v02V3fXV+6ujszJMr01fydFeyEjbh0+n2qTiCQIDAQABAoIBACcRPJrMDr6ivhDW
71P8p6x/DKkJzPmbPXGZIoFe/PRAGju+sKORDVMkF81ng4BcLTtPnYVmy5nugpix
EGqdVRHIpdJJzqYLSn8m0uE8kvd4t6kXl84DHRwp2HlTg82D5s81RK0CWyIXf0Tz
442VB1mIK/y3ZHmD1uDiTir6qHkPltYh1ZZyY5rd06321Nyi32CMAC3Sah6Jk9xI
czhmMADiHjFoysJDX4Q5FBZqgThYhDNaFNATOiAb8vOD31NjpWBJJXab6Mm2GugF
YLqVudND0vUXLHpwZMlt9sX31j7AOo1tricHsFZjGDd4S2a/8ugMRwAdV2gogjUv
Kdj1TzkCgYEA1+NSGMqQpjTFXaHuRv6NRkzyd6MDl4KDfdAeIZCS+6X6DFzkZUgA
Ir70+m36Xvh3NoPX+HPUkQQP/5ZmdkRLz9DGSJmec+y6EdW6mzXSPCYXyBNqC4CR
Sj6zv08O31FfI4jMWhVXTQfU3dDRJtwii7zZYwo7hAPgEUVC7qo54PcCgYEAzJ1R
SVSt2OxxMFdfE+M6+jbAXJEjkOXywf1b0SCpVoIEajL6dZMNsF+oLxzYqQy1UaSb
pCvPxQvCl/uAAWYntVLTOkPEvdUqsUit/3N04YWjOpZKeUL2fhtrhZ0UNqeLGNUS
k9OCj/O10V93XxPw+vOj7rtwUf58AOu5/qXJlP8CgYEAkd1NguKaiTHuiCz4yY8D
9RPYX20M6DmOjlsngJYmOVETeXbp+mSDcvaCnxHfsHtAUN0T9xKL9M9B3/bGk/Hh
JzBwSG1C2iCAN7yosGXU/j7eopg7djoP8JIc8I2CBvD7zw6Gw/bXXXyFHroQFql1
zeRzHK+1NqVHp2OcrZTmNlECgYBfn9XxU2W7zyRG105T2QojDZtwp1Pbz9tX1bQn
VABPsYumphRvBj6Lgujyu6R1vL6wXSFv5BnBmPFkXeFAxiEgmIim3i0AGrNNDw5i
J+8jxnS2WK6NZUIVRXNGilZ8BGj5PfrkoyCNbfQ22UrMYGFqppqiY27mouwI8iGG
ZKyEuQKBgQCvmHrSdXM+YvtYeCATDT7r5G0CsUPuxsAXrkdRocoE5Nxkkub3hNmK
K3sG1MRrPsTtBgvdnBnvP4m2KiSCXfrsDNfWXGcxPfsLbJhjtmdmQ3roKdiEab3O
/usXIC7wM2aweTKmN9A1nBcWugIVop7yS3JzQm1uNWfzPWTWuL4RMA==
-----END RSA PRIVATE KEY-----`
// SignerTest02Crt is the certificate for singer-test02.
var SignerTest02Crt = `-----BEGIN CERTIFICATE-----
MIIEWjCCAkKgAwIBAgIRAJ+RF/lFEwUcn+ENsCNJPQAwDQYJKoZIhvcNAQELBQAw
KDEmMCQGA1UEAxMdVGVzdGluZyBjZXJ0aWZpY2F0ZSBhdXRob3JpdHkwIBcNMjAw
NzE0MTkxMzA3WhgPMjExOTA3MTQxOTExNDJaMBgxFjAUBgNVBAMTDXNpZ25lci10
ZXN0MDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCnqL2UQZ0JSMyW
BbckBIGUN+jXLCi0zalhK8X8fZPRgLubgfkhqJInawNy5yCD6qVELaopJ0YViwJF
CtXKRzMuyMkH6w4Z94PoPTMMnAykfXuLzmUco3ijnhowzkRmD7hgj1JRCscKurkT
FxZeYyo6vQsfFJjuGx6DS70Z6UsEHcf7XVAn9u+5f26sGyeTvHqlPGAAdfCMKVRC
KVXbTwyrqjn/wFBy7K7BjxjbOBPjlnmDMbS8JBRlKw3xOKRQ9BoHtHBHnmo2rZHs
mrFlRYHZQbgxiRpcPGgVufWBKS8LFdNtTuafBpmlXCjcX5ijg2avjfFx0wZ2AB/d
OX/C3sSBAgMBAAGjgYwwgYkwDgYDVR0PAQH/BAQDAgO4MB0GA1UdJQQWMBQGCCsG
AQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUMXrb/F4hPpq7mEm7nGFaDxVfioww
HwYDVR0jBBgwFoAU8inA9NnqIST5SBR6L3z9rbZd1BowGAYDVR0RBBEwD4INc2ln
bmVyLXRlc3QwMjANBgkqhkiG9w0BAQsFAAOCAgEAC6DkcHVHegfZ42+FU7fLw81z
Jm/ngs4SbH6db249Q9lt00R70m3OU+vpAp3P/tIc/H6Jn7up1LItJvWlwUiqCyxn
YQj13r/lOWR9aqjS5jM4XvcjaiC1vfQdfghT/yHQT3HRsWSCsv+nDch4d80e20e+
ukPqLuDTTn7+nIWip2cHPIgaYOE6ZP9G3f3PORx8UwnTQvHiqV0tmBg61bD4xJmb
FIUFFmvG7LVmomu9GPdciXd9aOiBYmk+vHNXy5ekgDUR7xVM2Lt0uAoqegTZOWVh
UlAE1AAqL2YJcmej+g30by/ZvS/6GISYTGr+OhYSv+JAOY2ITBSrLD4c3CNzcq1d
SK6+hcVHRd9fv7Da3vpVVrNf4RcJGlzLFVfxCsrHeRrVfojjWW7voV8KpIqrBdX+
n1eWn1yiIonhZXvGo/UenPQ9QLjh8/l9ALn4DoefxdHnFtgFeyq5btAGKn5hEzOF
0Dbgob0B6s3JPQxk4DQiPwGFGGHLQGM9z3cbf7iOzf+3R2roTx+3s8WEljteYLOJ
F35AG+it80P21FzlMuLpnI3zbFomlx1U7Acf2lSpYshdRrcVpIfet3M8ZaraSDNO
mdY+QOjjjLpHwI64KqeJuCPbzdUrZW2Vth5DkDUwyX+Cld4G2HI3362NeI4gzWzG
tnOTVaeHiYpxrArnLno=
-----END CERTIFICATE-----`
// SignerTest02Key is the key for singer-test02.
var SignerTest02Key = `-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAp6i9lEGdCUjMlgW3JASBlDfo1ywotM2pYSvF/H2T0YC7m4H5
IaiSJ2sDcucgg+qlRC2qKSdGFYsCRQrVykczLsjJB+sOGfeD6D0zDJwMpH17i85l
HKN4o54aMM5EZg+4YI9SUQrHCrq5ExcWXmMqOr0LHxSY7hseg0u9GelLBB3H+11Q
J/bvuX9urBsnk7x6pTxgAHXwjClUQilV208Mq6o5/8BQcuyuwY8Y2zgT45Z5gzG0
vCQUZSsN8TikUPQaB7RwR55qNq2R7JqxZUWB2UG4MYkaXDxoFbn1gSkvCxXTbU7m
nwaZpVwo3F+Yo4Nmr43xcdMGdgAf3Tl/wt7EgQIDAQABAoIBAE0yhRgenhAIVSs+
tnT/HisBE1UAID4f9D2pyh/YMpfkjn2r+upkk+dSfuQJSA91m2MpI5CPZNXGi+T+
eDILVqXUDbx3nqaWMUZd54OG1stme9yDzErDemjcA3M1hoj39A2B8IUgUUW/dDg2
CTassmUZZmWJNmFsW0BZP1kO8luSHAnGqXoi62JdLGdcmrRIoeCdIhkCTlV/ciQr
WotnsaEF5Kz9ta0nnxB/Rr5DSR4W8x22ALo0bxKVWHDpKF/0t9ElBtzQat13p5NV
OIp/V32DUI2AGBem82lDxYCS0aAotxEljyB5TqmJQSJfXQUxRc0/dXK4Kdecl/gH
6dRcfYECgYEAyfRo6eo4WxcLpiKj6vMbGHcEneCaiwjxJD9KAKntXxeJ5NSDxTfK
7Apio0wRyCSo3mt7vNyVNhxOz2uO9mo5CqgSY5fNHlZu971fNEXp0vg6GMNS768x
/K94cbv5u1nOnIXa5SEixWr0Lh2ZsG1vavTLxHcMamv+7N437Ak7V7sCgYEA1IbL
yVKK9CYLaXuLTvHF2DF74BH5d8VXnRz0hMd82cFDTfNK6MwfNrOomN8mO7eZCAzG
RRsaU8X47UxeRDh4E2VcWToSYo/d6i0Wd7IF4WZeGol9PtXFGYxWSv7NkR9F7nj9
6Y0FXQblCdlfkQeI5TWxDMqcBGw5QxwODJAMmvMCgYEAqulMDIIq1XQIaL4yKPk6
ehbnclENmRKlOT7SewNUHsDF80Gijror4lzbo0USW2Yi/7DI1El9gYCtdb6aC5JT
2d/pSB3E+qK9YK4ELzHns6JdUG2k97E1xZoefWpO664SO8bQPE8xpQ9hvNFSKsxC
maq38/moKTxiTsW1X+1kKlcCgYEAqs6remKcyxzIjz57+DbYi6k5phzMIza3884R
t6Wc8mYhccTXr8JeU9iQ6Exwrg4hMBcUQvZFco7qQc3e9XVtDCmqzwudOxnlgRA7
vneVwlJDz5Aw2Q92GdJwiFXBYaGA0ujrKYnthZbE/eV2qVkk7RL5+Q3d1rAkVYt2
vyIG/4ECgYEAvMFs1kpWmIGuW1LI+gbXil+LLpR6l/4Lr9dbcW2oSTF88TW7Ijs6
kIoeB/eLMWt8jDnyp9G/UoB9jfFgtvZ+gGyPizZQWy02sY0laQnmq9RXA8dkIPtL
8zLX+YwCSclX5slV0OWwqTlzp757AYHx1rLFgaFt3rVwY6lveVITjH0=
-----END RSA PRIVATE KEY-----`
// SignerTest03Crt is the certificate for singer-test03.
var SignerTest03Crt = `-----BEGIN CERTIFICATE-----
MIIEWjCCAkKgAwIBAgIRAJu28fjs8COygbgpPnST4icwDQYJKoZIhvcNAQELBQAw
KDEmMCQGA1UEAxMdVGVzdGluZyBjZXJ0aWZpY2F0ZSBhdXRob3JpdHkwIBcNMjAw
NzE0MTkxMzM0WhgPMjExOTA3MTQxOTExNDJaMBgxFjAUBgNVBAMTDXNpZ25lci10
ZXN0MDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGg2WKF/2VcMBs
YMpgTAiouP9eoXDkvVQd97GUyMfTH8Oz1k+yNZ/WUU/k5z33HTkAyJkLxreDgOri
k+wuZeLToEbB414N3m7JL6ixbo5jt0A134v8zNetGasBz8a3l+JqY9reQPyyTrMi
va5zcGkDJTTVaerVrdclfPq7AF4NnsFP1qNFZoU9pqFoZN76Oz0lUQdv+qy/VxCz
r4QuF/1TNvTU/k/3yPM9uIOfoCMaCdexRCoa3BcLF0QiC3KOTOAUkSdWVz0pYZW7
aoaAo7a+PWYbpm/FAUGPXWbEWWHdtWkoeUyygjMrjqrLQsdbqOl4QALOKJxrS8sR
ueHYlCv1AgMBAAGjgYwwgYkwDgYDVR0PAQH/BAQDAgO4MB0GA1UdJQQWMBQGCCsG
AQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUJCvuUovWLCLq6IMuJcgeoFFT734w
HwYDVR0jBBgwFoAU8inA9NnqIST5SBR6L3z9rbZd1BowGAYDVR0RBBEwD4INc2ln
bmVyLXRlc3QwMzANBgkqhkiG9w0BAQsFAAOCAgEAGkQb15A9nctJ+aq+tc9wtkgZ
Quku/o/boQ04hWrVaMj4kKw0cVXRApa5LdHr0YHIcOddvCXq73N38scIgmMlXS5O
kaLnwM2J42zlze1BtPxJyqynfz5ifqrRcuH89CKznENbUdWmCwsh2jU9Jxme7yIp
2J0uU472PyLdQcDPD0ah89tIcQ51fPaChY8RGlndAzjkOPUHm9UWjE13Y49ca16h
xFHGpxHLWmjvOKn5k3Y3q2hgXR67DP9sXYEA1iRPZzhWztJXzWePRzPjYfaC9orm
y8YzQa1MgnuGbrAsJ5xyEWsn5Px7ZdiEPNmNvxBeWtmJGL0w4EeZ9UR5P55dVdnz
PAkju3MUqqb2uY/tKzD5Ps5UUuZT8Q/aZUt6kQjeu8Li3bvIQJsdPZ/AghTwQZek
IL5whpCMLJIpK5PKHzXUK3fCHWKLvEZRLhjS8FOtLdqUM5lGkdkhmw+xIxgfRSu/
oPGrJzTEWohoRKUcmTRNmwq53OJxSqS82tnXJFNG7HMhzp9qwEQ+IfJMZBNSEA9y
EdgVypD4J+EsKHM4vS150qV0Ipm0TbXPQNMcttm1MaBUWoiOl2ZWhhnLH3eIMTVP
AtjX7nZ2WsXL62pOOPRzmq4mDRklrZOGJLALlAbh2GV6Vlgl0INLhGKMCg4zR9zC
1PBzRN/jGLFUtPWDcfo=
-----END CERTIFICATE-----`
// SignerTest03Key is the certificate for singer-test03.
var SignerTest03Key = `-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAxoNlihf9lXDAbGDKYEwIqLj/XqFw5L1UHfexlMjH0x/Ds9ZP
sjWf1lFP5Oc99x05AMiZC8a3g4Dq4pPsLmXi06BGweNeDd5uyS+osW6OY7dANd+L
/MzXrRmrAc/Gt5fiamPa3kD8sk6zIr2uc3BpAyU01Wnq1a3XJXz6uwBeDZ7BT9aj
RWaFPaahaGTe+js9JVEHb/qsv1cQs6+ELhf9Uzb01P5P98jzPbiDn6AjGgnXsUQq
GtwXCxdEIgtyjkzgFJEnVlc9KWGVu2qGgKO2vj1mG6ZvxQFBj11mxFlh3bVpKHlM
soIzK46qy0LHW6jpeEACziica0vLEbnh2JQr9QIDAQABAoIBAHD7j+sMxHMtfRcx
73znSXZd9FozoEFP0HRN6XA45iIvTf8o1qsjAhnEpaguRIJEy5C6mwCs1P2vff//
GMk/i93OtvbbJUjXdE5lJan2tmvifFUtKktzer02grHBQ+RyOZc7xfIBItGJIUOA
ma1yKRJ1NqDQa6u6CV14yGtuRhmRYyiO+k43n9ig5GNtnhMN1Oi3jii6BoKxBZGE
ooFm3iQx3yqRLWo6nvvumjIGerdvhtACKI0SqlXacbzeJxa4WlLnlj3ccN8mK+kO
bQYR/HeGCn5m+0of39cBFooZjO1iC+jiy1bI10QpJ3Re0dEn2lKf4Smet2ZWgLoS
/nAHlPECgYEAyGNTjCDYOJk8ZzqRGfwdzwmDOxTeujD1kKBufusDmPjZc5YSWY85
iFUr7NihZZyfo4S6AsQlbwswG+vY74eHe33sK9FCepkymHTCgiE1SY1GlhZBV3lB
9hERuSz2VA72x6AuoIN0NaQJ4MyzDqY+jm4NQ+XUKO75B393RXjc+psCgYEA/Zrh
IAB/KJg4gLQrOYa/5dBjGIlIs4TbnB1lgWsYyaJDySR0YITIIJpTD2bgkG0eqjm1
4fFOo/znvISapEQh7hslusaJzRum2yExvCPrfECtcbBx52T0dUHWalY9ejMew0eQ
83Dw2TrBytzHTIsuX8y3NVRw4rDa/hjrY41+VK8CgYAaPl/nvzlyGCeAAXyVYZ5p
yf4k07PjwJu4iDpQZuj+tMCN0b6vegF36GerSifBDgUePji6OgQJCfcQARBVNnO4
6aHvjyVctwmYS9pZfo3jBxySdXGzSg8occ3XaZsNITSSqljQ7sZebBBbH5PnvD//
GUylcskZX0q//6KYN58BNwKBgAiNSn4rxh32VCFy8eo0sw/q4QyYxIzZNBalnyCo
HePexu5nfk0q7Ry8V4SzcWstYtVWsN13p7E7/AyNZDGZ4pMG81TDES6Leir1iZnQ
lEZSYAbvbkfhTaUOnU5krhoK00S+ixLKgjSxGIvgug/Iub2dR6hSuqPKVvgumvF2
egYdAoGAFH2UHTH4pa0U0PXG0GMZG40gMpBLN4jJTruynf/viwdvoKkpUWdjbjl8
GNwlttIq9YzYfrUTLn1sYhROrEUIUFmxc2ttFGPjMUifzosVDUbzMRbwhOpSgzof
K6dgyN0czk0YccR6L6TCQ+lGL1zNdE567TUMT8DcujPRzPp6NhA=
-----END RSA PRIVATE KEY-----`
// SignerTest04Crt is the certificate for singer-test04.
var SignerTest04Crt = `-----BEGIN CERTIFICATE-----
MIIEWTCCAkGgAwIBAgIQSVCO/y+/drLLF1/Ehl5HAjANBgkqhkiG9w0BAQsFADAo
MSYwJAYDVQQDEx1UZXN0aW5nIGNlcnRpZmljYXRlIGF1dGhvcml0eTAgFw0yMDA3
MTQxOTEzNDVaGA8yMTE5MDcxNDE5MTE0MlowGDEWMBQGA1UEAxMNc2lnbmVyLXRl
c3QwNDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAONujJphNIMRsSMC
NGFGip151lMGNUGCOimjCvy/DVmBGIvMacqCp267rUbogz1fyVt8JMwjgbaA1Uou
iJoMPC5PFnz9+/jETbjopGGxMXI103R/FWIGlpTozWq6G7u9ou7mBS/zWPen5aBt
IwVZKQFNBDiGUn50w3F5Kt/otBLwFHL9qlHfsYeIGWzsI0y3j3oDSGSh6JJKGZDv
MBSh0bxHnZPoVkHU15otF4uttSheYp6+otZZrVTb/C3Lr87CretjkCCqTFdqossn
bmRfkFy7X+c1LaTiT8IfHEiOWehsJA6Cy3F3dxBj1knccBjShBHTyKiOzJSxY9Ug
CG8AgE8CAwEAAaOBjDCBiTAOBgNVHQ8BAf8EBAMCA7gwHQYDVR0lBBYwFAYIKwYB
BQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBS9d8lNgz2ImVGa49a7JIeFY1R8IDAf
BgNVHSMEGDAWgBTyKcD02eohJPlIFHovfP2ttl3UGjAYBgNVHREEETAPgg1zaWdu
ZXItdGVzdDA0MA0GCSqGSIb3DQEBCwUAA4ICAQAUFKQqRVcsOJmKcrNhOeCPfjdR
1Xt4S9XYGEtdxOSHcnwiOvj/p3lCJAtqphVEDxe4THieeL05xMcOS9Q01TNTiNV5
dIm/N/hxcKKVYEeM7HtFSHMRIRuxb9wD1lgDV+ZhXXYNbs+dnSt3mENP5+FanVRP
JhfLPxbtaG/QR+N7ZQyvcdWv4jHfvPGB6l+ySP8IZOo5SktDTeEJYsjUgKZbSyvb
T6CTpftItgJo8yaRdbE5TsWx017KWh0vlk/dQAvvxQakN9aO3/JgtxcLPEkmNJxN
mIJA1xAcxV5/ixW+mX13lDOTsQc/PwrvzKW6OFvlvgPSfCMW0CVaFJf/yNCkngoc
DQIKPqRX46VLhgkGhsl8f1L7iuMn3tkERzrQx8XQr8f0zYTVyp5DbzdhZ51e9MmS
LNeC4NWDGhBhlepSpnWISiCgR7zkQmnbAL2CRHhNXu7f0aElRrvQ3LyT45Zvncy7
763lVGpdsdSEY1kKISMyFzGWMSDQI68J+5rEtuLews7KQimaKrEcp1b7bH5O6IjJ
hedkCs/Yc/n4FDuudYvdsDHFT2x0HTZn+qkIX57gpzSek3+1b3I5hJQtWgcSx/NR
neIRkZVTCW0R6hfKW7lea9rDTHMiyJ8jpscZjqg5KITLxJJ3ipg3miXxjeUMOZRW
6u0QVYXCMU+um5odFQ==
-----END CERTIFICATE-----`
// SignerTest04Key is the key for singer-test04.
var SignerTest04Key = `-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA426MmmE0gxGxIwI0YUaKnXnWUwY1QYI6KaMK/L8NWYEYi8xp
yoKnbrutRuiDPV/JW3wkzCOBtoDVSi6Imgw8Lk8WfP37+MRNuOikYbExcjXTdH8V
YgaWlOjNarobu72i7uYFL/NY96floG0jBVkpAU0EOIZSfnTDcXkq3+i0EvAUcv2q
Ud+xh4gZbOwjTLePegNIZKHokkoZkO8wFKHRvEedk+hWQdTXmi0Xi621KF5inr6i
1lmtVNv8LcuvzsKt62OQIKpMV2qiyyduZF+QXLtf5zUtpOJPwh8cSI5Z6GwkDoLL
cXd3EGPWSdxwGNKEEdPIqI7MlLFj1SAIbwCATwIDAQABAoIBAEOkiaUQ7DFffbPP
4AxekrOrnRcsbYKCXRItMANkP3AzeT17GqvkmC/TGgJQ/VevuY/AKKGeneHOB6H8
nRxUL0IGu8WJNPwURpmMd/emX/J8F9w6P/3bv8WiSBZKLB12lZNATqKoWfmushk4
3IWmsw9z/KFjMf3ydH63bw0RhR1sQr5TT0BLje/0z1neaoVNfocTgySpM4DH+Mpv
ZE38VR4+MlujKpbdGwR0qcBwvA5tG4jkGLBf3TPTYYMpjnDZZ9ZRYQ0BDJhWEA7a
3Dpy2A1OGsXIQ5wt3MjPqK4el1mIcTaaUvaIHNEzB9Og6y07uMMzJJtTJsz4pgcq
VauWWgECgYEA++RN5Ii7Bf4J/PyesUusgkMpu22Umc4UImipJzGhwLCauZdKn7Cy
ZwvZH4aVGfoooCWlYTwDlv2exWinz1RvEGsP9SMykOk66A+RU/Ej7PP7zqQcZN5k
P/Qn3BfyO5gksbDhnm+DJl1i7Gre+T09ZsHCunGWCS5jatlfUhfMZMECgYEA5yQe
tFl4icOPPxOA7ISWy5dhleTD97DikqCgntqxA52SgqtF2LAHXBl+6bdQBf5w4zpu
FBoXtVBZdbmzK2ms3LQpeyzuYuRNJLwtrVGs+YLUXrm7aZPHBPKGH+kRTaU62t6A
ou+hytMNMXDDYICbf1snEemKC6H9qSI0A6Vf2Q8CgYEAk1ss4ivG1SuXJkOWhnuR
kKa/zCC/1PZEuxhlFEOpr7Lg4P+LrT3OMBAzVYkCwq6gg4diZy6XnwYBktS1jsmD
K6SmMi8EDtgSGN26k9O2w5C711gUMEIVfYBUrSHpGEnZ9YVXh7sOiywIieu/Qyk7
OVjSlQWL0xUrHb/KTpkTfkECgYEA0xZWgCfxgAa7bERYiiewOy/9q9Fm8m51DKlq
5ogb/oxJv9HAkNp5bi/OioyhpUewOqQi4XLO0gQWHwA/U1dHyasy8s2ey2tp1DGS
mWUszhUf8341XH7b03XU7ZGA/uL1s+pdme+0VzGVK+CqXRg2agGJ1b7tFiCTMoIM
9INz3BsCgYEA+29TYqx2UTun9PxELEbJEZ/IC8jMmJROpx6Ido7mky5huJlgfhtU
C7YbhCkChxM6hbgehwGWH8xj1jbVkliPe0XpABVkIACXKtQMzhg4shHlCmRTgZ+h
xNFJxVdoGRAVUthJyUTcAxWZMH4K5giMdzcQk4YxANekoBmUw3itinA=
-----END RSA PRIVATE KEY-----`
// SignerTest05Crt is the certificate for singer-test05.
var SignerTest05Crt = `-----BEGIN CERTIFICATE-----
MIIEWTCCAkGgAwIBAgIQFx8Gc/4fzxgTzS4MtpoovTANBgkqhkiG9w0BAQsFADAo
MSYwJAYDVQQDEx1UZXN0aW5nIGNlcnRpZmljYXRlIGF1dGhvcml0eTAgFw0yMDA3
MTQxOTEzNTNaGA8yMTE5MDcxNDE5MTE0MlowGDEWMBQGA1UEAxMNc2lnbmVyLXRl
c3QwNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKuCo3uGGnlWK2Mr
qaX8Ep8USj+298tjTUogBUe1dvlkgNBiY9MiUuaBg3VaAqJy70G/nMuWos/Z/+m7
c+SyJaZaMGtOf91gSpSWWN2Ugh8PivgJMi+FWiSKwK3sYEN7V3g3iABGkNCfduA1
4eTAdKCBowQ7Xxz5wpWL5DjjgW6B0KbjL4iREzTwjl+bPHdOFEHzIdxLh18CRU1D
dvdwEwn8ST0VFdjl2hQVm+EYlMv8gyyl9mFaQ16YGW4XJSIjXNDIcxpe7ux6157o
IO9FS21A4aiNKWLrLtJEErX2F/PHZPb2i5L8kbumhom186VJssIlMGGFIfO8UiYC
ilwOWaECAwEAAaOBjDCBiTAOBgNVHQ8BAf8EBAMCA7gwHQYDVR0lBBYwFAYIKwYB
BQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBTYCgsnT8K6EV9hMxe5laZJHW4mNTAf
BgNVHSMEGDAWgBTyKcD02eohJPlIFHovfP2ttl3UGjAYBgNVHREEETAPgg1zaWdu
ZXItdGVzdDA1MA0GCSqGSIb3DQEBCwUAA4ICAQCOhEuD8fMm5iEU+416MoTQpLwX
irHPRym/5fGQxV5AG7ij9X/Pb9WPa7EO24K8/zxcmr7zdkMM/g89PmT/+Aa2Gy7+
XGNhGOQd3xgNcCk0cQ9GL/4HeyPWvLh681difsUEx3Gazh2NXlRAw2rScHmPuu06
+qZwu+zJkL8BUEXMgP4zh10B26zQQ/uFyE4M6Y0h4s2bOC06+vK8OBasklbC36ry
4x4BKlliADx9jtzHmsZJ30jMvjh6Uc2aPo91CGNXSfw4Zs8Ncz1fbyYlWd9goB9C
gxQsUK7o8JARioQQ0JPkMwh/4C2d41G7UFSDesOzbOlx+llNnE7JiWJiV6MFX7VV
Sy92p9/n0MV4pHYtiiftPhvzdLXRhqdKb+hAeYjEAquvHU7MSEv2EAB4Cen0wgh8
CAFqYrQNjZgiTZuPwZljoMlYmuGue91GX17+UvNA4hpUKXWxzampkKnO/Pp/TbCn
DQenKzBwoeY+faTZq30wAyvxfVWh1uebTxIf/7nUdUkVPVZDCwhbQCMxomXHwOhF
4xMTHOmCFxwOuUWqUwQeXIYGgQx0sm/qjx48+jetmJMOOvE4NEXVuRsP5Ggylqa0
vVTqf0eZISAIaBg+dVBe3NNCAfT89DtCE5j/pnqwbcK5sQYF1oxLLs0Wchz31L7Z
8lyeVv/66rxC8CrFSQ==
-----END CERTIFICATE-----`
// SignerTest05Key is the key for singer-test05.
var SignerTest05Key = `-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAq4Kje4YaeVYrYyuppfwSnxRKP7b3y2NNSiAFR7V2+WSA0GJj
0yJS5oGDdVoConLvQb+cy5aiz9n/6btz5LIlplowa05/3WBKlJZY3ZSCHw+K+Aky
L4VaJIrArexgQ3tXeDeIAEaQ0J924DXh5MB0oIGjBDtfHPnClYvkOOOBboHQpuMv
iJETNPCOX5s8d04UQfMh3EuHXwJFTUN293ATCfxJPRUV2OXaFBWb4RiUy/yDLKX2
YVpDXpgZbhclIiNc0MhzGl7u7HrXnugg70VLbUDhqI0pYusu0kQStfYX88dk9vaL
kvyRu6aGibXzpUmywiUwYYUh87xSJgKKXA5ZoQIDAQABAoIBAHHPie6xKaY04Su4
0KXdpPm9PBwVrU9hAOvcXcSdDWsnHzeo4rc7gqmFbheUeEUWYeBOZ5zNxBKLhf+z
LY+oC8Xc+V5rw/vCJxt8vVGkd8hmxwAbEhtosU2oaX3Aaoy9L2kN6IjOStC10Out
tc3XTE0qWWO4hkAzGMWmA/cgOUZ7dfSe+qrBiMcBcQiDWozeSztl1FR1Wbq34rYI
ql0J3at0Ca9hiDR82T7DYAEZHkaASCvJt5wtRYmT+JbkqgSWfQO3F6NEXk7hOBJI
RYjx/enPko8JDTY/OQS7JtB78WX4n9ndeEdM7W9rJUAiz+08oODIlPtYV5Iqrov8
Q7cF+QECgYEAx/Y3HYza2DbychO8f0vjH/tdsjySA+BGxF/M0dQ1GpMceIsNdhPM
B3vSSsQaROIhi29++g2QjFRqn7o6K0yw5DfecerzCVo1CVSIoTZQDLSiP3pV+vfN
C01uWS3wnoRlnAYIHbyIfz7nGLu56JQ2HNnBIt1I6Rb8tLBjRhFpIlECgYEA25M9
Y8Q/Y8Pcl6GtDNxAJAj7DRrhBGRwgyu8Ka/MuqLWM6DN8bvsZdHP45FXG8dSU0Sz
0ybKuSjohnopacncBOnpjh/sEqqv3S+4/j8jghmIa+EjsIPlxIKjX7dwXmwXXMRf
zBUpXJpOfFe9ulacauv6mkOobdmZA0ZuSV01HlECgYEAsiiODLcN2SyDsN4iySw8
7abRYVeUJP3zL03HuIAg3E+MQ15pHPYgh95rjA/S8+KiTpCFipcBXfZslWmgICoR
RRT+DXNvHLsRnAGERlaU1e0uze3ao2ObfeF8WtqSkzmVKoE5Q/1RhEXwMto3lqBO
4j+lU8HjD0Ja30Z0/N3QVTECgYEAzCPOFW0lChnUgtz7SFOVBmubDIoK3cyLlkgY
/iDFlFdEEmfUUIRIujkgsBA2Dkt3zJa5IPyVySOxWyVET2guuBrI2yvujURHkLqH
oUkOOCyI2tNMHRXjjpluTtT7Ea4o4kRoVBLwi3mispPYft97OST/rmBsvQRq79KR
Qn/3nKECgYASJ8lZrUMTl74amFSGVrd4xRPhKJTer4C1HeLlwUaAKlEksNvpNecw
l3inYSityX8BXZzOje0pINg9Hd4+ylPzh1PxqCrRjyNNb5R4z2nJrVb8hDCcoG/p
Mia3unc6Qwos7FDwj9okULGK9P+lq+3vDvtiFflTZZsq46qmzrEmtQ==
-----END RSA PRIVATE KEY-----`
// ClientTest01Crt is the certificate for client-test01.
var ClientTest01Crt = `-----BEGIN CERTIFICATE-----
MIIEWTCCAkGgAwIBAgIQEmQiGczWl8GehMItbxxtpTANBgkqhkiG9w0BAQsFADAo
MSYwJAYDVQQDEx1UZXN0aW5nIGNlcnRpZmljYXRlIGF1dGhvcml0eTAgFw0yMDA3
MTQxOTE0MTBaGA8yMTE5MDcxNDE5MTE0MlowGDEWMBQGA1UEAxMNY2xpZW50LXRl
c3QwMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMgqnlKXWgKe2/tl
OYQg+szYJKNCOnzq9h2LgDyGAg7weKToPFhqDDJeONV5Hs8Oe5J4hLw8nTy3QVc5
Ir4sqjdBE522X0ZKSVXkP6WXT2DknLfFqiYHPHfK1t8fjhGcIExfo3sU7x+tyZT+
tQwe3+wMd1/deEl/Y9imKvwJihTCtAORKlemyVzEdGLxlQkZ+OKIbmZ5WD1eru5R
O/sLkohoLqsF6kKwO5nsbs3ovD02kTbXCavofN8lXmk3Kp7e6Bbj0ZWtM1sx/1KD
iDKsX1eobdpl6cMhPiBsAbxBG4kQqvAuC8MtIWQrvHO+jPglo3Hfl0FvYhit5iFJ
uodoSLUCAwEAAaOBjDCBiTAOBgNVHQ8BAf8EBAMCA7gwHQYDVR0lBBYwFAYIKwYB
BQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBQjib0wXi+YdCOBflTX/Frp1tD/xjAf
BgNVHSMEGDAWgBTyKcD02eohJPlIFHovfP2ttl3UGjAYBgNVHREEETAPgg1jbGll
bnQtdGVzdDAxMA0GCSqGSIb3DQEBCwUAA4ICAQCKW9Da1WZ+TimbjhjKclm60OjT
yHX5pH3eZrG3iqkpSgoBMFKCtIEulHk38DTqEqKESFubU80A4H8lkQSWYxx/OV+3
OLYh3QgXv3R92pVqrnRD1Dspy+YtePrECART+RSCVoN2+4Oc+rqEMJtshQDGMlVJ
wN9mp1OiGiAU0EyNNUDmxoMaWs3+BGMSngbgTY2I3U76RFwWqXi2FK9gGiAfH/Vf
XQ+AKXtPq+pQdLPjGWZ0KfzmHUtaxoR3A3u6G4hi+eh7PY4N64g/3lO5FwzEK2ke
VSn6xq50PWk1OkULyWVobo9VsXiJaAltBV6Le6Eyk3dofFb8zp+mKedDEC/anhXw
tzO7OFltqOiyaJNOdAXgsskom71PTDM0aJEG/8Jl5eOwlEoKi4A7KRFt6rq09SHj
Ww8yjX6EbTUmT9plKYQmKCshJ65e1Y5rGElxTzfzeQjDAV+584xzF7heUcKbBn+o
Sndol4HdgMo+yLwbyPL/GdB2m+Itzfid/cFUd57X/9MuPrRvMHmHoas1e7/DtuqK
riQ2B5PmKjvDz+nrR7aIR3nMFSlA2UAM4sGU0hmAR9XQRf7unKW95tcKRLx/+Blt
b71wse/U4f4QKz+JUntuY/x+Q13/np/DUDz0koYRtwqe+J4nlZdSH9on1i8lTXcj
yWJYDKQTImOKFINmag==
-----END CERTIFICATE-----`
// ClientTest01Key is the key for client-test01.
var ClientTest01Key = `-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAyCqeUpdaAp7b+2U5hCD6zNgko0I6fOr2HYuAPIYCDvB4pOg8
WGoMMl441Xkezw57kniEvDydPLdBVzkiviyqN0ETnbZfRkpJVeQ/pZdPYOSct8Wq
Jgc8d8rW3x+OEZwgTF+jexTvH63JlP61DB7f7Ax3X914SX9j2KYq/AmKFMK0A5Eq
V6bJXMR0YvGVCRn44ohuZnlYPV6u7lE7+wuSiGguqwXqQrA7mexuzei8PTaRNtcJ
q+h83yVeaTcqnt7oFuPRla0zWzH/UoOIMqxfV6ht2mXpwyE+IGwBvEEbiRCq8C4L
wy0hZCu8c76M+CWjcd+XQW9iGK3mIUm6h2hItQIDAQABAoIBAQCgORUQEVyYWmbF
3anjbK60x5LUJ9A/a6hjz+VvDOma4bwAbHDZaNGog6lEnzYdEX+yp8vADVjjX+Dq
m66GwaPipLG5/WBYGGCJYzHbL7n3WidkJtHirMonLXM/mLeUuv9Tgv6OKByco/SG
0jdDo3ckMHphfxqo4lKe+avQoSYpJKKRINefHUDTuVbybutAssAJODpfPdrZuoGy
W0ZYNKHUx8vA+yYPL+8LoVaw1C8sekeoVNAIUKAPOHXkqcy4E2qyMlgR0+VDHLHq
7bGnBt1CnnIGyE+5fFTDxzCNwJsHzBB9B6F9W6/eX7QWktVOkt8P+T0uCQukGFgh
s+jX2pCFAoGBAN3l+cTPduSoFxGKVjpE0kyjLIVnohMcDVC74ftCXu0NVVwk3PMV
CqqqBVqMVKUHAzOdnYrvL/YG3XFVV1jpZAZUcp2c3OFpFTlicNRt3UgddxVy7WuY
FsKhXQXh6RWjvptLL6/6ADx+ZrfzrvoiYMNTgJ1Gm852Zge7b1ygSahXAoGBAObt
qHQUWKHFk2+Vgyp54SPy/tc636JIGjPM24RhWM2MZjvOae7MNnFIXY3ibwbshmmu
7bT1UNvp7ex1D58ulhqHzcy8EpIQZdxffEI6JqQ1TK9Q3qc4Pbdg138ezzpW1XQp
jamBOohaVxzhHpwEaAaD5yC2BbDmCiU3WewpMB/TAoGAE/8vnQ7dNgn32jrPPn0J
PqLN1k/aiUJT6NylptD6YP58nMstpjJVPcAIr3pJ/n09Sp9/nQ+lENTZi+cW8gpG
W1Os6ItEVIP1x7AZXutvr5oIK0SqJLIWCwAjs+4B5VNWUARcjc1HzCvP8e/h6uTC
N5gE1SeRzu9YjoXTqVNAkA0CgYBn2+1OP7RZFYYowkKawPQL+ga5gCYCU5FNSM5V
rH6G+6UjMsOb/cZijpxc6sDqiUgukdkg8M/sCDrUhRWAjzA9QGTDtrZXcP6O7Xby
RjsI0Vvq4WEyLe474lcpOg8TeuhHdUTcPl2344GYYHsmyiiK/ZnesV6/38YiVNGh
kCivtwKBgQC0EKA/1BQ5dN30iz6GyBneCtJauJFnBsiNkn8ERpnfgMh1b1XlNRtj
mCJtFtCCoOFlEW09up2daZew9yI7dJVcFqlJgSNAoQGze+1WZXEA2QhHfJprSmGi
MWxGRw6f60FdvZss49OMsMDyRetDDL/dWzwXVQ4QfEAYpDBUUSSMFg==
-----END RSA PRIVATE KEY-----`
// ClientTest02Crt is the certificate for client-test02.
var ClientTest02Crt = `-----BEGIN CERTIFICATE-----
MIIEWjCCAkKgAwIBAgIRANEPhPoPTEoCoNdq5yZgyDcwDQYJKoZIhvcNAQELBQAw
KDEmMCQGA1UEAxMdVGVzdGluZyBjZXJ0aWZpY2F0ZSBhdXRob3JpdHkwIBcNMjAw
NzE0MTkxNDE4WhgPMjExOTA3MTQxOTExNDJaMBgxFjAUBgNVBAMTDWNsaWVudC10
ZXN0MDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCo4MTVF60qU2Mv
ccV2mP/3ILM40hzThDgRpJd+IjD1KBvNuWbRl9vJlRT3NuwmjjYgG4TEzYMxEwnp
mOHSCmtmGy4sQKPot7gjrgqXdVKt7/9/uqOl2hv9B92AYiK6Ob2ev3dsfwvGCq0I
+CpoaQqdIYwN5ZQVMXOMzeFlu74/jK/HFC1n2THaA1EWWI/FZywsbUA7g41ha2ls
7fOfKnNhh1ovQryoMJeZjiuWbZqzPgvDP4Dszyp7tuMYLQtQ6vvK3MkLzvzYgsN6
1fiGwwYiBu5FYgiQ44MPGaJ5UgR5Pn2ocGmbGdCVm5qfWFtgrVoNtjmquAR5+6Ai
ttB06Kw/AgMBAAGjgYwwgYkwDgYDVR0PAQH/BAQDAgO4MB0GA1UdJQQWMBQGCCsG
AQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUVvxTtaJNcnQbbkR3vVwHLsFQiqow
HwYDVR0jBBgwFoAU8inA9NnqIST5SBR6L3z9rbZd1BowGAYDVR0RBBEwD4INY2xp
ZW50LXRlc3QwMjANBgkqhkiG9w0BAQsFAAOCAgEAWXb+03oCqQP7lR4Ijl3k8Bj7
E4C6qbTjAgSUo3JKVCrSIvCpK/f295feyeUhb6Gd6fGhgEsz/HxOUD+p+QS5Z3tq
7Ydx3Wb/EJ3uu3AUZf35ClRsf/bMsanzvKvc94pkCfqbMSDa8s+F73wgZQzCqQ3j
5645BKM0f7W1Lq0O1htl8fpVb8g+vhVhwvBHuK6IIb1Mqh9gSuY+OGR5l0v7B2s7
Lzt2Yj0yDkXvfnrLsTxf3u/O02Xxk5pN34BgRLPP6Rv6Nht3KfIO/mRX1RetLRo5
wkCeMt86on8APWJxlfS7WmB12jXvzNjznlGzyA5Bg8coqq6imqXGa5F2JEclc4Xy
J1afWsJCrZ+e1TF65oEe2c61z6QFWMLPgftKUhEd1nve8xxTroFckx/DSJw155XL
ond2+dpD63znGQYATFRUk2dJfhNRZVcqLABsqHuNJlTHrZInU9FrfoMIQl7HCT7b
Y+cmqQd+Z6c/RhASv6Ej6PQYNfcj7QO4OwloazGBnWllBgmAmERdE0d+65ZYTIf+
jjWljvDx7qK/t4gwk23/9SQoPp66Yr60Jxm2vK1o70wxxKAe0G/skMO7oH8+1td/
L/7LyA4miSuym3OotnmL54xOAIZvwdr7ULlHaADt6N3QUpmjIfF5za7dzCek8iWv
+gv/m7jLA2aihJxgcOM=
-----END CERTIFICATE-----`
// ClientTest02Key is the key for client-test02.
var ClientTest02Key = `-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAqODE1RetKlNjL3HFdpj/9yCzONIc04Q4EaSXfiIw9Sgbzblm
0ZfbyZUU9zbsJo42IBuExM2DMRMJ6Zjh0gprZhsuLECj6Le4I64Kl3VSre//f7qj
pdob/QfdgGIiujm9nr93bH8LxgqtCPgqaGkKnSGMDeWUFTFzjM3hZbu+P4yvxxQt
Z9kx2gNRFliPxWcsLG1AO4ONYWtpbO3znypzYYdaL0K8qDCXmY4rlm2asz4Lwz+A
7M8qe7bjGC0LUOr7ytzJC8782ILDetX4hsMGIgbuRWIIkOODDxmieVIEeT59qHBp
mxnQlZuan1hbYK1aDbY5qrgEefugIrbQdOisPwIDAQABAoIBAGKzU3bzqoqFR//v
r6f8DgXCf9ziuGRK73YoSz41/4UZFv7qsBQpfBRZ5HIEEIsMLMghLTzUnCtvZCi5
6KmY22JG2nqUoPefgKihzKDuug7cqOhfDcweKKN/GE8zi/ZpTtDcOJEZw6jQjoci
e66gTcq+U5u/pQep6k3N+kE6NBvxS40+6nvWpqDNShGXf4Wf4H+ZFlueZn9ExQJ+
SzGpbuh7/kQSN9KiE0TZPwuRHxUG9S/jyGqpoUx3m9LPcymLE3sW1z9JQokhmyUM
nncSj/3A3bCdJ+Gk3vN78UmDp8hs+naKXqYpohFLrLzf1euojeTUUCTk3/ZUNLd3
wMtbhrECgYEA10evXE6d0xzT90WF0bgOBxxgVo7ArWngjOBNg2snF4OMvMiCusng
3ACYb3r3FP7XTnmtX0pzDhRiR2Dtdj+iKUQj3Edlqze4Jl1lapcP00oGHaL0aWHS
sSJ1dLiKOX+J3NipOb6SMVyRC2TCtfDOrVKjTh2IL/r12tjEQZ4bwncCgYEAyNIz
KqBYfLfnz50zzovbxGpXXioWCZnbegTIEuav24KVA2Dnxm6+X3jSa2y6Jha+KKcn
ck7xLlyXNTiFDteCoNOHDoFD29deThIqhVENaaj99v6uqa2pFKaLguKSpmVTYGfN
nzgc0TrH24EotKwUKNQOPeeim40M2SXaakyiznkCgYAA50EaHw5Ue3N8PyNvnNka
OIlC87hlQeN6U9qfaYyxcZDenezGgeBaq/n3xclRojwfDS2oD7Tp4zYCXKrCa0Pv
7mREIVyQ2lwAdTXeu6GKXm4mI6/o3Us4CQ/7HGcgFKPsdFBJeL4+TMgjBxo2Dzue
yJD82+zdXq03bN9t8w7kwwKBgQCff/QLoxck15xSFXWUUxjVw/BoZdzi+0SKgUm3
WWnLWseny0vLGyIxCfF2SQEAR4f5GeoGrBR60id2qdFknF6wBdF6/8g5z7CjKWKE
SH/yr7omdtmbAscME8syxWncpxW1uDxkfVjGBX2/JbKC7TmFxAcbu+I20aymu53i
V8PnYQKBgHJ6g/YmCVsTETxiL7jQlLhmiitI4DBtu7FJmh8L75eyZs7JyXrrsmu7
+IMc+2eF2yB0Po9TInzCyN/eLVANZEL0uqQjT1F8MoftJspe5GxRtTtT/iv02B/O
5DKMSYKqDJVSH4D+Rw9RJNYQvElXBXo2/jwnTxaEXUarNP8WDRb1
-----END RSA PRIVATE KEY-----`
// ClientTest03Crt is the certificate for client-test03.
var ClientTest03Crt = `-----BEGIN CERTIFICATE-----
MIIEWjCCAkKgAwIBAgIRAOEjdJ1nM7Zr50Ht9TA4s4EwDQYJKoZIhvcNAQELBQAw
KDEmMCQGA1UEAxMdVGVzdGluZyBjZXJ0aWZpY2F0ZSBhdXRob3JpdHkwIBcNMjAw
NzE0MTkxNDI2WhgPMjExOTA3MTQxOTExNDJaMBgxFjAUBgNVBAMTDWNsaWVudC10
ZXN0MDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgiezBVyx8iy0i
RCzmht//pvKRnzRMBCau0Bb5VLhYkzAMnQCKxu7k9+bi70rgV3HOOzFfYEJRFHqN
DKqodRQu8rmCMBSwyS/uALJk2ms/QcUVXD73Q6uD2m2rARPXa9AroNJ0ONnaOTRT
GHr6Eh+obiCj7m5yuHqaX7QBcM4AXqdN8H57xsH6zBs8xPKozI0QRadtMF0OFbwe
bHvf9CJ+dn0KsxnJlhP+Lj5b95LYCazOAiDZdWTVn7CAZr2L/5kW25VxPlrrVfEj
i1MxEvOkdq4tH36+VjUu/NqC71RkLiNP+cDnokkn4ygzD+hKcUKkpm68Aox0yrBA
c13KDmUpAgMBAAGjgYwwgYkwDgYDVR0PAQH/BAQDAgO4MB0GA1UdJQQWMBQGCCsG
AQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUWEUXCwHFixg2RMkafbFr4MtqqXgw
HwYDVR0jBBgwFoAU8inA9NnqIST5SBR6L3z9rbZd1BowGAYDVR0RBBEwD4INY2xp
ZW50LXRlc3QwMzANBgkqhkiG9w0BAQsFAAOCAgEABcbrz/GuHwXE5aGxwbRPYK4D
UoMgAxfKGdMeq/q/KFF4sFUdPL+9+OEw0mo7IJDKzSDyxAyMa+ZZ0/gRuMYVPDtJ
VUt2PVpf3njhwbXqrvZaZ7zqCa0Lcsie0MReS7PPW+rBYLE4kXEROl/VpxMVO3XD
TDlmjfcpsOmB3APHUSRoKvf6wBTngZqyUD4+MI/ICLJTZ48BMAZQnsdfWsCrv3pY
LLICO+ie+T+Q8SA5kj/IhQNwFPtmDtT5b0JMA9OCXZxgi+AjxJd/fC3j0kAYX5/W
IlR+I5OMns8y5Cn69BvkQsaR0QusS11FiSlYLpvu9ZNCaeCBl49GDlKJHkurFJbf
J9sj0Wri23i1rO4BX7iUmxHORj+YkxVIu5tWSRG5pvhrzUGsi9kZUnwuZBH95ctL
4RybnKldaEtEFVhpgcRITqxl0KLSDIQKYXM/E6BkBP9sxUijw8kdn+elDYvYKRbc
tegroRGgQlvv+tmfywnbl3wgqhJNofA6F1w3B5O/osu9kS1d1lTcZRUTBPfz445T
yaDE2hKJ3EAMU19pENsoQ03RUdXZdNcIgV9bfQXjVNQgR0M3BJsvtmD1Axc2iz8Y
muV8tNq6HtzTVQENwY9XjOQuMA0eIhjfScNtopgVqzKuH+OtmkMULK/MREce6G3D
ZDPJlY1l7uBTkvtcg/4=
-----END CERTIFICATE-----`
// ClientTest03Key is the key for client-test03.
var ClientTest03Key = `-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAoInswVcsfIstIkQs5obf/6bykZ80TAQmrtAW+VS4WJMwDJ0A
isbu5Pfm4u9K4FdxzjsxX2BCURR6jQyqqHUULvK5gjAUsMkv7gCyZNprP0HFFVw+
90Org9ptqwET12vQK6DSdDjZ2jk0Uxh6+hIfqG4go+5ucrh6ml+0AXDOAF6nTfB+
e8bB+swbPMTyqMyNEEWnbTBdDhW8Hmx73/QifnZ9CrMZyZYT/i4+W/eS2AmszgIg
2XVk1Z+wgGa9i/+ZFtuVcT5a61XxI4tTMRLzpHauLR9+vlY1Lvzagu9UZC4jT/nA
56JJJ+MoMw/oSnFCpKZuvAKMdMqwQHNdyg5lKQIDAQABAoIBAFFhWZkw3aZMzxZd
xP0fRhHMyY40TEh0mj9n0R2XatPL2UGrnQi8i4GagXpsn2JWMaS/sOmOXE/Jt84k
q6Y1o4OhG5T5VqO/eQKHa+dgKZmpd4S6fFjP/vQaGBnls+8yAhb7sXOlFhpfgTzW
XhDCezXgjb9MMMUK62uyNAe+7U6V3xsuHojwd16CV3xDC2q7gbSwsMZm2HChBYA2
NLxgE7C7WJWTvch7nvZYYprFs982P8MZWgbRkwhiw0EdO2baEQNTMpJwDhT7Gcl2
dKVM4zNLtTA4nw7V38TZDpTlGBYtFcHknogisPVxkUGiUK+kNgWRFyduFjDyQu2n
m58QxWECgYEAwEd1TK2WfRe1YuCN4A7nUcQByJorZqYvaXSCyZwhIPIN+MqRhtef
vDfMVDCgUqtUqlK8JXnz0arV+rYdgVHcgB7mDOTdrz8wxjlOl5GoYDMhCP52vDYa
1VRNQ1lELAOrdo8wPSKoxXtGA8p0LDFm38zB6UbLhQzsIDcooDmnzx0CgYEA1b2u
8s+Bl9L4d6xxdCxEOX5FtV/aNGEjYdWjMmwag8jcB+dT5bvfYlEPWR98riDisnxQ
EVk4qhGjUqoeW0fTmy9QxSYp9LMOSoUDRzDfl2bswELB2vap0uU0oHDbT57HeN7a
IAFRCwg/FKIoeEmkNeusI/3f1W8MMm16Uj+wFH0CgYACxQS7hgSU6LKEKhfhElXi
p6Ae85mMcPhd3H/Fx6nyf4oT+1b9Sj3SyDr5O3oTtsQRb/+lyovoiT1rzxO9uSAj
+E34AZPv4kkhkdG//SkfuZzQNFohe+YHDJ/QSIji2Wqu2oEnYEhuD8iCZXgm6s9A
igKBCbQExprgG+tJ44q3QQKBgQCn46TGCQSMUyTkK8m6LQMx/eOXgkENn7eBI6Ra
+Nsi5OUgOC6IZ7ghq/ZYVQlEZYRsGoVx+xktTUlypznNDXBDlzjkgwO1t+fj1PMs
OlGGxUv2APnwmovuoidiVwONWPTqFnJTbXVRKxsRhAYx5fZcfE/svX/SULXN7nyE
mo4eqQKBgQCIPXpp9KhH40dHfDnOdTi+xzUBTnJwxA2yETFhmFsrc245c19saZNK
XDCQeaEUOuLjokRojHrN27ghz3wJoUJzTdjtHZ+yE9s2cW9VXRUxkun0aLcQd/iY
xvXEII1qCvhI4mmWvbcepvtswQmTEeOroM/27/IIEAOvTyqd6rDi2A==
-----END RSA PRIVATE KEY-----`
// SetupCerts sets up a number of certificates on-disk in the provided location.
func SetupCerts(base string) error {
if err := ioutil.WriteFile(filepath.Join(base, "ca.crt"), []byte(CACrt), 0600); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(base, "signer-test01.crt"), []byte(SignerTest01Crt), 0600); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(base, "signer-test01.key"), []byte(SignerTest01Key), 0600); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(base, "signer-test02.crt"), []byte(SignerTest02Crt), 0600); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(base, "signer-test02.key"), []byte(SignerTest02Key), 0600); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(base, "signer-test03.crt"), []byte(SignerTest03Crt), 0600); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(base, "signer-test03.key"), []byte(SignerTest03Key), 0600); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(base, "signer-test04.crt"), []byte(SignerTest04Crt), 0600); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(base, "signer-test04.key"), []byte(SignerTest04Key), 0600); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(base, "signer-test05.crt"), []byte(SignerTest05Crt), 0600); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(base, "signer-test05.key"), []byte(SignerTest05Key), 0600); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(base, "client-test01.crt"), []byte(ClientTest01Crt), 0600); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(base, "client-test01.key"), []byte(ClientTest01Key), 0600); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(base, "client-test02.crt"), []byte(ClientTest02Crt), 0600); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(base, "client-test02.key"), []byte(ClientTest02Key), 0600); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(base, "client-test03.crt"), []byte(ClientTest03Crt), 0600); err != nil {
return err
}
if err := ioutil.WriteFile(filepath.Join(base, "client-test03.key"), []byte(ClientTest03Key), 0600); err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEWTCCAkGgAwIBAgIQEmQiGczWl8GehMItbxxtpTANBgkqhkiG9w0BAQsFADAo
MSYwJAYDVQQDEx1UZXN0aW5nIGNlcnRpZmljYXRlIGF1dGhvcml0eTAgFw0yMDA3
MTQxOTE0MTBaGA8yMTE5MDcxNDE5MTE0MlowGDEWMBQGA1UEAxMNY2xpZW50LXRl
c3QwMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMgqnlKXWgKe2/tl
OYQg+szYJKNCOnzq9h2LgDyGAg7weKToPFhqDDJeONV5Hs8Oe5J4hLw8nTy3QVc5
Ir4sqjdBE522X0ZKSVXkP6WXT2DknLfFqiYHPHfK1t8fjhGcIExfo3sU7x+tyZT+
tQwe3+wMd1/deEl/Y9imKvwJihTCtAORKlemyVzEdGLxlQkZ+OKIbmZ5WD1eru5R
O/sLkohoLqsF6kKwO5nsbs3ovD02kTbXCavofN8lXmk3Kp7e6Bbj0ZWtM1sx/1KD
iDKsX1eobdpl6cMhPiBsAbxBG4kQqvAuC8MtIWQrvHO+jPglo3Hfl0FvYhit5iFJ
uodoSLUCAwEAAaOBjDCBiTAOBgNVHQ8BAf8EBAMCA7gwHQYDVR0lBBYwFAYIKwYB
BQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBQjib0wXi+YdCOBflTX/Frp1tD/xjAf
BgNVHSMEGDAWgBTyKcD02eohJPlIFHovfP2ttl3UGjAYBgNVHREEETAPgg1jbGll
bnQtdGVzdDAxMA0GCSqGSIb3DQEBCwUAA4ICAQCKW9Da1WZ+TimbjhjKclm60OjT
yHX5pH3eZrG3iqkpSgoBMFKCtIEulHk38DTqEqKESFubU80A4H8lkQSWYxx/OV+3
OLYh3QgXv3R92pVqrnRD1Dspy+YtePrECART+RSCVoN2+4Oc+rqEMJtshQDGMlVJ
wN9mp1OiGiAU0EyNNUDmxoMaWs3+BGMSngbgTY2I3U76RFwWqXi2FK9gGiAfH/Vf
XQ+AKXtPq+pQdLPjGWZ0KfzmHUtaxoR3A3u6G4hi+eh7PY4N64g/3lO5FwzEK2ke
VSn6xq50PWk1OkULyWVobo9VsXiJaAltBV6Le6Eyk3dofFb8zp+mKedDEC/anhXw
tzO7OFltqOiyaJNOdAXgsskom71PTDM0aJEG/8Jl5eOwlEoKi4A7KRFt6rq09SHj
Ww8yjX6EbTUmT9plKYQmKCshJ65e1Y5rGElxTzfzeQjDAV+584xzF7heUcKbBn+o
Sndol4HdgMo+yLwbyPL/GdB2m+Itzfid/cFUd57X/9MuPrRvMHmHoas1e7/DtuqK
riQ2B5PmKjvDz+nrR7aIR3nMFSlA2UAM4sGU0hmAR9XQRf7unKW95tcKRLx/+Blt
b71wse/U4f4QKz+JUntuY/x+Q13/np/DUDz0koYRtwqe+J4nlZdSH9on1i8lTXcj
yWJYDKQTImOKFINmag==
-----END CERTIFICATE-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAyCqeUpdaAp7b+2U5hCD6zNgko0I6fOr2HYuAPIYCDvB4pOg8
WGoMMl441Xkezw57kniEvDydPLdBVzkiviyqN0ETnbZfRkpJVeQ/pZdPYOSct8Wq
Jgc8d8rW3x+OEZwgTF+jexTvH63JlP61DB7f7Ax3X914SX9j2KYq/AmKFMK0A5Eq
V6bJXMR0YvGVCRn44ohuZnlYPV6u7lE7+wuSiGguqwXqQrA7mexuzei8PTaRNtcJ
q+h83yVeaTcqnt7oFuPRla0zWzH/UoOIMqxfV6ht2mXpwyE+IGwBvEEbiRCq8C4L
wy0hZCu8c76M+CWjcd+XQW9iGK3mIUm6h2hItQIDAQABAoIBAQCgORUQEVyYWmbF
3anjbK60x5LUJ9A/a6hjz+VvDOma4bwAbHDZaNGog6lEnzYdEX+yp8vADVjjX+Dq
m66GwaPipLG5/WBYGGCJYzHbL7n3WidkJtHirMonLXM/mLeUuv9Tgv6OKByco/SG
0jdDo3ckMHphfxqo4lKe+avQoSYpJKKRINefHUDTuVbybutAssAJODpfPdrZuoGy
W0ZYNKHUx8vA+yYPL+8LoVaw1C8sekeoVNAIUKAPOHXkqcy4E2qyMlgR0+VDHLHq
7bGnBt1CnnIGyE+5fFTDxzCNwJsHzBB9B6F9W6/eX7QWktVOkt8P+T0uCQukGFgh
s+jX2pCFAoGBAN3l+cTPduSoFxGKVjpE0kyjLIVnohMcDVC74ftCXu0NVVwk3PMV
CqqqBVqMVKUHAzOdnYrvL/YG3XFVV1jpZAZUcp2c3OFpFTlicNRt3UgddxVy7WuY
FsKhXQXh6RWjvptLL6/6ADx+ZrfzrvoiYMNTgJ1Gm852Zge7b1ygSahXAoGBAObt
qHQUWKHFk2+Vgyp54SPy/tc636JIGjPM24RhWM2MZjvOae7MNnFIXY3ibwbshmmu
7bT1UNvp7ex1D58ulhqHzcy8EpIQZdxffEI6JqQ1TK9Q3qc4Pbdg138ezzpW1XQp
jamBOohaVxzhHpwEaAaD5yC2BbDmCiU3WewpMB/TAoGAE/8vnQ7dNgn32jrPPn0J
PqLN1k/aiUJT6NylptD6YP58nMstpjJVPcAIr3pJ/n09Sp9/nQ+lENTZi+cW8gpG
W1Os6ItEVIP1x7AZXutvr5oIK0SqJLIWCwAjs+4B5VNWUARcjc1HzCvP8e/h6uTC
N5gE1SeRzu9YjoXTqVNAkA0CgYBn2+1OP7RZFYYowkKawPQL+ga5gCYCU5FNSM5V
rH6G+6UjMsOb/cZijpxc6sDqiUgukdkg8M/sCDrUhRWAjzA9QGTDtrZXcP6O7Xby
RjsI0Vvq4WEyLe474lcpOg8TeuhHdUTcPl2344GYYHsmyiiK/ZnesV6/38YiVNGh
kCivtwKBgQC0EKA/1BQ5dN30iz6GyBneCtJauJFnBsiNkn8ERpnfgMh1b1XlNRtj
mCJtFtCCoOFlEW09up2daZew9yI7dJVcFqlJgSNAoQGze+1WZXEA2QhHfJprSmGi
MWxGRw6f60FdvZss49OMsMDyRetDDL/dWzwXVQ4QfEAYpDBUUSSMFg==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEWjCCAkKgAwIBAgIRANEPhPoPTEoCoNdq5yZgyDcwDQYJKoZIhvcNAQELBQAw
KDEmMCQGA1UEAxMdVGVzdGluZyBjZXJ0aWZpY2F0ZSBhdXRob3JpdHkwIBcNMjAw
NzE0MTkxNDE4WhgPMjExOTA3MTQxOTExNDJaMBgxFjAUBgNVBAMTDWNsaWVudC10
ZXN0MDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCo4MTVF60qU2Mv
ccV2mP/3ILM40hzThDgRpJd+IjD1KBvNuWbRl9vJlRT3NuwmjjYgG4TEzYMxEwnp
mOHSCmtmGy4sQKPot7gjrgqXdVKt7/9/uqOl2hv9B92AYiK6Ob2ev3dsfwvGCq0I
+CpoaQqdIYwN5ZQVMXOMzeFlu74/jK/HFC1n2THaA1EWWI/FZywsbUA7g41ha2ls
7fOfKnNhh1ovQryoMJeZjiuWbZqzPgvDP4Dszyp7tuMYLQtQ6vvK3MkLzvzYgsN6
1fiGwwYiBu5FYgiQ44MPGaJ5UgR5Pn2ocGmbGdCVm5qfWFtgrVoNtjmquAR5+6Ai
ttB06Kw/AgMBAAGjgYwwgYkwDgYDVR0PAQH/BAQDAgO4MB0GA1UdJQQWMBQGCCsG
AQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUVvxTtaJNcnQbbkR3vVwHLsFQiqow
HwYDVR0jBBgwFoAU8inA9NnqIST5SBR6L3z9rbZd1BowGAYDVR0RBBEwD4INY2xp
ZW50LXRlc3QwMjANBgkqhkiG9w0BAQsFAAOCAgEAWXb+03oCqQP7lR4Ijl3k8Bj7
E4C6qbTjAgSUo3JKVCrSIvCpK/f295feyeUhb6Gd6fGhgEsz/HxOUD+p+QS5Z3tq
7Ydx3Wb/EJ3uu3AUZf35ClRsf/bMsanzvKvc94pkCfqbMSDa8s+F73wgZQzCqQ3j
5645BKM0f7W1Lq0O1htl8fpVb8g+vhVhwvBHuK6IIb1Mqh9gSuY+OGR5l0v7B2s7
Lzt2Yj0yDkXvfnrLsTxf3u/O02Xxk5pN34BgRLPP6Rv6Nht3KfIO/mRX1RetLRo5
wkCeMt86on8APWJxlfS7WmB12jXvzNjznlGzyA5Bg8coqq6imqXGa5F2JEclc4Xy
J1afWsJCrZ+e1TF65oEe2c61z6QFWMLPgftKUhEd1nve8xxTroFckx/DSJw155XL
ond2+dpD63znGQYATFRUk2dJfhNRZVcqLABsqHuNJlTHrZInU9FrfoMIQl7HCT7b
Y+cmqQd+Z6c/RhASv6Ej6PQYNfcj7QO4OwloazGBnWllBgmAmERdE0d+65ZYTIf+
jjWljvDx7qK/t4gwk23/9SQoPp66Yr60Jxm2vK1o70wxxKAe0G/skMO7oH8+1td/
L/7LyA4miSuym3OotnmL54xOAIZvwdr7ULlHaADt6N3QUpmjIfF5za7dzCek8iWv
+gv/m7jLA2aihJxgcOM=
-----END CERTIFICATE-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAqODE1RetKlNjL3HFdpj/9yCzONIc04Q4EaSXfiIw9Sgbzblm
0ZfbyZUU9zbsJo42IBuExM2DMRMJ6Zjh0gprZhsuLECj6Le4I64Kl3VSre//f7qj
pdob/QfdgGIiujm9nr93bH8LxgqtCPgqaGkKnSGMDeWUFTFzjM3hZbu+P4yvxxQt
Z9kx2gNRFliPxWcsLG1AO4ONYWtpbO3znypzYYdaL0K8qDCXmY4rlm2asz4Lwz+A
7M8qe7bjGC0LUOr7ytzJC8782ILDetX4hsMGIgbuRWIIkOODDxmieVIEeT59qHBp
mxnQlZuan1hbYK1aDbY5qrgEefugIrbQdOisPwIDAQABAoIBAGKzU3bzqoqFR//v
r6f8DgXCf9ziuGRK73YoSz41/4UZFv7qsBQpfBRZ5HIEEIsMLMghLTzUnCtvZCi5
6KmY22JG2nqUoPefgKihzKDuug7cqOhfDcweKKN/GE8zi/ZpTtDcOJEZw6jQjoci
e66gTcq+U5u/pQep6k3N+kE6NBvxS40+6nvWpqDNShGXf4Wf4H+ZFlueZn9ExQJ+
SzGpbuh7/kQSN9KiE0TZPwuRHxUG9S/jyGqpoUx3m9LPcymLE3sW1z9JQokhmyUM
nncSj/3A3bCdJ+Gk3vN78UmDp8hs+naKXqYpohFLrLzf1euojeTUUCTk3/ZUNLd3
wMtbhrECgYEA10evXE6d0xzT90WF0bgOBxxgVo7ArWngjOBNg2snF4OMvMiCusng
3ACYb3r3FP7XTnmtX0pzDhRiR2Dtdj+iKUQj3Edlqze4Jl1lapcP00oGHaL0aWHS
sSJ1dLiKOX+J3NipOb6SMVyRC2TCtfDOrVKjTh2IL/r12tjEQZ4bwncCgYEAyNIz
KqBYfLfnz50zzovbxGpXXioWCZnbegTIEuav24KVA2Dnxm6+X3jSa2y6Jha+KKcn
ck7xLlyXNTiFDteCoNOHDoFD29deThIqhVENaaj99v6uqa2pFKaLguKSpmVTYGfN
nzgc0TrH24EotKwUKNQOPeeim40M2SXaakyiznkCgYAA50EaHw5Ue3N8PyNvnNka
OIlC87hlQeN6U9qfaYyxcZDenezGgeBaq/n3xclRojwfDS2oD7Tp4zYCXKrCa0Pv
7mREIVyQ2lwAdTXeu6GKXm4mI6/o3Us4CQ/7HGcgFKPsdFBJeL4+TMgjBxo2Dzue
yJD82+zdXq03bN9t8w7kwwKBgQCff/QLoxck15xSFXWUUxjVw/BoZdzi+0SKgUm3
WWnLWseny0vLGyIxCfF2SQEAR4f5GeoGrBR60id2qdFknF6wBdF6/8g5z7CjKWKE
SH/yr7omdtmbAscME8syxWncpxW1uDxkfVjGBX2/JbKC7TmFxAcbu+I20aymu53i
V8PnYQKBgHJ6g/YmCVsTETxiL7jQlLhmiitI4DBtu7FJmh8L75eyZs7JyXrrsmu7
+IMc+2eF2yB0Po9TInzCyN/eLVANZEL0uqQjT1F8MoftJspe5GxRtTtT/iv02B/O
5DKMSYKqDJVSH4D+Rw9RJNYQvElXBXo2/jwnTxaEXUarNP8WDRb1
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEWjCCAkKgAwIBAgIRAOEjdJ1nM7Zr50Ht9TA4s4EwDQYJKoZIhvcNAQELBQAw
KDEmMCQGA1UEAxMdVGVzdGluZyBjZXJ0aWZpY2F0ZSBhdXRob3JpdHkwIBcNMjAw
NzE0MTkxNDI2WhgPMjExOTA3MTQxOTExNDJaMBgxFjAUBgNVBAMTDWNsaWVudC10
ZXN0MDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgiezBVyx8iy0i
RCzmht//pvKRnzRMBCau0Bb5VLhYkzAMnQCKxu7k9+bi70rgV3HOOzFfYEJRFHqN
DKqodRQu8rmCMBSwyS/uALJk2ms/QcUVXD73Q6uD2m2rARPXa9AroNJ0ONnaOTRT
GHr6Eh+obiCj7m5yuHqaX7QBcM4AXqdN8H57xsH6zBs8xPKozI0QRadtMF0OFbwe
bHvf9CJ+dn0KsxnJlhP+Lj5b95LYCazOAiDZdWTVn7CAZr2L/5kW25VxPlrrVfEj
i1MxEvOkdq4tH36+VjUu/NqC71RkLiNP+cDnokkn4ygzD+hKcUKkpm68Aox0yrBA
c13KDmUpAgMBAAGjgYwwgYkwDgYDVR0PAQH/BAQDAgO4MB0GA1UdJQQWMBQGCCsG
AQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUWEUXCwHFixg2RMkafbFr4MtqqXgw
HwYDVR0jBBgwFoAU8inA9NnqIST5SBR6L3z9rbZd1BowGAYDVR0RBBEwD4INY2xp
ZW50LXRlc3QwMzANBgkqhkiG9w0BAQsFAAOCAgEABcbrz/GuHwXE5aGxwbRPYK4D
UoMgAxfKGdMeq/q/KFF4sFUdPL+9+OEw0mo7IJDKzSDyxAyMa+ZZ0/gRuMYVPDtJ
VUt2PVpf3njhwbXqrvZaZ7zqCa0Lcsie0MReS7PPW+rBYLE4kXEROl/VpxMVO3XD
TDlmjfcpsOmB3APHUSRoKvf6wBTngZqyUD4+MI/ICLJTZ48BMAZQnsdfWsCrv3pY
LLICO+ie+T+Q8SA5kj/IhQNwFPtmDtT5b0JMA9OCXZxgi+AjxJd/fC3j0kAYX5/W
IlR+I5OMns8y5Cn69BvkQsaR0QusS11FiSlYLpvu9ZNCaeCBl49GDlKJHkurFJbf
J9sj0Wri23i1rO4BX7iUmxHORj+YkxVIu5tWSRG5pvhrzUGsi9kZUnwuZBH95ctL
4RybnKldaEtEFVhpgcRITqxl0KLSDIQKYXM/E6BkBP9sxUijw8kdn+elDYvYKRbc
tegroRGgQlvv+tmfywnbl3wgqhJNofA6F1w3B5O/osu9kS1d1lTcZRUTBPfz445T
yaDE2hKJ3EAMU19pENsoQ03RUdXZdNcIgV9bfQXjVNQgR0M3BJsvtmD1Axc2iz8Y
muV8tNq6HtzTVQENwY9XjOQuMA0eIhjfScNtopgVqzKuH+OtmkMULK/MREce6G3D
ZDPJlY1l7uBTkvtcg/4=
-----END CERTIFICATE-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAoInswVcsfIstIkQs5obf/6bykZ80TAQmrtAW+VS4WJMwDJ0A
isbu5Pfm4u9K4FdxzjsxX2BCURR6jQyqqHUULvK5gjAUsMkv7gCyZNprP0HFFVw+
90Org9ptqwET12vQK6DSdDjZ2jk0Uxh6+hIfqG4go+5ucrh6ml+0AXDOAF6nTfB+
e8bB+swbPMTyqMyNEEWnbTBdDhW8Hmx73/QifnZ9CrMZyZYT/i4+W/eS2AmszgIg
2XVk1Z+wgGa9i/+ZFtuVcT5a61XxI4tTMRLzpHauLR9+vlY1Lvzagu9UZC4jT/nA
56JJJ+MoMw/oSnFCpKZuvAKMdMqwQHNdyg5lKQIDAQABAoIBAFFhWZkw3aZMzxZd
xP0fRhHMyY40TEh0mj9n0R2XatPL2UGrnQi8i4GagXpsn2JWMaS/sOmOXE/Jt84k
q6Y1o4OhG5T5VqO/eQKHa+dgKZmpd4S6fFjP/vQaGBnls+8yAhb7sXOlFhpfgTzW
XhDCezXgjb9MMMUK62uyNAe+7U6V3xsuHojwd16CV3xDC2q7gbSwsMZm2HChBYA2
NLxgE7C7WJWTvch7nvZYYprFs982P8MZWgbRkwhiw0EdO2baEQNTMpJwDhT7Gcl2
dKVM4zNLtTA4nw7V38TZDpTlGBYtFcHknogisPVxkUGiUK+kNgWRFyduFjDyQu2n
m58QxWECgYEAwEd1TK2WfRe1YuCN4A7nUcQByJorZqYvaXSCyZwhIPIN+MqRhtef
vDfMVDCgUqtUqlK8JXnz0arV+rYdgVHcgB7mDOTdrz8wxjlOl5GoYDMhCP52vDYa
1VRNQ1lELAOrdo8wPSKoxXtGA8p0LDFm38zB6UbLhQzsIDcooDmnzx0CgYEA1b2u
8s+Bl9L4d6xxdCxEOX5FtV/aNGEjYdWjMmwag8jcB+dT5bvfYlEPWR98riDisnxQ
EVk4qhGjUqoeW0fTmy9QxSYp9LMOSoUDRzDfl2bswELB2vap0uU0oHDbT57HeN7a
IAFRCwg/FKIoeEmkNeusI/3f1W8MMm16Uj+wFH0CgYACxQS7hgSU6LKEKhfhElXi
p6Ae85mMcPhd3H/Fx6nyf4oT+1b9Sj3SyDr5O3oTtsQRb/+lyovoiT1rzxO9uSAj
+E34AZPv4kkhkdG//SkfuZzQNFohe+YHDJ/QSIji2Wqu2oEnYEhuD8iCZXgm6s9A
igKBCbQExprgG+tJ44q3QQKBgQCn46TGCQSMUyTkK8m6LQMx/eOXgkENn7eBI6Ra
+Nsi5OUgOC6IZ7ghq/ZYVQlEZYRsGoVx+xktTUlypznNDXBDlzjkgwO1t+fj1PMs
OlGGxUv2APnwmovuoidiVwONWPTqFnJTbXVRKxsRhAYx5fZcfE/svX/SULXN7nyE
mo4eqQKBgQCIPXpp9KhH40dHfDnOdTi+xzUBTnJwxA2yETFhmFsrc245c19saZNK
XDCQeaEUOuLjokRojHrN27ghz3wJoUJzTdjtHZ+yE9s2cW9VXRUxkun0aLcQd/iY
xvXEII1qCvhI4mmWvbcepvtswQmTEeOroM/27/IIEAOvTyqd6rDi2A==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEWTCCAkGgAwIBAgIQOmQoybWcXv5kykIKSdE5YjANBgkqhkiG9w0BAQsFADAo
MSYwJAYDVQQDEx1UZXN0aW5nIGNlcnRpZmljYXRlIGF1dGhvcml0eTAgFw0yMDA3
MTQxOTEyNTZaGA8yMTE5MDcxNDE5MTE0MlowGDEWMBQGA1UEAxMNc2lnbmVyLXRl
c3QwMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKyN0GHe1PLPUvrO
jki9BJvx8QaiEyzTtmDv9N0AjsXOfgNlw8qdJ9uWDGEE4YduNIJg1pNqQuKaUedJ
sH4ddnGflVutEFGbC3awXFbOw3FYxNp6pli7E41sDJ1qihxb3E4xInEYDZpkBZkF
AxiujCN2wue7SNuaAc6J8EmUvvONArL1pAiJ7XeSYmx1HsNpkVobq7DMgnNcTr3I
D599RKX6PMpxtyAr+qgPwxXTIOno4AINIcAc3nywubi71SE8112c/fGHNU4Shx1y
hTKnbeE+Rmn5jsOLoknzqDrAkyuT9XNw6r9Nld311furo7MyTK9NX8nRXshI24dP
p9qk4gkCAwEAAaOBjDCBiTAOBgNVHQ8BAf8EBAMCA7gwHQYDVR0lBBYwFAYIKwYB
BQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBRq9vcOi24CL2wXKhfSo1fnuIHt6jAf
BgNVHSMEGDAWgBTyKcD02eohJPlIFHovfP2ttl3UGjAYBgNVHREEETAPgg1zaWdu
ZXItdGVzdDAxMA0GCSqGSIb3DQEBCwUAA4ICAQAV339n2B1/7zF3sRr6ZtTKX8b3
sdZD2uFzla4C/kvPQQertvlO1rTr3EfzEkvvA0X+knMqJ1glVSyVxzz/XFPif8IE
ddfPcHnnj/fObe/SysDv/R1AMlewwXwjPHggpCnNwXvxyE2ryLdSCFbsoSkZocqk
o6J0AxjlnMXXvqHVPEFYbLzMjguhRULpOy8PUX326jcxlBLjVejhwUfv7sS1pwEc
+tVH5IFHSGwGJSCfrnWh2mSkT9sxcGRXTJ2MFXH4iMs6wG9Gx6GoVtBuroXYgzcr
BLDe/5oUd+xNP47sJgYSnaTpGv2/WZnCCGangAjP+0jU6lN5CS861lIADZRmAZVB
1ZVlr0QPQ+Nmod+BM8qdw+kBSz/nCzEfTHrd4n3hBE/cFT4R9NrdekGCg6/GQIYb
sg5mdZkU+gwdpf7nUxyP6bJV6zqPZ1/ZwyRFcRqnXaLST45n2HCb1V754FUgg9jO
FQj4dtUjud7zs2J2KfDAPjXE7CWOpFlUjtDMjnaCyGh5IcRbgWSTm6KEQj38IU6R
wu/ezoj80BkYEP5Q6YOT1pDHUsNQwJW/cSV0ELGkfxovrN9VLRGJR+8uJ6j0wWMk
5cPmnLsvAuLPBO3iY+/w1ZKU40nebTwZL+2MyOAEidbLwqAtOhlsj9f8r0o4XBU0
QQ9lLQoXywGU8bfdgw==
-----END CERTIFICATE-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEArI3QYd7U8s9S+s6OSL0Em/HxBqITLNO2YO/03QCOxc5+A2XD
yp0n25YMYQThh240gmDWk2pC4ppR50mwfh12cZ+VW60QUZsLdrBcVs7DcVjE2nqm
WLsTjWwMnWqKHFvcTjEicRgNmmQFmQUDGK6MI3bC57tI25oBzonwSZS+840CsvWk
CIntd5JibHUew2mRWhursMyCc1xOvcgPn31Epfo8ynG3ICv6qA/DFdMg6ejgAg0h
wBzefLC5uLvVITzXXZz98Yc1ThKHHXKFMqdt4T5GafmOw4uiSfOoOsCTK5P1c3Dq
v02V3fXV+6ujszJMr01fydFeyEjbh0+n2qTiCQIDAQABAoIBACcRPJrMDr6ivhDW
71P8p6x/DKkJzPmbPXGZIoFe/PRAGju+sKORDVMkF81ng4BcLTtPnYVmy5nugpix
EGqdVRHIpdJJzqYLSn8m0uE8kvd4t6kXl84DHRwp2HlTg82D5s81RK0CWyIXf0Tz
442VB1mIK/y3ZHmD1uDiTir6qHkPltYh1ZZyY5rd06321Nyi32CMAC3Sah6Jk9xI
czhmMADiHjFoysJDX4Q5FBZqgThYhDNaFNATOiAb8vOD31NjpWBJJXab6Mm2GugF
YLqVudND0vUXLHpwZMlt9sX31j7AOo1tricHsFZjGDd4S2a/8ugMRwAdV2gogjUv
Kdj1TzkCgYEA1+NSGMqQpjTFXaHuRv6NRkzyd6MDl4KDfdAeIZCS+6X6DFzkZUgA
Ir70+m36Xvh3NoPX+HPUkQQP/5ZmdkRLz9DGSJmec+y6EdW6mzXSPCYXyBNqC4CR
Sj6zv08O31FfI4jMWhVXTQfU3dDRJtwii7zZYwo7hAPgEUVC7qo54PcCgYEAzJ1R
SVSt2OxxMFdfE+M6+jbAXJEjkOXywf1b0SCpVoIEajL6dZMNsF+oLxzYqQy1UaSb
pCvPxQvCl/uAAWYntVLTOkPEvdUqsUit/3N04YWjOpZKeUL2fhtrhZ0UNqeLGNUS
k9OCj/O10V93XxPw+vOj7rtwUf58AOu5/qXJlP8CgYEAkd1NguKaiTHuiCz4yY8D
9RPYX20M6DmOjlsngJYmOVETeXbp+mSDcvaCnxHfsHtAUN0T9xKL9M9B3/bGk/Hh
JzBwSG1C2iCAN7yosGXU/j7eopg7djoP8JIc8I2CBvD7zw6Gw/bXXXyFHroQFql1
zeRzHK+1NqVHp2OcrZTmNlECgYBfn9XxU2W7zyRG105T2QojDZtwp1Pbz9tX1bQn
VABPsYumphRvBj6Lgujyu6R1vL6wXSFv5BnBmPFkXeFAxiEgmIim3i0AGrNNDw5i
J+8jxnS2WK6NZUIVRXNGilZ8BGj5PfrkoyCNbfQ22UrMYGFqppqiY27mouwI8iGG
ZKyEuQKBgQCvmHrSdXM+YvtYeCATDT7r5G0CsUPuxsAXrkdRocoE5Nxkkub3hNmK
K3sG1MRrPsTtBgvdnBnvP4m2KiSCXfrsDNfWXGcxPfsLbJhjtmdmQ3roKdiEab3O
/usXIC7wM2aweTKmN9A1nBcWugIVop7yS3JzQm1uNWfzPWTWuL4RMA==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEWjCCAkKgAwIBAgIRAJ+RF/lFEwUcn+ENsCNJPQAwDQYJKoZIhvcNAQELBQAw
KDEmMCQGA1UEAxMdVGVzdGluZyBjZXJ0aWZpY2F0ZSBhdXRob3JpdHkwIBcNMjAw
NzE0MTkxMzA3WhgPMjExOTA3MTQxOTExNDJaMBgxFjAUBgNVBAMTDXNpZ25lci10
ZXN0MDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCnqL2UQZ0JSMyW
BbckBIGUN+jXLCi0zalhK8X8fZPRgLubgfkhqJInawNy5yCD6qVELaopJ0YViwJF
CtXKRzMuyMkH6w4Z94PoPTMMnAykfXuLzmUco3ijnhowzkRmD7hgj1JRCscKurkT
FxZeYyo6vQsfFJjuGx6DS70Z6UsEHcf7XVAn9u+5f26sGyeTvHqlPGAAdfCMKVRC
KVXbTwyrqjn/wFBy7K7BjxjbOBPjlnmDMbS8JBRlKw3xOKRQ9BoHtHBHnmo2rZHs
mrFlRYHZQbgxiRpcPGgVufWBKS8LFdNtTuafBpmlXCjcX5ijg2avjfFx0wZ2AB/d
OX/C3sSBAgMBAAGjgYwwgYkwDgYDVR0PAQH/BAQDAgO4MB0GA1UdJQQWMBQGCCsG
AQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUMXrb/F4hPpq7mEm7nGFaDxVfioww
HwYDVR0jBBgwFoAU8inA9NnqIST5SBR6L3z9rbZd1BowGAYDVR0RBBEwD4INc2ln
bmVyLXRlc3QwMjANBgkqhkiG9w0BAQsFAAOCAgEAC6DkcHVHegfZ42+FU7fLw81z
Jm/ngs4SbH6db249Q9lt00R70m3OU+vpAp3P/tIc/H6Jn7up1LItJvWlwUiqCyxn
YQj13r/lOWR9aqjS5jM4XvcjaiC1vfQdfghT/yHQT3HRsWSCsv+nDch4d80e20e+
ukPqLuDTTn7+nIWip2cHPIgaYOE6ZP9G3f3PORx8UwnTQvHiqV0tmBg61bD4xJmb
FIUFFmvG7LVmomu9GPdciXd9aOiBYmk+vHNXy5ekgDUR7xVM2Lt0uAoqegTZOWVh
UlAE1AAqL2YJcmej+g30by/ZvS/6GISYTGr+OhYSv+JAOY2ITBSrLD4c3CNzcq1d
SK6+hcVHRd9fv7Da3vpVVrNf4RcJGlzLFVfxCsrHeRrVfojjWW7voV8KpIqrBdX+
n1eWn1yiIonhZXvGo/UenPQ9QLjh8/l9ALn4DoefxdHnFtgFeyq5btAGKn5hEzOF
0Dbgob0B6s3JPQxk4DQiPwGFGGHLQGM9z3cbf7iOzf+3R2roTx+3s8WEljteYLOJ
F35AG+it80P21FzlMuLpnI3zbFomlx1U7Acf2lSpYshdRrcVpIfet3M8ZaraSDNO
mdY+QOjjjLpHwI64KqeJuCPbzdUrZW2Vth5DkDUwyX+Cld4G2HI3362NeI4gzWzG
tnOTVaeHiYpxrArnLno=
-----END CERTIFICATE-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAp6i9lEGdCUjMlgW3JASBlDfo1ywotM2pYSvF/H2T0YC7m4H5
IaiSJ2sDcucgg+qlRC2qKSdGFYsCRQrVykczLsjJB+sOGfeD6D0zDJwMpH17i85l
HKN4o54aMM5EZg+4YI9SUQrHCrq5ExcWXmMqOr0LHxSY7hseg0u9GelLBB3H+11Q
J/bvuX9urBsnk7x6pTxgAHXwjClUQilV208Mq6o5/8BQcuyuwY8Y2zgT45Z5gzG0
vCQUZSsN8TikUPQaB7RwR55qNq2R7JqxZUWB2UG4MYkaXDxoFbn1gSkvCxXTbU7m
nwaZpVwo3F+Yo4Nmr43xcdMGdgAf3Tl/wt7EgQIDAQABAoIBAE0yhRgenhAIVSs+
tnT/HisBE1UAID4f9D2pyh/YMpfkjn2r+upkk+dSfuQJSA91m2MpI5CPZNXGi+T+
eDILVqXUDbx3nqaWMUZd54OG1stme9yDzErDemjcA3M1hoj39A2B8IUgUUW/dDg2
CTassmUZZmWJNmFsW0BZP1kO8luSHAnGqXoi62JdLGdcmrRIoeCdIhkCTlV/ciQr
WotnsaEF5Kz9ta0nnxB/Rr5DSR4W8x22ALo0bxKVWHDpKF/0t9ElBtzQat13p5NV
OIp/V32DUI2AGBem82lDxYCS0aAotxEljyB5TqmJQSJfXQUxRc0/dXK4Kdecl/gH
6dRcfYECgYEAyfRo6eo4WxcLpiKj6vMbGHcEneCaiwjxJD9KAKntXxeJ5NSDxTfK
7Apio0wRyCSo3mt7vNyVNhxOz2uO9mo5CqgSY5fNHlZu971fNEXp0vg6GMNS768x
/K94cbv5u1nOnIXa5SEixWr0Lh2ZsG1vavTLxHcMamv+7N437Ak7V7sCgYEA1IbL
yVKK9CYLaXuLTvHF2DF74BH5d8VXnRz0hMd82cFDTfNK6MwfNrOomN8mO7eZCAzG
RRsaU8X47UxeRDh4E2VcWToSYo/d6i0Wd7IF4WZeGol9PtXFGYxWSv7NkR9F7nj9
6Y0FXQblCdlfkQeI5TWxDMqcBGw5QxwODJAMmvMCgYEAqulMDIIq1XQIaL4yKPk6
ehbnclENmRKlOT7SewNUHsDF80Gijror4lzbo0USW2Yi/7DI1El9gYCtdb6aC5JT
2d/pSB3E+qK9YK4ELzHns6JdUG2k97E1xZoefWpO664SO8bQPE8xpQ9hvNFSKsxC
maq38/moKTxiTsW1X+1kKlcCgYEAqs6remKcyxzIjz57+DbYi6k5phzMIza3884R
t6Wc8mYhccTXr8JeU9iQ6Exwrg4hMBcUQvZFco7qQc3e9XVtDCmqzwudOxnlgRA7
vneVwlJDz5Aw2Q92GdJwiFXBYaGA0ujrKYnthZbE/eV2qVkk7RL5+Q3d1rAkVYt2
vyIG/4ECgYEAvMFs1kpWmIGuW1LI+gbXil+LLpR6l/4Lr9dbcW2oSTF88TW7Ijs6
kIoeB/eLMWt8jDnyp9G/UoB9jfFgtvZ+gGyPizZQWy02sY0laQnmq9RXA8dkIPtL
8zLX+YwCSclX5slV0OWwqTlzp757AYHx1rLFgaFt3rVwY6lveVITjH0=
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEWjCCAkKgAwIBAgIRAJu28fjs8COygbgpPnST4icwDQYJKoZIhvcNAQELBQAw
KDEmMCQGA1UEAxMdVGVzdGluZyBjZXJ0aWZpY2F0ZSBhdXRob3JpdHkwIBcNMjAw
NzE0MTkxMzM0WhgPMjExOTA3MTQxOTExNDJaMBgxFjAUBgNVBAMTDXNpZ25lci10
ZXN0MDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGg2WKF/2VcMBs
YMpgTAiouP9eoXDkvVQd97GUyMfTH8Oz1k+yNZ/WUU/k5z33HTkAyJkLxreDgOri
k+wuZeLToEbB414N3m7JL6ixbo5jt0A134v8zNetGasBz8a3l+JqY9reQPyyTrMi
va5zcGkDJTTVaerVrdclfPq7AF4NnsFP1qNFZoU9pqFoZN76Oz0lUQdv+qy/VxCz
r4QuF/1TNvTU/k/3yPM9uIOfoCMaCdexRCoa3BcLF0QiC3KOTOAUkSdWVz0pYZW7
aoaAo7a+PWYbpm/FAUGPXWbEWWHdtWkoeUyygjMrjqrLQsdbqOl4QALOKJxrS8sR
ueHYlCv1AgMBAAGjgYwwgYkwDgYDVR0PAQH/BAQDAgO4MB0GA1UdJQQWMBQGCCsG
AQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUJCvuUovWLCLq6IMuJcgeoFFT734w
HwYDVR0jBBgwFoAU8inA9NnqIST5SBR6L3z9rbZd1BowGAYDVR0RBBEwD4INc2ln
bmVyLXRlc3QwMzANBgkqhkiG9w0BAQsFAAOCAgEAGkQb15A9nctJ+aq+tc9wtkgZ
Quku/o/boQ04hWrVaMj4kKw0cVXRApa5LdHr0YHIcOddvCXq73N38scIgmMlXS5O
kaLnwM2J42zlze1BtPxJyqynfz5ifqrRcuH89CKznENbUdWmCwsh2jU9Jxme7yIp
2J0uU472PyLdQcDPD0ah89tIcQ51fPaChY8RGlndAzjkOPUHm9UWjE13Y49ca16h
xFHGpxHLWmjvOKn5k3Y3q2hgXR67DP9sXYEA1iRPZzhWztJXzWePRzPjYfaC9orm
y8YzQa1MgnuGbrAsJ5xyEWsn5Px7ZdiEPNmNvxBeWtmJGL0w4EeZ9UR5P55dVdnz
PAkju3MUqqb2uY/tKzD5Ps5UUuZT8Q/aZUt6kQjeu8Li3bvIQJsdPZ/AghTwQZek
IL5whpCMLJIpK5PKHzXUK3fCHWKLvEZRLhjS8FOtLdqUM5lGkdkhmw+xIxgfRSu/
oPGrJzTEWohoRKUcmTRNmwq53OJxSqS82tnXJFNG7HMhzp9qwEQ+IfJMZBNSEA9y
EdgVypD4J+EsKHM4vS150qV0Ipm0TbXPQNMcttm1MaBUWoiOl2ZWhhnLH3eIMTVP
AtjX7nZ2WsXL62pOOPRzmq4mDRklrZOGJLALlAbh2GV6Vlgl0INLhGKMCg4zR9zC
1PBzRN/jGLFUtPWDcfo=
-----END CERTIFICATE-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAxoNlihf9lXDAbGDKYEwIqLj/XqFw5L1UHfexlMjH0x/Ds9ZP
sjWf1lFP5Oc99x05AMiZC8a3g4Dq4pPsLmXi06BGweNeDd5uyS+osW6OY7dANd+L
/MzXrRmrAc/Gt5fiamPa3kD8sk6zIr2uc3BpAyU01Wnq1a3XJXz6uwBeDZ7BT9aj
RWaFPaahaGTe+js9JVEHb/qsv1cQs6+ELhf9Uzb01P5P98jzPbiDn6AjGgnXsUQq
GtwXCxdEIgtyjkzgFJEnVlc9KWGVu2qGgKO2vj1mG6ZvxQFBj11mxFlh3bVpKHlM
soIzK46qy0LHW6jpeEACziica0vLEbnh2JQr9QIDAQABAoIBAHD7j+sMxHMtfRcx
73znSXZd9FozoEFP0HRN6XA45iIvTf8o1qsjAhnEpaguRIJEy5C6mwCs1P2vff//
GMk/i93OtvbbJUjXdE5lJan2tmvifFUtKktzer02grHBQ+RyOZc7xfIBItGJIUOA
ma1yKRJ1NqDQa6u6CV14yGtuRhmRYyiO+k43n9ig5GNtnhMN1Oi3jii6BoKxBZGE
ooFm3iQx3yqRLWo6nvvumjIGerdvhtACKI0SqlXacbzeJxa4WlLnlj3ccN8mK+kO
bQYR/HeGCn5m+0of39cBFooZjO1iC+jiy1bI10QpJ3Re0dEn2lKf4Smet2ZWgLoS
/nAHlPECgYEAyGNTjCDYOJk8ZzqRGfwdzwmDOxTeujD1kKBufusDmPjZc5YSWY85
iFUr7NihZZyfo4S6AsQlbwswG+vY74eHe33sK9FCepkymHTCgiE1SY1GlhZBV3lB
9hERuSz2VA72x6AuoIN0NaQJ4MyzDqY+jm4NQ+XUKO75B393RXjc+psCgYEA/Zrh
IAB/KJg4gLQrOYa/5dBjGIlIs4TbnB1lgWsYyaJDySR0YITIIJpTD2bgkG0eqjm1
4fFOo/znvISapEQh7hslusaJzRum2yExvCPrfECtcbBx52T0dUHWalY9ejMew0eQ
83Dw2TrBytzHTIsuX8y3NVRw4rDa/hjrY41+VK8CgYAaPl/nvzlyGCeAAXyVYZ5p
yf4k07PjwJu4iDpQZuj+tMCN0b6vegF36GerSifBDgUePji6OgQJCfcQARBVNnO4
6aHvjyVctwmYS9pZfo3jBxySdXGzSg8occ3XaZsNITSSqljQ7sZebBBbH5PnvD//
GUylcskZX0q//6KYN58BNwKBgAiNSn4rxh32VCFy8eo0sw/q4QyYxIzZNBalnyCo
HePexu5nfk0q7Ry8V4SzcWstYtVWsN13p7E7/AyNZDGZ4pMG81TDES6Leir1iZnQ
lEZSYAbvbkfhTaUOnU5krhoK00S+ixLKgjSxGIvgug/Iub2dR6hSuqPKVvgumvF2
egYdAoGAFH2UHTH4pa0U0PXG0GMZG40gMpBLN4jJTruynf/viwdvoKkpUWdjbjl8
GNwlttIq9YzYfrUTLn1sYhROrEUIUFmxc2ttFGPjMUifzosVDUbzMRbwhOpSgzof
K6dgyN0czk0YccR6L6TCQ+lGL1zNdE567TUMT8DcujPRzPp6NhA=
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEWTCCAkGgAwIBAgIQSVCO/y+/drLLF1/Ehl5HAjANBgkqhkiG9w0BAQsFADAo
MSYwJAYDVQQDEx1UZXN0aW5nIGNlcnRpZmljYXRlIGF1dGhvcml0eTAgFw0yMDA3
MTQxOTEzNDVaGA8yMTE5MDcxNDE5MTE0MlowGDEWMBQGA1UEAxMNc2lnbmVyLXRl
c3QwNDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAONujJphNIMRsSMC
NGFGip151lMGNUGCOimjCvy/DVmBGIvMacqCp267rUbogz1fyVt8JMwjgbaA1Uou
iJoMPC5PFnz9+/jETbjopGGxMXI103R/FWIGlpTozWq6G7u9ou7mBS/zWPen5aBt
IwVZKQFNBDiGUn50w3F5Kt/otBLwFHL9qlHfsYeIGWzsI0y3j3oDSGSh6JJKGZDv
MBSh0bxHnZPoVkHU15otF4uttSheYp6+otZZrVTb/C3Lr87CretjkCCqTFdqossn
bmRfkFy7X+c1LaTiT8IfHEiOWehsJA6Cy3F3dxBj1knccBjShBHTyKiOzJSxY9Ug
CG8AgE8CAwEAAaOBjDCBiTAOBgNVHQ8BAf8EBAMCA7gwHQYDVR0lBBYwFAYIKwYB
BQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBS9d8lNgz2ImVGa49a7JIeFY1R8IDAf
BgNVHSMEGDAWgBTyKcD02eohJPlIFHovfP2ttl3UGjAYBgNVHREEETAPgg1zaWdu
ZXItdGVzdDA0MA0GCSqGSIb3DQEBCwUAA4ICAQAUFKQqRVcsOJmKcrNhOeCPfjdR
1Xt4S9XYGEtdxOSHcnwiOvj/p3lCJAtqphVEDxe4THieeL05xMcOS9Q01TNTiNV5
dIm/N/hxcKKVYEeM7HtFSHMRIRuxb9wD1lgDV+ZhXXYNbs+dnSt3mENP5+FanVRP
JhfLPxbtaG/QR+N7ZQyvcdWv4jHfvPGB6l+ySP8IZOo5SktDTeEJYsjUgKZbSyvb
T6CTpftItgJo8yaRdbE5TsWx017KWh0vlk/dQAvvxQakN9aO3/JgtxcLPEkmNJxN
mIJA1xAcxV5/ixW+mX13lDOTsQc/PwrvzKW6OFvlvgPSfCMW0CVaFJf/yNCkngoc
DQIKPqRX46VLhgkGhsl8f1L7iuMn3tkERzrQx8XQr8f0zYTVyp5DbzdhZ51e9MmS
LNeC4NWDGhBhlepSpnWISiCgR7zkQmnbAL2CRHhNXu7f0aElRrvQ3LyT45Zvncy7
763lVGpdsdSEY1kKISMyFzGWMSDQI68J+5rEtuLews7KQimaKrEcp1b7bH5O6IjJ
hedkCs/Yc/n4FDuudYvdsDHFT2x0HTZn+qkIX57gpzSek3+1b3I5hJQtWgcSx/NR
neIRkZVTCW0R6hfKW7lea9rDTHMiyJ8jpscZjqg5KITLxJJ3ipg3miXxjeUMOZRW
6u0QVYXCMU+um5odFQ==
-----END CERTIFICATE-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA426MmmE0gxGxIwI0YUaKnXnWUwY1QYI6KaMK/L8NWYEYi8xp
yoKnbrutRuiDPV/JW3wkzCOBtoDVSi6Imgw8Lk8WfP37+MRNuOikYbExcjXTdH8V
YgaWlOjNarobu72i7uYFL/NY96floG0jBVkpAU0EOIZSfnTDcXkq3+i0EvAUcv2q
Ud+xh4gZbOwjTLePegNIZKHokkoZkO8wFKHRvEedk+hWQdTXmi0Xi621KF5inr6i
1lmtVNv8LcuvzsKt62OQIKpMV2qiyyduZF+QXLtf5zUtpOJPwh8cSI5Z6GwkDoLL
cXd3EGPWSdxwGNKEEdPIqI7MlLFj1SAIbwCATwIDAQABAoIBAEOkiaUQ7DFffbPP
4AxekrOrnRcsbYKCXRItMANkP3AzeT17GqvkmC/TGgJQ/VevuY/AKKGeneHOB6H8
nRxUL0IGu8WJNPwURpmMd/emX/J8F9w6P/3bv8WiSBZKLB12lZNATqKoWfmushk4
3IWmsw9z/KFjMf3ydH63bw0RhR1sQr5TT0BLje/0z1neaoVNfocTgySpM4DH+Mpv
ZE38VR4+MlujKpbdGwR0qcBwvA5tG4jkGLBf3TPTYYMpjnDZZ9ZRYQ0BDJhWEA7a
3Dpy2A1OGsXIQ5wt3MjPqK4el1mIcTaaUvaIHNEzB9Og6y07uMMzJJtTJsz4pgcq
VauWWgECgYEA++RN5Ii7Bf4J/PyesUusgkMpu22Umc4UImipJzGhwLCauZdKn7Cy
ZwvZH4aVGfoooCWlYTwDlv2exWinz1RvEGsP9SMykOk66A+RU/Ej7PP7zqQcZN5k
P/Qn3BfyO5gksbDhnm+DJl1i7Gre+T09ZsHCunGWCS5jatlfUhfMZMECgYEA5yQe
tFl4icOPPxOA7ISWy5dhleTD97DikqCgntqxA52SgqtF2LAHXBl+6bdQBf5w4zpu
FBoXtVBZdbmzK2ms3LQpeyzuYuRNJLwtrVGs+YLUXrm7aZPHBPKGH+kRTaU62t6A
ou+hytMNMXDDYICbf1snEemKC6H9qSI0A6Vf2Q8CgYEAk1ss4ivG1SuXJkOWhnuR
kKa/zCC/1PZEuxhlFEOpr7Lg4P+LrT3OMBAzVYkCwq6gg4diZy6XnwYBktS1jsmD
K6SmMi8EDtgSGN26k9O2w5C711gUMEIVfYBUrSHpGEnZ9YVXh7sOiywIieu/Qyk7
OVjSlQWL0xUrHb/KTpkTfkECgYEA0xZWgCfxgAa7bERYiiewOy/9q9Fm8m51DKlq
5ogb/oxJv9HAkNp5bi/OioyhpUewOqQi4XLO0gQWHwA/U1dHyasy8s2ey2tp1DGS
mWUszhUf8341XH7b03XU7ZGA/uL1s+pdme+0VzGVK+CqXRg2agGJ1b7tFiCTMoIM
9INz3BsCgYEA+29TYqx2UTun9PxELEbJEZ/IC8jMmJROpx6Ido7mky5huJlgfhtU
C7YbhCkChxM6hbgehwGWH8xj1jbVkliPe0XpABVkIACXKtQMzhg4shHlCmRTgZ+h
xNFJxVdoGRAVUthJyUTcAxWZMH4K5giMdzcQk4YxANekoBmUw3itinA=
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEWTCCAkGgAwIBAgIQFx8Gc/4fzxgTzS4MtpoovTANBgkqhkiG9w0BAQsFADAo
MSYwJAYDVQQDEx1UZXN0aW5nIGNlcnRpZmljYXRlIGF1dGhvcml0eTAgFw0yMDA3
MTQxOTEzNTNaGA8yMTE5MDcxNDE5MTE0MlowGDEWMBQGA1UEAxMNc2lnbmVyLXRl
c3QwNTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKuCo3uGGnlWK2Mr
qaX8Ep8USj+298tjTUogBUe1dvlkgNBiY9MiUuaBg3VaAqJy70G/nMuWos/Z/+m7
c+SyJaZaMGtOf91gSpSWWN2Ugh8PivgJMi+FWiSKwK3sYEN7V3g3iABGkNCfduA1
4eTAdKCBowQ7Xxz5wpWL5DjjgW6B0KbjL4iREzTwjl+bPHdOFEHzIdxLh18CRU1D
dvdwEwn8ST0VFdjl2hQVm+EYlMv8gyyl9mFaQ16YGW4XJSIjXNDIcxpe7ux6157o
IO9FS21A4aiNKWLrLtJEErX2F/PHZPb2i5L8kbumhom186VJssIlMGGFIfO8UiYC
ilwOWaECAwEAAaOBjDCBiTAOBgNVHQ8BAf8EBAMCA7gwHQYDVR0lBBYwFAYIKwYB
BQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBTYCgsnT8K6EV9hMxe5laZJHW4mNTAf
BgNVHSMEGDAWgBTyKcD02eohJPlIFHovfP2ttl3UGjAYBgNVHREEETAPgg1zaWdu
ZXItdGVzdDA1MA0GCSqGSIb3DQEBCwUAA4ICAQCOhEuD8fMm5iEU+416MoTQpLwX
irHPRym/5fGQxV5AG7ij9X/Pb9WPa7EO24K8/zxcmr7zdkMM/g89PmT/+Aa2Gy7+
XGNhGOQd3xgNcCk0cQ9GL/4HeyPWvLh681difsUEx3Gazh2NXlRAw2rScHmPuu06
+qZwu+zJkL8BUEXMgP4zh10B26zQQ/uFyE4M6Y0h4s2bOC06+vK8OBasklbC36ry
4x4BKlliADx9jtzHmsZJ30jMvjh6Uc2aPo91CGNXSfw4Zs8Ncz1fbyYlWd9goB9C
gxQsUK7o8JARioQQ0JPkMwh/4C2d41G7UFSDesOzbOlx+llNnE7JiWJiV6MFX7VV
Sy92p9/n0MV4pHYtiiftPhvzdLXRhqdKb+hAeYjEAquvHU7MSEv2EAB4Cen0wgh8
CAFqYrQNjZgiTZuPwZljoMlYmuGue91GX17+UvNA4hpUKXWxzampkKnO/Pp/TbCn
DQenKzBwoeY+faTZq30wAyvxfVWh1uebTxIf/7nUdUkVPVZDCwhbQCMxomXHwOhF
4xMTHOmCFxwOuUWqUwQeXIYGgQx0sm/qjx48+jetmJMOOvE4NEXVuRsP5Ggylqa0
vVTqf0eZISAIaBg+dVBe3NNCAfT89DtCE5j/pnqwbcK5sQYF1oxLLs0Wchz31L7Z
8lyeVv/66rxC8CrFSQ==
-----END CERTIFICATE-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAq4Kje4YaeVYrYyuppfwSnxRKP7b3y2NNSiAFR7V2+WSA0GJj
0yJS5oGDdVoConLvQb+cy5aiz9n/6btz5LIlplowa05/3WBKlJZY3ZSCHw+K+Aky
L4VaJIrArexgQ3tXeDeIAEaQ0J924DXh5MB0oIGjBDtfHPnClYvkOOOBboHQpuMv
iJETNPCOX5s8d04UQfMh3EuHXwJFTUN293ATCfxJPRUV2OXaFBWb4RiUy/yDLKX2
YVpDXpgZbhclIiNc0MhzGl7u7HrXnugg70VLbUDhqI0pYusu0kQStfYX88dk9vaL
kvyRu6aGibXzpUmywiUwYYUh87xSJgKKXA5ZoQIDAQABAoIBAHHPie6xKaY04Su4
0KXdpPm9PBwVrU9hAOvcXcSdDWsnHzeo4rc7gqmFbheUeEUWYeBOZ5zNxBKLhf+z
LY+oC8Xc+V5rw/vCJxt8vVGkd8hmxwAbEhtosU2oaX3Aaoy9L2kN6IjOStC10Out
tc3XTE0qWWO4hkAzGMWmA/cgOUZ7dfSe+qrBiMcBcQiDWozeSztl1FR1Wbq34rYI
ql0J3at0Ca9hiDR82T7DYAEZHkaASCvJt5wtRYmT+JbkqgSWfQO3F6NEXk7hOBJI
RYjx/enPko8JDTY/OQS7JtB78WX4n9ndeEdM7W9rJUAiz+08oODIlPtYV5Iqrov8
Q7cF+QECgYEAx/Y3HYza2DbychO8f0vjH/tdsjySA+BGxF/M0dQ1GpMceIsNdhPM
B3vSSsQaROIhi29++g2QjFRqn7o6K0yw5DfecerzCVo1CVSIoTZQDLSiP3pV+vfN
C01uWS3wnoRlnAYIHbyIfz7nGLu56JQ2HNnBIt1I6Rb8tLBjRhFpIlECgYEA25M9
Y8Q/Y8Pcl6GtDNxAJAj7DRrhBGRwgyu8Ka/MuqLWM6DN8bvsZdHP45FXG8dSU0Sz
0ybKuSjohnopacncBOnpjh/sEqqv3S+4/j8jghmIa+EjsIPlxIKjX7dwXmwXXMRf
zBUpXJpOfFe9ulacauv6mkOobdmZA0ZuSV01HlECgYEAsiiODLcN2SyDsN4iySw8
7abRYVeUJP3zL03HuIAg3E+MQ15pHPYgh95rjA/S8+KiTpCFipcBXfZslWmgICoR
RRT+DXNvHLsRnAGERlaU1e0uze3ao2ObfeF8WtqSkzmVKoE5Q/1RhEXwMto3lqBO
4j+lU8HjD0Ja30Z0/N3QVTECgYEAzCPOFW0lChnUgtz7SFOVBmubDIoK3cyLlkgY
/iDFlFdEEmfUUIRIujkgsBA2Dkt3zJa5IPyVySOxWyVET2guuBrI2yvujURHkLqH
oUkOOCyI2tNMHRXjjpluTtT7Ea4o4kRoVBLwi3mispPYft97OST/rmBsvQRq79KR
Qn/3nKECgYASJ8lZrUMTl74amFSGVrd4xRPhKJTer4C1HeLlwUaAKlEksNvpNecw
l3inYSityX8BXZzOje0pINg9Hd4+ylPzh1PxqCrRjyNNb5R4z2nJrVb8hDCcoG/p
Mia3unc6Qwos7FDwj9okULGK9P+lq+3vDvtiFflTZZsq46qmzrEmtQ==
-----END RSA PRIVATE KEY-----