Merge pull request #603 from nspcc-dev/feature/wallet

consensus: use wallets instead of WIF, closes #588.
This commit is contained in:
Roman Khimov 2020-01-20 16:16:10 +03:00 committed by GitHub
commit f4aa088d04
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 186 additions and 38 deletions

View file

@ -19,6 +19,7 @@ services:
command: "node --config-path /config --privnet"
volumes:
- ../config/protocol.privnet.docker.one.yml:/config/protocol.privnet.yml
- ./wallets/wallet1.json:/wallet1.json
- volume_chain:/chains
networks:
neo_go_network:
@ -33,6 +34,7 @@ services:
command: "node --config-path /config --privnet"
volumes:
- ../config/protocol.privnet.docker.two.yml:/config/protocol.privnet.yml
- ./wallets/wallet2.json:/wallet2.json
- volume_chain:/chains
networks:
neo_go_network:
@ -47,6 +49,7 @@ services:
command: "node --config-path /config --privnet"
volumes:
- ../config/protocol.privnet.docker.three.yml:/config/protocol.privnet.yml
- ./wallets/wallet3.json:/wallet3.json
- volume_chain:/chains
networks:
neo_go_network:
@ -61,6 +64,7 @@ services:
command: "node --config-path /config --privnet"
volumes:
- ../config/protocol.privnet.docker.four.yml:/config/protocol.privnet.yml
- ./wallets/wallet4.json:/wallet4.json
- volume_chain:/chains
networks:
neo_go_network:
@ -75,6 +79,7 @@ services:
command: "node --config-path /config --privnet"
volumes:
- ../config/protocol.privnet.docker.single.yml:/config/protocol.privnet.yml
- ./wallets/wallet1.json:/wallet1.json
- volume_chain:/chains
- ./1600-privnet-blocks-single.acc.gz:/privnet-blocks.acc.gz
networks:

View file

@ -0,0 +1 @@
{"name":"wallet1","version":"1.0","scrypt":{"n":16384,"r":8,"p":8},"accounts":[{"address":"AKkkumHbBipZ46UMZJoFynJMXzSRnBvKcs","label":null,"isDefault":false,"lock":false,"key":"6PYLmjBYJ4wQTCEfqvnznGJwZeW9pfUcV5m5oreHxqryUgqKpTRAFt9L8Y","contract":{"script":"2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2ac","parameters":[{"name":"parameter0","type":"Signature"}],"deployed":false},"extra":null},{"address":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","label":null,"isDefault":false,"lock":false,"key":"6PYLmjBYJ4wQTCEfqvnznGJwZeW9pfUcV5m5oreHxqryUgqKpTRAFt9L8Y","contract":{"script":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae","parameters":[{"name":"parameter0","type":"Signature"},{"name":"parameter1","type":"Signature"},{"name":"parameter2","type":"Signature"}],"deployed":false},"extra":null}],"extra":null}

View file

@ -0,0 +1 @@
{"name":"wallet1","version":"1.0","scrypt":{"n":16384,"r":8,"p":8},"accounts":[{"address":"AKkkumHbBipZ46UMZJoFynJMXzSRnBvKcs","label":null,"isDefault":false,"lock":false,"key":"6PYLmjBYJ4wQTCEfqvnznGJwZeW9pfUcV5m5oreHxqryUgqKpTRAFt9L8Y","contract":{"script":"2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2ac","parameters":[{"name":"parameter0","type":"Signature"}],"deployed":false},"extra":null},{"address":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","label":null,"isDefault":false,"lock":false,"key":"6PYLmjBYJ4wQTCEfqvnznGJwZeW9pfUcV5m5oreHxqryUgqKpTRAFt9L8Y","contract":{"script":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae","parameters":[{"name":"parameter0","type":"Signature"},{"name":"parameter1","type":"Signature"},{"name":"parameter2","type":"Signature"}],"deployed":false},"extra":null},{"address":"AbU69m8WUZJSWanfr1Cy66cpEcsmMcX7BR","label":null,"isDefault":false,"lock":false,"key":"6PYLmjBYJ4wQTCEfqvnznGJwZeW9pfUcV5m5oreHxqryUgqKpTRAFt9L8Y","contract":{"script":"512102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc251ae","parameters":[{"name":"parameter0","type":"Signature"}],"deployed":false},"extra":null}],"extra":null}

