github.com/prysmaticlabs/prysm@v1.4.4/shared/testutil/deposits.go (about) 1 package testutil 2 3 import ( 4 "context" 5 "sync" 6 "testing" 7 8 "github.com/pkg/errors" 9 "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" 10 "github.com/prysmaticlabs/prysm/beacon-chain/core/state" 11 iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface" 12 pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1" 13 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 14 "github.com/prysmaticlabs/prysm/shared/bls" 15 "github.com/prysmaticlabs/prysm/shared/bytesutil" 16 "github.com/prysmaticlabs/prysm/shared/hashutil" 17 "github.com/prysmaticlabs/prysm/shared/interop" 18 "github.com/prysmaticlabs/prysm/shared/params" 19 "github.com/prysmaticlabs/prysm/shared/trieutil" 20 ) 21 22 var lock sync.Mutex 23 24 // Caches 25 var cachedDeposits []*ethpb.Deposit 26 var privKeys []bls.SecretKey 27 var trie *trieutil.SparseMerkleTrie 28 29 // DeterministicDepositsAndKeys returns the entered amount of deposits and secret keys. 30 // The deposits are configured such that for deposit n the validator 31 // account is key n and the withdrawal account is key n+1. As such, 32 // if all secret keys for n validators are required then numDeposits 33 // should be n+1. 34 func DeterministicDepositsAndKeys(numDeposits uint64) ([]*ethpb.Deposit, []bls.SecretKey, error) { 35 resetCache() 36 lock.Lock() 37 defer lock.Unlock() 38 var err error 39 40 // Populate trie cache, if not initialized yet. 41 if trie == nil { 42 trie, err = trieutil.NewTrie(params.BeaconConfig().DepositContractTreeDepth) 43 if err != nil { 44 return nil, nil, errors.Wrap(err, "failed to create new trie") 45 } 46 } 47 48 // If more deposits requested than cached, generate more. 49 if numDeposits > uint64(len(cachedDeposits)) { 50 numExisting := uint64(len(cachedDeposits)) 51 numRequired := numDeposits - uint64(len(cachedDeposits)) 52 // Fetch the required number of keys. 53 secretKeys, publicKeys, err := interop.DeterministicallyGenerateKeys(numExisting, numRequired+1) 54 if err != nil { 55 return nil, nil, errors.Wrap(err, "could not create deterministic keys: ") 56 } 57 privKeys = append(privKeys, secretKeys[:len(secretKeys)-1]...) 58 59 // Create the new deposits and add them to the trie. 60 for i := uint64(0); i < numRequired; i++ { 61 balance := params.BeaconConfig().MaxEffectiveBalance 62 deposit, err := signedDeposit(secretKeys[i], publicKeys[i].Marshal(), publicKeys[i+1].Marshal(), balance) 63 if err != nil { 64 return nil, nil, errors.Wrap(err, "could not create signed deposit") 65 } 66 cachedDeposits = append(cachedDeposits, deposit) 67 68 hashedDeposit, err := deposit.Data.HashTreeRoot() 69 if err != nil { 70 return nil, nil, errors.Wrap(err, "could not tree hash deposit data") 71 } 72 73 trie.Insert(hashedDeposit[:], int(numExisting+i)) 74 } 75 } 76 77 depositTrie, _, err := DeterministicDepositTrie(int(numDeposits)) 78 if err != nil { 79 return nil, nil, errors.Wrap(err, "failed to create deposit trie") 80 } 81 requestedDeposits := cachedDeposits[:numDeposits] 82 for i := range requestedDeposits { 83 proof, err := depositTrie.MerkleProof(i) 84 if err != nil { 85 return nil, nil, errors.Wrap(err, "could not create merkle proof") 86 } 87 requestedDeposits[i].Proof = proof 88 } 89 90 return requestedDeposits, privKeys[0:numDeposits], nil 91 } 92 93 // DepositsWithBalance generates N amount of deposits with the balances taken from the passed in balances array. 94 // If an empty array is passed, 95 func DepositsWithBalance(balances []uint64) ([]*ethpb.Deposit, *trieutil.SparseMerkleTrie, error) { 96 var err error 97 98 sparseTrie, err := trieutil.NewTrie(params.BeaconConfig().DepositContractTreeDepth) 99 if err != nil { 100 return nil, nil, errors.Wrap(err, "failed to create new trie") 101 } 102 103 numDeposits := uint64(len(balances)) 104 numExisting := uint64(len(cachedDeposits)) 105 numRequired := numDeposits - uint64(len(cachedDeposits)) 106 107 var secretKeys []bls.SecretKey 108 var publicKeys []bls.PublicKey 109 if numExisting >= numDeposits+1 { 110 secretKeys = append(secretKeys, privKeys[:numDeposits+1]...) 111 publicKeys = publicKeysFromSecrets(secretKeys) 112 } else { 113 secretKeys = append(secretKeys, privKeys[:numExisting]...) 114 publicKeys = publicKeysFromSecrets(secretKeys) 115 // Fetch enough keys for all deposits, since this function is uncached. 116 newSecretKeys, newPublicKeys, err := interop.DeterministicallyGenerateKeys(numExisting, numRequired+1) 117 if err != nil { 118 return nil, nil, errors.Wrap(err, "could not create deterministic keys: ") 119 } 120 secretKeys = append(secretKeys, newSecretKeys...) 121 publicKeys = append(publicKeys, newPublicKeys...) 122 } 123 124 deposits := make([]*ethpb.Deposit, numDeposits) 125 // Create the new deposits and add them to the trie. 126 for i := uint64(0); i < numDeposits; i++ { 127 balance := params.BeaconConfig().MaxEffectiveBalance 128 if len(balances) == int(numDeposits) { 129 balance = balances[i] 130 } 131 deposit, err := signedDeposit(secretKeys[i], publicKeys[i].Marshal(), publicKeys[i+1].Marshal(), balance) 132 if err != nil { 133 return nil, nil, errors.Wrap(err, "could not create signed deposit") 134 } 135 deposits[i] = deposit 136 137 hashedDeposit, err := deposit.Data.HashTreeRoot() 138 if err != nil { 139 return nil, nil, errors.Wrap(err, "could not tree hash deposit data") 140 } 141 142 sparseTrie.Insert(hashedDeposit[:], int(i)) 143 } 144 145 depositTrie, _, err := DepositTrieSubset(sparseTrie, int(numDeposits)) 146 if err != nil { 147 return nil, nil, errors.Wrap(err, "failed to create deposit trie") 148 } 149 for i := range deposits { 150 proof, err := depositTrie.MerkleProof(i) 151 if err != nil { 152 return nil, nil, errors.Wrap(err, "could not create merkle proof") 153 } 154 deposits[i].Proof = proof 155 } 156 157 return deposits, sparseTrie, nil 158 } 159 160 func signedDeposit( 161 secretKey bls.SecretKey, 162 publicKey, 163 withdrawalKey []byte, 164 balance uint64, 165 ) (*ethpb.Deposit, error) { 166 withdrawalCreds := hashutil.Hash(withdrawalKey) 167 withdrawalCreds[0] = params.BeaconConfig().BLSWithdrawalPrefixByte 168 depositMessage := &pb.DepositMessage{ 169 PublicKey: publicKey, 170 Amount: balance, 171 WithdrawalCredentials: withdrawalCreds[:], 172 } 173 174 domain, err := helpers.ComputeDomain(params.BeaconConfig().DomainDeposit, nil, nil) 175 if err != nil { 176 return nil, errors.Wrap(err, "could not compute domain") 177 } 178 root, err := depositMessage.HashTreeRoot() 179 if err != nil { 180 return nil, errors.Wrap(err, "could not get signing root of deposit data") 181 } 182 183 sigRoot, err := (&pb.SigningData{ObjectRoot: root[:], Domain: domain}).HashTreeRoot() 184 if err != nil { 185 return nil, err 186 } 187 depositData := ðpb.Deposit_Data{ 188 PublicKey: publicKey, 189 Amount: balance, 190 WithdrawalCredentials: withdrawalCreds[:], 191 Signature: secretKey.Sign(sigRoot[:]).Marshal(), 192 } 193 194 deposit := ðpb.Deposit{ 195 Data: depositData, 196 } 197 return deposit, nil 198 } 199 200 // DeterministicDepositTrie returns a merkle trie of the requested size from the 201 // deterministic deposits. 202 func DeterministicDepositTrie(size int) (*trieutil.SparseMerkleTrie, [][32]byte, error) { 203 if trie == nil { 204 return nil, [][32]byte{}, errors.New("trie cache is empty, generate deposits at an earlier point") 205 } 206 207 return DepositTrieSubset(trie, size) 208 } 209 210 // DepositTrieSubset takes in a full tree and the desired size and returns a subset of the deposit trie. 211 func DepositTrieSubset(sparseTrie *trieutil.SparseMerkleTrie, size int) (*trieutil.SparseMerkleTrie, [][32]byte, error) { 212 if sparseTrie == nil { 213 return nil, [][32]byte{}, errors.New("trie is empty") 214 } 215 216 items := sparseTrie.Items() 217 if size > len(items) { 218 return nil, [][32]byte{}, errors.New("requested a larger tree than amount of deposits") 219 } 220 221 items = items[:size] 222 depositTrie, err := trieutil.GenerateTrieFromItems(items, params.BeaconConfig().DepositContractTreeDepth) 223 if err != nil { 224 return nil, [][32]byte{}, errors.Wrapf(err, "could not generate trie of %d length", size) 225 } 226 227 roots := make([][32]byte, len(items)) 228 for i, dep := range items { 229 roots[i] = bytesutil.ToBytes32(dep) 230 } 231 return depositTrie, roots, nil 232 } 233 234 // DeterministicEth1Data takes an array of deposits and returns the eth1Data made from the deposit trie. 235 func DeterministicEth1Data(size int) (*ethpb.Eth1Data, error) { 236 depositTrie, _, err := DeterministicDepositTrie(size) 237 if err != nil { 238 return nil, errors.Wrap(err, "failed to create trie") 239 } 240 root := depositTrie.Root() 241 eth1Data := ðpb.Eth1Data{ 242 BlockHash: root[:], 243 DepositRoot: root[:], 244 DepositCount: uint64(size), 245 } 246 return eth1Data, nil 247 } 248 249 // DeterministicGenesisState returns a genesis state made using the deterministic deposits. 250 func DeterministicGenesisState(t testing.TB, numValidators uint64) (iface.BeaconState, []bls.SecretKey) { 251 resetCache() 252 deposits, privKeys, err := DeterministicDepositsAndKeys(numValidators) 253 if err != nil { 254 t.Fatal(errors.Wrapf(err, "failed to get %d deposits", numValidators)) 255 } 256 eth1Data, err := DeterministicEth1Data(len(deposits)) 257 if err != nil { 258 t.Fatal(errors.Wrapf(err, "failed to get eth1data for %d deposits", numValidators)) 259 } 260 beaconState, err := state.GenesisBeaconState(context.Background(), deposits, uint64(0), eth1Data) 261 if err != nil { 262 t.Fatal(errors.Wrapf(err, "failed to get genesis beacon state of %d validators", numValidators)) 263 } 264 265 return beaconState, privKeys 266 } 267 268 // DepositTrieFromDeposits takes an array of deposits and returns the deposit trie. 269 func DepositTrieFromDeposits(deposits []*ethpb.Deposit) (*trieutil.SparseMerkleTrie, [][32]byte, error) { 270 encodedDeposits := make([][]byte, len(deposits)) 271 for i := 0; i < len(encodedDeposits); i++ { 272 hashedDeposit, err := deposits[i].Data.HashTreeRoot() 273 if err != nil { 274 return nil, [][32]byte{}, errors.Wrap(err, "could not tree hash deposit data") 275 } 276 encodedDeposits[i] = hashedDeposit[:] 277 } 278 279 depositTrie, err := trieutil.GenerateTrieFromItems(encodedDeposits, params.BeaconConfig().DepositContractTreeDepth) 280 if err != nil { 281 return nil, [][32]byte{}, errors.Wrap(err, "Could not generate deposit trie") 282 } 283 284 roots := make([][32]byte, len(deposits)) 285 for i, dep := range encodedDeposits { 286 roots[i] = bytesutil.ToBytes32(dep) 287 } 288 289 return depositTrie, roots, nil 290 } 291 292 // resetCache clears out the old trie, private keys and deposits. 293 func resetCache() { 294 trie = nil 295 privKeys = []bls.SecretKey{} 296 cachedDeposits = []*ethpb.Deposit{} 297 } 298 299 // DeterministicDepositsAndKeysSameValidator returns the entered amount of deposits and secret keys 300 // of the same validator. This is for negative test cases such as same deposits from same validators in a block don't 301 // result in duplicated validator indices. 302 func DeterministicDepositsAndKeysSameValidator(numDeposits uint64) ([]*ethpb.Deposit, []bls.SecretKey, error) { 303 resetCache() 304 lock.Lock() 305 defer lock.Unlock() 306 var err error 307 308 // Populate trie cache, if not initialized yet. 309 if trie == nil { 310 trie, err = trieutil.NewTrie(params.BeaconConfig().DepositContractTreeDepth) 311 if err != nil { 312 return nil, nil, errors.Wrap(err, "failed to create new trie") 313 } 314 } 315 316 // If more deposits requested than cached, generate more. 317 if numDeposits > uint64(len(cachedDeposits)) { 318 numExisting := uint64(len(cachedDeposits)) 319 numRequired := numDeposits - uint64(len(cachedDeposits)) 320 // Fetch the required number of keys. 321 secretKeys, publicKeys, err := interop.DeterministicallyGenerateKeys(numExisting, numRequired+1) 322 if err != nil { 323 return nil, nil, errors.Wrap(err, "could not create deterministic keys: ") 324 } 325 privKeys = append(privKeys, secretKeys[:len(secretKeys)-1]...) 326 327 // Create the new deposits and add them to the trie. Always use the first validator to create deposit 328 for i := uint64(0); i < numRequired; i++ { 329 withdrawalCreds := hashutil.Hash(publicKeys[1].Marshal()) 330 withdrawalCreds[0] = params.BeaconConfig().BLSWithdrawalPrefixByte 331 332 depositMessage := &pb.DepositMessage{ 333 PublicKey: publicKeys[1].Marshal(), 334 Amount: params.BeaconConfig().MaxEffectiveBalance, 335 WithdrawalCredentials: withdrawalCreds[:], 336 } 337 338 domain, err := helpers.ComputeDomain(params.BeaconConfig().DomainDeposit, nil, nil) 339 if err != nil { 340 return nil, nil, errors.Wrap(err, "could not compute domain") 341 } 342 root, err := depositMessage.HashTreeRoot() 343 if err != nil { 344 return nil, nil, errors.Wrap(err, "could not get signing root of deposit data") 345 } 346 sigRoot, err := (&pb.SigningData{ObjectRoot: root[:], Domain: domain}).HashTreeRoot() 347 if err != nil { 348 return nil, nil, errors.Wrap(err, "could not get signing root of deposit data and domain") 349 } 350 // Always use the same validator to sign 351 depositData := ðpb.Deposit_Data{ 352 PublicKey: depositMessage.PublicKey, 353 Amount: depositMessage.Amount, 354 WithdrawalCredentials: depositMessage.WithdrawalCredentials, 355 Signature: secretKeys[1].Sign(sigRoot[:]).Marshal(), 356 } 357 deposit := ðpb.Deposit{ 358 Data: depositData, 359 } 360 cachedDeposits = append(cachedDeposits, deposit) 361 362 hashedDeposit, err := deposit.Data.HashTreeRoot() 363 if err != nil { 364 return nil, nil, errors.Wrap(err, "could not tree hash deposit data") 365 } 366 367 trie.Insert(hashedDeposit[:], int(numExisting+i)) 368 } 369 } 370 371 depositTrie, _, err := DeterministicDepositTrie(int(numDeposits)) 372 if err != nil { 373 return nil, nil, errors.Wrap(err, "failed to create deposit trie") 374 } 375 requestedDeposits := cachedDeposits[:numDeposits] 376 for i := range requestedDeposits { 377 proof, err := depositTrie.MerkleProof(i) 378 if err != nil { 379 return nil, nil, errors.Wrap(err, "could not create merkle proof") 380 } 381 requestedDeposits[i].Proof = proof 382 } 383 384 return requestedDeposits, privKeys[0:numDeposits], nil 385 } 386 387 func publicKeysFromSecrets(secretKeys []bls.SecretKey) []bls.PublicKey { 388 publicKeys := make([]bls.PublicKey, len(secretKeys)) 389 for i, secretKey := range secretKeys { 390 publicKeys[i] = secretKey.PublicKey() 391 } 392 return publicKeys 393 }