github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/internal/testchain/address.go (about) 1 package testchain 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/nspcc-dev/neo-go/pkg/core/block" 8 "github.com/nspcc-dev/neo-go/pkg/core/transaction" 9 "github.com/nspcc-dev/neo-go/pkg/crypto/hash" 10 "github.com/nspcc-dev/neo-go/pkg/crypto/keys" 11 "github.com/nspcc-dev/neo-go/pkg/encoding/address" 12 "github.com/nspcc-dev/neo-go/pkg/io" 13 "github.com/nspcc-dev/neo-go/pkg/smartcontract" 14 "github.com/nspcc-dev/neo-go/pkg/util" 15 "github.com/nspcc-dev/neo-go/pkg/vm/emit" 16 "github.com/stretchr/testify/require" 17 ) 18 19 // privNetKeys is a list of unencrypted WIFs sorted by public key. 20 var privNetKeys = []string{ 21 "KzfPUYDC9n2yf4fK5ro4C8KMcdeXtFuEnStycbZgX3GomiUsvX6W", 22 "KzgWE3u3EDp13XPXXuTKZxeJ3Gi8Bsm8f9ijY3ZsCKKRvZUo1Cdn", 23 "KxyjQ8eUa4FHt3Gvioyt1Wz29cTUrE4eTqX3yFSk1YFCsPL8uNsY", 24 "L2oEXKRAAMiPEZukwR5ho2S6SMeQLhcK9mF71ZnF7GvT8dU4Kkgz", 25 26 // Provide 2 committee extra members so that the committee address differs from 27 // the validators one. 28 "L1Tr1iq5oz1jaFaMXP21sHDkJYDDkuLtpvQ4wRf1cjKvJYvnvpAb", 29 "Kz6XTUrExy78q8f4MjDHnwz8fYYyUE8iPXwPRAkHa3qN2JcHYm7e", 30 } 31 32 // ValidatorsCount returns the number of validators in the testchain. 33 const ValidatorsCount = 4 34 35 var ( 36 // ids maps validators order by public key sorting to validators ID. 37 // That is the order of the validator in the StandByValidators list. 38 ids = []int{1, 3, 0, 2, 4, 5} 39 // orders maps validators id to its order by public key sorting. 40 orders = []int{2, 0, 3, 1, 4, 5} 41 ) 42 43 // Size returns testchain initial validators amount. 44 func Size() int { 45 return ValidatorsCount 46 } 47 48 // CommitteeSize returns testchain committee size. 49 func CommitteeSize() int { 50 return len(privNetKeys) 51 } 52 53 // IDToOrder returns node's order in privnet. 54 func IDToOrder(id int) int { 55 return orders[id] 56 } 57 58 // WIF returns the unencrypted wif of the specified validator. 59 func WIF(i int) string { 60 return privNetKeys[i] 61 } 62 63 // PrivateKey returns the private key of node #i. 64 func PrivateKey(i int) *keys.PrivateKey { 65 wif := WIF(i) 66 priv, err := keys.NewPrivateKeyFromWIF(wif) 67 if err != nil { 68 panic(err) 69 } 70 return priv 71 } 72 73 // PrivateKeyByID returns private keys of a node with the specified id. 74 func PrivateKeyByID(id int) *keys.PrivateKey { 75 return PrivateKey(IDToOrder(id)) 76 } 77 78 // MultisigVerificationScript returns script hash of the consensus multisig address. 79 func MultisigVerificationScript() []byte { 80 var pubs keys.PublicKeys 81 for i := range privNetKeys[:ValidatorsCount] { 82 priv := PrivateKey(ids[i]) 83 pubs = append(pubs, priv.PublicKey()) 84 } 85 86 script, err := smartcontract.CreateDefaultMultiSigRedeemScript(pubs) 87 if err != nil { 88 panic(err) 89 } 90 return script 91 } 92 93 // MultisigScriptHash returns consensus address as Uint160. 94 func MultisigScriptHash() util.Uint160 { 95 return hash.Hash160(MultisigVerificationScript()) 96 } 97 98 // MultisigAddress return consensus address as string. 99 func MultisigAddress() string { 100 return address.Uint160ToString(MultisigScriptHash()) 101 } 102 103 // CommitteeVerificationScript returns script hash of the committee multisig address. 104 func CommitteeVerificationScript() []byte { 105 var pubs keys.PublicKeys 106 for i := range privNetKeys { 107 priv := PrivateKey(ids[i]) 108 pubs = append(pubs, priv.PublicKey()) 109 } 110 111 script, err := smartcontract.CreateMajorityMultiSigRedeemScript(pubs) 112 if err != nil { 113 panic(err) 114 } 115 return script 116 } 117 118 // CommitteeScriptHash returns committee address as Uint160. 119 func CommitteeScriptHash() util.Uint160 { 120 return hash.Hash160(CommitteeVerificationScript()) 121 } 122 123 // CommitteeAddress return committee address as string. 124 func CommitteeAddress() string { 125 return address.Uint160ToString(CommitteeScriptHash()) 126 } 127 128 // Sign signs data by all consensus nodes and returns invocation script. 129 func Sign(h hash.Hashable) []byte { 130 buf := io.NewBufBinWriter() 131 for i := 0; i < 3; i++ { 132 pKey := PrivateKey(i) 133 sig := pKey.SignHashable(uint32(Network()), h) 134 if len(sig) != 64 { 135 panic("wrong signature length") 136 } 137 emit.Bytes(buf.BinWriter, sig) 138 } 139 return buf.Bytes() 140 } 141 142 // SignCommittee signs data by a majority of committee members. 143 func SignCommittee(h hash.Hashable) []byte { 144 buf := io.NewBufBinWriter() 145 for i := 0; i < CommitteeSize()/2+1; i++ { 146 pKey := PrivateKey(i) 147 sig := pKey.SignHashable(uint32(Network()), h) 148 if len(sig) != 64 { 149 panic("wrong signature length") 150 } 151 emit.Bytes(buf.BinWriter, sig) 152 } 153 return buf.Bytes() 154 } 155 156 // NewBlock creates a new block for the given blockchain with the given offset 157 // (usually, 1), primary node index and transactions. 158 func NewBlock(t *testing.T, bc Ledger, offset uint32, primary uint32, txs ...*transaction.Transaction) *block.Block { 159 witness := transaction.Witness{VerificationScript: MultisigVerificationScript()} 160 height := bc.BlockHeight() 161 h := bc.GetHeaderHash(height) 162 hdr, err := bc.GetHeader(h) 163 require.NoError(t, err) 164 b := &block.Block{ 165 Header: block.Header{ 166 PrevHash: hdr.Hash(), 167 Timestamp: (uint64(time.Now().UTC().Unix()) + uint64(hdr.Index)) * 1000, 168 Index: hdr.Index + offset, 169 PrimaryIndex: byte(primary), 170 NextConsensus: witness.ScriptHash(), 171 Script: witness, 172 }, 173 Transactions: txs, 174 } 175 b.RebuildMerkleRoot() 176 177 b.Script.InvocationScript = Sign(b) 178 return b 179 }