View file

@ -0,0 +1 @@
{"name":"wallet2","version":"1.0","scrypt":{"n":16384,"r":8,"p":8},"accounts":[{"address":"AWLYWXB8C9Lt1nHdDZJnC5cpYJjgRDLk17","label":null,"isDefault":false,"lock":false,"key":"6PYXHjPaNvW8YknSXaKsTWjf9FRxo1s4naV2jdmSQEgzaqKGX368rndN3L","contract":{"script":"2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406eac","parameters":[{"name":"parameter0","type":"Signature"}],"deployed":false},"extra":null},{"address":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","label":null,"isDefault":false,"lock":false,"key":"6PYXHjPaNvW8YknSXaKsTWjf9FRxo1s4naV2jdmSQEgzaqKGX368rndN3L","contract":{"script":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae","parameters":[{"name":"parameter0","type":"Signature"},{"name":"parameter1","type":"Signature"},{"name":"parameter2","type":"Signature"}],"deployed":false},"extra":null}],"extra":null}

View file

@ -0,0 +1 @@
{"name":"wallet3","version":"1.0","scrypt":{"n":16384,"r":8,"p":8},"accounts":[{"address":"AR3uEnLUdfm1tPMJmiJQurAXGL7h3EXQ2F","label":null,"isDefault":false,"lock":false,"key":"6PYX86vYiHfUbpD95hfN1xgnvcSxy5skxfWYKu3ztjecxk6ikYs2kcWbeh","contract":{"script":"2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699ac","parameters":[{"name":"parameter0","type":"Signature"}],"deployed":false},"extra":null},{"address":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","label":null,"isDefault":false,"lock":false,"key":"6PYX86vYiHfUbpD95hfN1xgnvcSxy5skxfWYKu3ztjecxk6ikYs2kcWbeh","contract":{"script":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae","parameters":[{"name":"parameter0","type":"Signature"},{"name":"parameter1","type":"Signature"},{"name":"parameter2","type":"Signature"}],"deployed":false},"extra":null}],"extra":null}

View file

@ -0,0 +1 @@
{"name":"wallet4","version":"1.0","scrypt":{"n":16384,"r":8,"p":8},"accounts":[{"address":"AJmjUqf1jDenxYpuNS4i2NxD9FQYieDpBF","label":null,"isDefault":false,"lock":false,"key":"6PYRXVwHSqFSukL3CuXxdQ75VmsKpjeLgQLEjt83FrtHf1gCVphHzdD4nc","contract":{"script":"2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62ac","parameters":[{"name":"parameter0","type":"Signature"}],"deployed":false},"extra":null},{"address":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","label":null,"isDefault":false,"lock":false,"key":"6PYRXVwHSqFSukL3CuXxdQ75VmsKpjeLgQLEjt83FrtHf1gCVphHzdD4nc","contract":{"script":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae","parameters":[{"name":"parameter0","type":"Signature"},{"name":"parameter1","type":"Signature"},{"name":"parameter2","type":"Signature"}],"deployed":false},"extra":null}],"extra":null}

View file

@ -57,5 +57,5 @@ ApplicationConfiguration:
Enabled: false
Port: 20014
UnlockWallet:
Path: "6PYRXVwHSqFSukL3CuXxdQ75VmsKpjeLgQLEjt83FrtHf1gCVphHzdD4nc"
Path: "/wallet4.json"
Password: "four"

View file

@ -57,5 +57,5 @@ ApplicationConfiguration:
Enabled: false
Port: 20011
UnlockWallet:
Path: "6PYLmjBYJ4wQTCEfqvnznGJwZeW9pfUcV5m5oreHxqryUgqKpTRAFt9L8Y"
Path: "/wallet1.json"
Password: "one"

View file

@ -51,5 +51,5 @@ ApplicationConfiguration:
Enabled: false
Port: 20011
UnlockWallet:
Path: "6PYLmjBYJ4wQTCEfqvnznGJwZeW9pfUcV5m5oreHxqryUgqKpTRAFt9L8Y"
Path: "/wallet1.json"
Password: "one"

View file

@ -57,5 +57,5 @@ ApplicationConfiguration:
Enabled: false
Port: 20013
UnlockWallet:
Path: "6PYX86vYiHfUbpD95hfN1xgnvcSxy5skxfWYKu3ztjecxk6ikYs2kcWbeh"
Path: "/wallet3.json"
Password: "three"

View file

@ -57,5 +57,5 @@ ApplicationConfiguration:
Enabled: false
Port: 20012
UnlockWallet:
Path: "6PYXHjPaNvW8YknSXaKsTWjf9FRxo1s4naV2jdmSQEgzaqKGX368rndN3L"
Path: "/wallet2.json"
Password: "two"

2
go.mod
View file

@ -7,7 +7,7 @@ require (
github.com/go-redis/redis v6.10.2+incompatible
github.com/go-yaml/yaml v2.1.0+incompatible
github.com/mr-tron/base58 v1.1.2
github.com/nspcc-dev/dbft v0.0.0-20200116150450-80b3f6f0dff8
github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a
github.com/nspcc-dev/rfc6979 v0.2.0
github.com/pkg/errors v0.8.1
github.com/prometheus/client_golang v1.2.1

4
go.sum
View file

@ -94,8 +94,8 @@ github.com/nspcc-dev/dbft v0.0.0-20191205084618-dacb1a30c254 h1:A4OkQDQOSPsJF8qU
github.com/nspcc-dev/dbft v0.0.0-20191205084618-dacb1a30c254/go.mod h1:w1Ln2aT+dBlPhLnuZhBV+DfPEdS2CHWWLp5JTScY3bw=
github.com/nspcc-dev/dbft v0.0.0-20191209120240-0d6b7568d9ae h1:T5V1QANlNMKun0EPB3eqg2PTXG4rmLhzDyEiV63kdB0=
github.com/nspcc-dev/dbft v0.0.0-20191209120240-0d6b7568d9ae/go.mod h1:3FjXOoHmA51EGfb5GS/HOv7VdmngNRTssSeQ729dvGY=
github.com/nspcc-dev/dbft v0.0.0-20200116150450-80b3f6f0dff8 h1:WjfnKH75ncU5iySB6ooTsbg2P0q1iQoecTN4gHIuEbs=
github.com/nspcc-dev/dbft v0.0.0-20200116150450-80b3f6f0dff8/go.mod h1:/YFK+XOxxg0Bfm6P92lY5eDSLYfp06XOdL8KAVgXjVk=
github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a h1:ajvxgEe9qY4vvoSmrADqdDx7hReodKTnT2IXN++qZG8=
github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a/go.mod h1:/YFK+XOxxg0Bfm6P92lY5eDSLYfp06XOdL8KAVgXjVk=
github.com/nspcc-dev/neofs-crypto v0.2.0 h1:ftN+59WqxSWz/RCgXYOfhmltOOqU+udsNQSvN6wkFck=
github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA=
github.com/nspcc-dev/neofs-crypto v0.2.3 h1:aca3X2aly92ENRbFK+kH6Hd+J9EQ4Eu6XMVoITSIKtc=

View file

@ -14,6 +14,7 @@ import (
"github.com/CityOfZion/neo-go/pkg/smartcontract"
"github.com/CityOfZion/neo-go/pkg/util"
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
"github.com/CityOfZion/neo-go/pkg/wallet"
"github.com/nspcc-dev/dbft"
"github.com/nspcc-dev/dbft/block"
"github.com/nspcc-dev/dbft/crypto"
@ -56,6 +57,7 @@ type service struct {
messages chan Payload
transactions chan *transaction.Transaction
lastProposal []util.Uint256
wallet *wallet.Wallet
}
// Config is a configuration for consensus services.
@ -104,12 +106,18 @@ func NewService(cfg Config) (Service, error) {
return srv, nil
}
priv, pub := getKeyPair(cfg.Wallet)
var err error
if srv.wallet, err = wallet.NewWalletFromFile(cfg.Wallet.Path); err != nil {
return nil, err
}
defer srv.wallet.Close()
srv.dbft = dbft.New(
dbft.WithLogger(srv.log),
dbft.WithSecondsPerBlock(cfg.TimePerBlock),
dbft.WithKeyPair(priv, pub),
dbft.WithGetKeyPair(srv.getKeyPair),
dbft.WithTxPerBlock(10000),
dbft.WithRequestTx(cfg.RequestTx),
dbft.WithGetTx(srv.getTx),
@ -180,14 +188,23 @@ func (s *service) validatePayload(p *Payload) bool {
return p.Verify(h)
}
func getKeyPair(cfg *config.WalletConfig) (crypto.PrivateKey, crypto.PublicKey) {
// TODO: replace with wallet opening from the given path (#588)
key, err := keys.NEP2Decrypt(cfg.Path, cfg.Password)
if err != nil {
return nil, nil
func (s *service) getKeyPair(pubs []crypto.PublicKey) (int, crypto.PrivateKey, crypto.PublicKey) {
for i := range pubs {
script := pubs[i].(*publicKey).GetVerificationScript()
acc := s.wallet.GetAccount(hash.Hash160(script))
if acc == nil {
continue
}
key, err := keys.NEP2Decrypt(acc.EncryptedWIF, s.Config.Wallet.Password)
if err != nil {
continue
}
return i, &privateKey{PrivateKey: key}, &publicKey{PublicKey: key.PublicKey()}
}
return &privateKey{PrivateKey: key}, &publicKey{PublicKey: key.PublicKey()}
return -1, nil, nil
}
// OnPayload handles Payload receive.

View file

@ -7,6 +7,7 @@ import (
"github.com/CityOfZion/neo-go/pkg/core"
"github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/util"
"github.com/nspcc-dev/dbft/block"
"github.com/nspcc-dev/dbft/payload"
@ -182,7 +183,7 @@ func newTestService(t *testing.T) *service {
Chain: newTestChain(t),
RequestTx: func(...util.Uint256) {},
Wallet: &config.WalletConfig{
Path: "6PYLmjBYJ4wQTCEfqvnznGJwZeW9pfUcV5m5oreHxqryUgqKpTRAFt9L8Y",
Path: "./testdata/wallet1.json",
Password: "one",
},
})
@ -192,35 +193,35 @@ func newTestService(t *testing.T) *service {
}
func getTestValidator(i int) (*privateKey, *publicKey) {
var wallet *config.WalletConfig
var wif, password string
switch i {
case 0:
wallet = &config.WalletConfig{
Path: "6PYLmjBYJ4wQTCEfqvnznGJwZeW9pfUcV5m5oreHxqryUgqKpTRAFt9L8Y",
Password: "one",
}
wif = "6PYLmjBYJ4wQTCEfqvnznGJwZeW9pfUcV5m5oreHxqryUgqKpTRAFt9L8Y"
password = "one"
case 1:
wallet = &config.WalletConfig{
Path: "6PYXHjPaNvW8YknSXaKsTWjf9FRxo1s4naV2jdmSQEgzaqKGX368rndN3L",
Password: "two",
}
wif = "6PYXHjPaNvW8YknSXaKsTWjf9FRxo1s4naV2jdmSQEgzaqKGX368rndN3L"
password = "two"
case 2:
wallet = &config.WalletConfig{
Path: "6PYX86vYiHfUbpD95hfN1xgnvcSxy5skxfWYKu3ztjecxk6ikYs2kcWbeh",
Password: "three",
}
wif = "6PYX86vYiHfUbpD95hfN1xgnvcSxy5skxfWYKu3ztjecxk6ikYs2kcWbeh"
password = "three"
case 3:
wallet = &config.WalletConfig{
Path: "6PYRXVwHSqFSukL3CuXxdQ75VmsKpjeLgQLEjt83FrtHf1gCVphHzdD4nc",
Password: "four",
}
wif = "6PYRXVwHSqFSukL3CuXxdQ75VmsKpjeLgQLEjt83FrtHf1gCVphHzdD4nc"
password = "four"
default:
return nil, nil
}
priv, pub := getKeyPair(wallet)
key, err := keys.NEP2Decrypt(wif, password)
if err != nil {
return nil, nil
}
return priv.(*privateKey), pub.(*publicKey)
return &privateKey{PrivateKey: key}, &publicKey{PublicKey: key.PublicKey()}
}
func newTestChain(t *testing.T) *core.Blockchain {

1
pkg/consensus/testdata/wallet1.json vendored Normal file
View file

@ -0,0 +1 @@
{"name":"wallet1","version":"1.0","scrypt":{"n":16384,"r":8,"p":8},"accounts":[{"address":"AKkkumHbBipZ46UMZJoFynJMXzSRnBvKcs","label":null,"isDefault":false,"lock":false,"key":"6PYLmjBYJ4wQTCEfqvnznGJwZeW9pfUcV5m5oreHxqryUgqKpTRAFt9L8Y","contract":{"script":"2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2ac","parameters":[{"name":"parameter0","type":"Signature"}],"deployed":false},"extra":null},{"address":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","label":null,"isDefault":false,"lock":false,"key":"6PYLmjBYJ4wQTCEfqvnznGJwZeW9pfUcV5m5oreHxqryUgqKpTRAFt9L8Y","contract":{"script":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae","parameters":[{"name":"parameter0","type":"Signature"},{"name":"parameter1","type":"Signature"},{"name":"parameter2","type":"Signature"}],"deployed":false},"extra":null}],"extra":null}

1
pkg/consensus/testdata/wallet2.json vendored Normal file
View file

@ -0,0 +1 @@
{"name":"wallet2","version":"1.0","scrypt":{"n":16384,"r":8,"p":8},"accounts":[{"address":"AWLYWXB8C9Lt1nHdDZJnC5cpYJjgRDLk17","label":null,"isDefault":false,"lock":false,"key":"6PYXHjPaNvW8YknSXaKsTWjf9FRxo1s4naV2jdmSQEgzaqKGX368rndN3L","contract":{"script":"2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406eac","parameters":[{"name":"parameter0","type":"Signature"}],"deployed":false},"extra":null},{"address":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","label":null,"isDefault":false,"lock":false,"key":"6PYXHjPaNvW8YknSXaKsTWjf9FRxo1s4naV2jdmSQEgzaqKGX368rndN3L","contract":{"script":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae","parameters":[{"name":"parameter0","type":"Signature"},{"name":"parameter1","type":"Signature"},{"name":"parameter2","type":"Signature"}],"deployed":false},"extra":null}],"extra":null}

1
pkg/consensus/testdata/wallet3.json vendored Normal file
View file

@ -0,0 +1 @@
{"name":"wallet3","version":"1.0","scrypt":{"n":16384,"r":8,"p":8},"accounts":[{"address":"AR3uEnLUdfm1tPMJmiJQurAXGL7h3EXQ2F","label":null,"isDefault":false,"lock":false,"key":"6PYX86vYiHfUbpD95hfN1xgnvcSxy5skxfWYKu3ztjecxk6ikYs2kcWbeh","contract":{"script":"2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699ac","parameters":[{"name":"parameter0","type":"Signature"}],"deployed":false},"extra":null},{"address":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","label":null,"isDefault":false,"lock":false,"key":"6PYX86vYiHfUbpD95hfN1xgnvcSxy5skxfWYKu3ztjecxk6ikYs2kcWbeh","contract":{"script":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae","parameters":[{"name":"parameter0","type":"Signature"},{"name":"parameter1","type":"Signature"},{"name":"parameter2","type":"Signature"}],"deployed":false},"extra":null}],"extra":null}

1
pkg/consensus/testdata/wallet4.json vendored Normal file
View file

@ -0,0 +1 @@
{"name":"wallet4","version":"1.0","scrypt":{"n":16384,"r":8,"p":8},"accounts":[{"address":"AJmjUqf1jDenxYpuNS4i2NxD9FQYieDpBF","label":null,"isDefault":false,"lock":false,"key":"6PYRXVwHSqFSukL3CuXxdQ75VmsKpjeLgQLEjt83FrtHf1gCVphHzdD4nc","contract":{"script":"2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd62ac","parameters":[{"name":"parameter0","type":"Signature"}],"deployed":false},"extra":null},{"address":"AZ81H31DMWzbSnFDLFkzh9vHwaDLayV7fU","label":null,"isDefault":false,"lock":false,"key":"6PYRXVwHSqFSukL3CuXxdQ75VmsKpjeLgQLEjt83FrtHf1gCVphHzdD4nc","contract":{"script":"532102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd622102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc22103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee69954ae","parameters":[{"name":"parameter0","type":"Signature"},{"name":"parameter1","type":"Signature"},{"name":"parameter2","type":"Signature"}],"deployed":false},"extra":null}],"extra":null}

View file

@ -1,8 +1,11 @@
package wallet
import (
"encoding/hex"
"encoding/json"
"errors"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/util"
)
@ -43,8 +46,8 @@ type Account struct {
// Contract represents a subset of the smartcontract to embed in the
// Account so it's NEP-6 compliant.
type Contract struct {
// Script hash of the contract deployed on the blockchain.
Script util.Uint160 `json:"script"`
// Script of the contract deployed on the blockchain.
Script []byte `json:"script"`
// A list of parameters used deploying this contract.
Parameters []interface{} `json:"parameters"`
@ -53,6 +56,54 @@ type Contract struct {
Deployed bool `json:"deployed"`
}
// contract is an intermediate struct used for json unmarshalling.
type contract struct {
// Script is a hex-encoded script of the contract.
Script string `json:"script"`
// A list of parameters used deploying this contract.
Parameters []interface{} `json:"parameters"`
// Indicates whether the contract has been deployed to the blockchain.
Deployed bool `json:"deployed"`
}
// ScriptHash returns the hash of contract's script.
func (c Contract) ScriptHash() util.Uint160 {
return hash.Hash160(c.Script)
}
// MarshalJSON implements json.Marshaler interface.
func (c Contract) MarshalJSON() ([]byte, error) {
var cc contract
cc.Script = hex.EncodeToString(c.Script)
cc.Parameters = c.Parameters
cc.Deployed = c.Deployed
return json.Marshal(cc)
}
// UnmarshalJSON implements json.Unmarshaler interface.
func (c *Contract) UnmarshalJSON(data []byte) error {
var cc contract
if err := json.Unmarshal(data, &cc); err != nil {
return err
}
script, err := hex.DecodeString(cc.Script)
if err != nil {
return err
}
c.Script = script
c.Parameters = cc.Parameters
c.Deployed = cc.Deployed
return nil
}
// NewAccount creates a new Account with a random generated PrivateKey.
func NewAccount() (*Account, error) {
priv, err := keys.NewPrivateKey()

View file

@ -2,8 +2,10 @@ package wallet
import (
"encoding/hex"
"encoding/json"
"testing"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/internal/keytestcases"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -47,6 +49,31 @@ func TestNewFromWif(t *testing.T) {
}
}
func TestContract_MarshalJSON(t *testing.T) {
var c Contract
data := []byte(`{"script":"0102","parameters":[1],"deployed":false}`)
require.NoError(t, json.Unmarshal(data, &c))
require.Equal(t, []byte{1, 2}, c.Script)
result, err := json.Marshal(c)
require.NoError(t, err)
require.JSONEq(t, string(data), string(result))
data = []byte(`1`)
require.Error(t, json.Unmarshal(data, &c))
data = []byte(`{"script":"ERROR","parameters":[1],"deployed":false}`)
require.Error(t, json.Unmarshal(data, &c))
}
func TestContract_ScriptHash(t *testing.T) {
script := []byte{0, 1, 2, 3}
c := &Contract{Script: script}
require.Equal(t, hash.Hash160(script), c.ScriptHash())
}
func compareFields(t *testing.T, tk keytestcases.Ktype, acc *Account) {
if want, have := tk.Address, acc.Address; want != have {
t.Fatalf("expected %s got %s", want, have)

View file

@ -6,6 +6,7 @@ import (
"os"
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
"github.com/CityOfZion/neo-go/pkg/util"
)
const (
@ -117,3 +118,14 @@ func (w *Wallet) Close() {
rc.Close()
}
}
// GetAccount returns account corresponding to the provided scripthash.
func (w *Wallet) GetAccount(h util.Uint160) *Account {
for _, acc := range w.Accounts {
if c := acc.Contract; c != nil && h.Equals(c.ScriptHash()) {
return acc
}
}
return nil
}

View file

@ -6,6 +6,7 @@ import (
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -119,3 +120,28 @@ func removeWallet(t *testing.T, walletPath string) {
err := os.RemoveAll(walletPath)
require.NoError(t, err)
}
func TestWallet_GetAccount(t *testing.T) {
wallet := checkWalletConstructor(t)
accounts := []*Account{
{
Contract: &Contract{
Script: []byte{0, 1, 2, 3},
},
},
{
Contract: &Contract{
Script: []byte{3, 2, 1, 0},
},
},
}
for _, acc := range accounts {
wallet.AddAccount(acc)
}
for i, acc := range accounts {
h := acc.Contract.ScriptHash()
assert.Equal(t, acc, wallet.GetAccount(h), "can't get %d account", i)
}
}