mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-07 13:55:17 +00:00
crypto: remove unused code (#8412)
This commit is contained in:
@@ -2,6 +2,8 @@ package ed25519
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/sha256"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -124,7 +126,7 @@ func (privKey PrivKey) Type() string {
|
|||||||
// It uses OS randomness in conjunction with the current global random seed
|
// It uses OS randomness in conjunction with the current global random seed
|
||||||
// in tendermint/libs/common to generate the private key.
|
// in tendermint/libs/common to generate the private key.
|
||||||
func GenPrivKey() PrivKey {
|
func GenPrivKey() PrivKey {
|
||||||
return genPrivKey(crypto.CReader())
|
return genPrivKey(rand.Reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
// genPrivKey generates a new ed25519 private key using the provided reader.
|
// genPrivKey generates a new ed25519 private key using the provided reader.
|
||||||
@@ -142,9 +144,8 @@ func genPrivKey(rand io.Reader) PrivKey {
|
|||||||
// NOTE: secret should be the output of a KDF like bcrypt,
|
// NOTE: secret should be the output of a KDF like bcrypt,
|
||||||
// if it's derived from user input.
|
// if it's derived from user input.
|
||||||
func GenPrivKeyFromSecret(secret []byte) PrivKey {
|
func GenPrivKeyFromSecret(secret []byte) PrivKey {
|
||||||
seed := crypto.Sha256(secret) // Not Ripemd160 because we want 32 bytes.
|
seed := sha256.Sum256(secret)
|
||||||
|
return PrivKey(ed25519.NewKeyFromSeed(seed[:]))
|
||||||
return PrivKey(ed25519.NewKeyFromSeed(seed))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
@@ -229,5 +230,5 @@ func (b *BatchVerifier) Add(key crypto.PubKey, msg, signature []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *BatchVerifier) Verify() (bool, []bool) {
|
func (b *BatchVerifier) Verify() (bool, []bool) {
|
||||||
return b.BatchVerifier.Verify(crypto.CReader())
|
return b.BatchVerifier.Verify(rand.Reader)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
// Copyright 2017 Tendermint. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// 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 crypto_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/tendermint/tendermint/crypto"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExampleSha256() {
|
|
||||||
sum := crypto.Sha256([]byte("This is Tendermint"))
|
|
||||||
fmt.Printf("%x\n", sum)
|
|
||||||
// Output:
|
|
||||||
// f91afb642f3d1c87c17eb01aae5cb65c242dfdbe7cf1066cc260f4ce5d33b94e
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package crypto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/sha256"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Sha256(bytes []byte) []byte {
|
|
||||||
hasher := sha256.New()
|
|
||||||
hasher.Write(bytes)
|
|
||||||
return hasher.Sum(nil)
|
|
||||||
}
|
|
||||||
@@ -2,9 +2,9 @@ package merkle
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
|
||||||
tmcrypto "github.com/tendermint/tendermint/proto/tendermint/crypto"
|
tmcrypto "github.com/tendermint/tendermint/proto/tendermint/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -79,14 +79,13 @@ func (op ValueOp) Run(args [][]byte) ([][]byte, error) {
|
|||||||
return nil, fmt.Errorf("expected 1 arg, got %v", len(args))
|
return nil, fmt.Errorf("expected 1 arg, got %v", len(args))
|
||||||
}
|
}
|
||||||
value := args[0]
|
value := args[0]
|
||||||
hasher := tmhash.New()
|
|
||||||
hasher.Write(value)
|
vhash := sha256.Sum256(value)
|
||||||
vhash := hasher.Sum(nil)
|
|
||||||
|
|
||||||
bz := new(bytes.Buffer)
|
bz := new(bytes.Buffer)
|
||||||
// Wrap <op.Key, vhash> to hash the KVPair.
|
// Wrap <op.Key, vhash> to hash the KVPair.
|
||||||
encodeByteSlice(bz, op.key) //nolint: errcheck // does not error
|
encodeByteSlice(bz, op.key) //nolint: errcheck // does not error
|
||||||
encodeByteSlice(bz, vhash) //nolint: errcheck // does not error
|
encodeByteSlice(bz, vhash[:]) //nolint: errcheck // does not error
|
||||||
kvhash := leafHash(bz.Bytes())
|
kvhash := leafHash(bz.Bytes())
|
||||||
|
|
||||||
if !bytes.Equal(kvhash, op.Proof.LeafHash) {
|
if !bytes.Equal(kvhash, op.Proof.LeafHash) {
|
||||||
|
|||||||
@@ -1,35 +1,15 @@
|
|||||||
package crypto
|
package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
crand "crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
|
||||||
"io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// This only uses the OS's randomness
|
// This only uses the OS's randomness
|
||||||
func randBytes(numBytes int) []byte {
|
func CRandBytes(numBytes int) []byte {
|
||||||
b := make([]byte, numBytes)
|
b := make([]byte, numBytes)
|
||||||
_, err := crand.Read(b)
|
_, err := rand.Read(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// This only uses the OS's randomness
|
|
||||||
func CRandBytes(numBytes int) []byte {
|
|
||||||
return randBytes(numBytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CRandHex returns a hex encoded string that's floor(numDigits/2) * 2 long.
|
|
||||||
//
|
|
||||||
// Note: CRandHex(24) gives 96 bits of randomness that
|
|
||||||
// are usually strong enough for most purposes.
|
|
||||||
func CRandHex(numDigits int) string {
|
|
||||||
return hex.EncodeToString(CRandBytes(numDigits / 2))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a crand.Reader.
|
|
||||||
func CReader() io.Reader {
|
|
||||||
return crand.Reader
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package secp256k1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -70,7 +71,7 @@ func (privKey PrivKey) Type() string {
|
|||||||
// GenPrivKey generates a new ECDSA private key on curve secp256k1 private key.
|
// GenPrivKey generates a new ECDSA private key on curve secp256k1 private key.
|
||||||
// It uses OS randomness to generate the private key.
|
// It uses OS randomness to generate the private key.
|
||||||
func GenPrivKey() PrivKey {
|
func GenPrivKey() PrivKey {
|
||||||
return genPrivKey(crypto.CReader())
|
return genPrivKey(rand.Reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
// genPrivKey generates a new secp256k1 private key using the provided reader.
|
// genPrivKey generates a new secp256k1 private key using the provided reader.
|
||||||
@@ -190,8 +191,8 @@ var secp256k1halfN = new(big.Int).Rsh(secp256k1.S256().N, 1)
|
|||||||
// The returned signature will be of the form R || S (in lower-S form).
|
// The returned signature will be of the form R || S (in lower-S form).
|
||||||
func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
|
func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
|
||||||
priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey)
|
priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey)
|
||||||
|
seed := sha256.Sum256(msg)
|
||||||
sig, err := priv.Sign(crypto.Sha256(msg))
|
sig, err := priv.Sign(seed[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -220,7 +221,8 @@ func (pubKey PubKey) VerifySignature(msg []byte, sigStr []byte) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return signature.Verify(crypto.Sha256(msg), pub)
|
seed := sha256.Sum256(msg)
|
||||||
|
return signature.Verify(seed[:], pub)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read Signature struct from R || S. Caller needs to ensure
|
// Read Signature struct from R || S. Caller needs to ensure
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package sr25519
|
package sr25519
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/oasisprotocol/curve25519-voi/primitives/sr25519"
|
"github.com/oasisprotocol/curve25519-voi/primitives/sr25519"
|
||||||
@@ -42,5 +43,5 @@ func (b *BatchVerifier) Add(key crypto.PubKey, msg, signature []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *BatchVerifier) Verify() (bool, []bool) {
|
func (b *BatchVerifier) Verify() (bool, []bool) {
|
||||||
return b.BatchVerifier.Verify(crypto.CReader())
|
return b.BatchVerifier.Verify(rand.Reader)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package sr25519
|
package sr25519
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/sha256"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -48,7 +50,7 @@ func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
|
|||||||
|
|
||||||
st := signingCtx.NewTranscriptBytes(msg)
|
st := signingCtx.NewTranscriptBytes(msg)
|
||||||
|
|
||||||
sig, err := privKey.kp.Sign(crypto.CReader(), st)
|
sig, err := privKey.kp.Sign(rand.Reader, st)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("sr25519: failed to sign message: %w", err)
|
return nil, fmt.Errorf("sr25519: failed to sign message: %w", err)
|
||||||
}
|
}
|
||||||
@@ -132,7 +134,7 @@ func (privKey *PrivKey) UnmarshalJSON(data []byte) error {
|
|||||||
// It uses OS randomness in conjunction with the current global random seed
|
// It uses OS randomness in conjunction with the current global random seed
|
||||||
// in tendermint/libs/common to generate the private key.
|
// in tendermint/libs/common to generate the private key.
|
||||||
func GenPrivKey() PrivKey {
|
func GenPrivKey() PrivKey {
|
||||||
return genPrivKey(crypto.CReader())
|
return genPrivKey(rand.Reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
func genPrivKey(rng io.Reader) PrivKey {
|
func genPrivKey(rng io.Reader) PrivKey {
|
||||||
@@ -154,10 +156,9 @@ func genPrivKey(rng io.Reader) PrivKey {
|
|||||||
// NOTE: secret should be the output of a KDF like bcrypt,
|
// NOTE: secret should be the output of a KDF like bcrypt,
|
||||||
// if it's derived from user input.
|
// if it's derived from user input.
|
||||||
func GenPrivKeyFromSecret(secret []byte) PrivKey {
|
func GenPrivKeyFromSecret(secret []byte) PrivKey {
|
||||||
seed := crypto.Sha256(secret) // Not Ripemd160 because we want 32 bytes.
|
seed := sha256.Sum256(secret)
|
||||||
|
|
||||||
var privKey PrivKey
|
var privKey PrivKey
|
||||||
if err := privKey.msk.UnmarshalBinary(seed); err != nil {
|
if err := privKey.msk.UnmarshalBinary(seed[:]); err != nil {
|
||||||
panic("sr25519: failed to deserialize MiniSecretKey: " + err.Error())
|
panic("sr25519: failed to deserialize MiniSecretKey: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,19 +2,14 @@ package tmhash
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"hash"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Size = sha256.Size
|
Size = sha256.Size
|
||||||
BlockSize = sha256.BlockSize
|
BlockSize = sha256.BlockSize
|
||||||
|
TruncatedSize = 20
|
||||||
)
|
)
|
||||||
|
|
||||||
// New returns a new hash.Hash.
|
|
||||||
func New() hash.Hash {
|
|
||||||
return sha256.New()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sum returns the SHA256 of the bz.
|
// Sum returns the SHA256 of the bz.
|
||||||
func Sum(bz []byte) []byte {
|
func Sum(bz []byte) []byte {
|
||||||
h := sha256.Sum256(bz)
|
h := sha256.Sum256(bz)
|
||||||
@@ -23,41 +18,6 @@ func Sum(bz []byte) []byte {
|
|||||||
|
|
||||||
//-------------------------------------------------------------
|
//-------------------------------------------------------------
|
||||||
|
|
||||||
const (
|
|
||||||
TruncatedSize = 20
|
|
||||||
)
|
|
||||||
|
|
||||||
type sha256trunc struct {
|
|
||||||
sha256 hash.Hash
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h sha256trunc) Write(p []byte) (n int, err error) {
|
|
||||||
return h.sha256.Write(p)
|
|
||||||
}
|
|
||||||
func (h sha256trunc) Sum(b []byte) []byte {
|
|
||||||
shasum := h.sha256.Sum(b)
|
|
||||||
return shasum[:TruncatedSize]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h sha256trunc) Reset() {
|
|
||||||
h.sha256.Reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h sha256trunc) Size() int {
|
|
||||||
return TruncatedSize
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h sha256trunc) BlockSize() int {
|
|
||||||
return h.sha256.BlockSize()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewTruncated returns a new hash.Hash.
|
|
||||||
func NewTruncated() hash.Hash {
|
|
||||||
return sha256trunc{
|
|
||||||
sha256: sha256.New(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SumTruncated returns the first 20 bytes of SHA256 of the bz.
|
// SumTruncated returns the first 20 bytes of SHA256 of the bz.
|
||||||
func SumTruncated(bz []byte) []byte {
|
func SumTruncated(bz []byte) []byte {
|
||||||
hash := sha256.Sum256(bz)
|
hash := sha256.Sum256(bz)
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
package tmhash_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/sha256"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestHash(t *testing.T) {
|
|
||||||
testVector := []byte("abc")
|
|
||||||
hasher := tmhash.New()
|
|
||||||
_, err := hasher.Write(testVector)
|
|
||||||
require.NoError(t, err)
|
|
||||||
bz := hasher.Sum(nil)
|
|
||||||
|
|
||||||
bz2 := tmhash.Sum(testVector)
|
|
||||||
|
|
||||||
hasher = sha256.New()
|
|
||||||
_, err = hasher.Write(testVector)
|
|
||||||
require.NoError(t, err)
|
|
||||||
bz3 := hasher.Sum(nil)
|
|
||||||
|
|
||||||
assert.Equal(t, bz, bz2)
|
|
||||||
assert.Equal(t, bz, bz3)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHashTruncated(t *testing.T) {
|
|
||||||
testVector := []byte("abc")
|
|
||||||
hasher := tmhash.NewTruncated()
|
|
||||||
_, err := hasher.Write(testVector)
|
|
||||||
require.NoError(t, err)
|
|
||||||
bz := hasher.Sum(nil)
|
|
||||||
|
|
||||||
bz2 := tmhash.SumTruncated(testVector)
|
|
||||||
|
|
||||||
hasher = sha256.New()
|
|
||||||
_, err = hasher.Write(testVector)
|
|
||||||
require.NoError(t, err)
|
|
||||||
bz3 := hasher.Sum(nil)
|
|
||||||
bz3 = bz3[:tmhash.TruncatedSize]
|
|
||||||
|
|
||||||
assert.Equal(t, bz, bz2)
|
|
||||||
assert.Equal(t, bz, bz3)
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
package crypto
|
|
||||||
|
|
||||||
const Version = "0.9.0-dev"
|
|
||||||
@@ -63,7 +63,6 @@ func InjectEvidence(ctx context.Context, logger log.Logger, r *rand.Rand, testne
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
valSet, err := types.ValidatorSetFromExistingValidators(valRes.Validators)
|
valSet, err := types.ValidatorSetFromExistingValidators(valRes.Validators)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -289,8 +288,7 @@ func makeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) types.Bloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func mutateValidatorSet(ctx context.Context, privVals []types.MockPV, vals *types.ValidatorSet,
|
func mutateValidatorSet(ctx context.Context, privVals []types.MockPV, vals *types.ValidatorSet) ([]types.PrivValidator, *types.ValidatorSet, error) {
|
||||||
) ([]types.PrivValidator, *types.ValidatorSet, error) {
|
|
||||||
newVal, newPrivVal, err := factory.Validator(ctx, 10)
|
newVal, newPrivVal, err := factory.Validator(ctx, 10)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
@@ -8,7 +9,6 @@ import (
|
|||||||
"github.com/tendermint/tendermint/crypto/ed25519"
|
"github.com/tendermint/tendermint/crypto/ed25519"
|
||||||
"github.com/tendermint/tendermint/crypto/secp256k1"
|
"github.com/tendermint/tendermint/crypto/secp256k1"
|
||||||
"github.com/tendermint/tendermint/crypto/sr25519"
|
"github.com/tendermint/tendermint/crypto/sr25519"
|
||||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
|
||||||
tmstrings "github.com/tendermint/tendermint/libs/strings"
|
tmstrings "github.com/tendermint/tendermint/libs/strings"
|
||||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||||
)
|
)
|
||||||
@@ -328,8 +328,6 @@ func (params ConsensusParams) ValidateConsensusParams() error {
|
|||||||
// This allows the ConsensusParams to evolve more without breaking the block
|
// This allows the ConsensusParams to evolve more without breaking the block
|
||||||
// protocol. No need for a Merkle tree here, just a small struct to hash.
|
// protocol. No need for a Merkle tree here, just a small struct to hash.
|
||||||
func (params ConsensusParams) HashConsensusParams() []byte {
|
func (params ConsensusParams) HashConsensusParams() []byte {
|
||||||
hasher := tmhash.New()
|
|
||||||
|
|
||||||
hp := tmproto.HashedParams{
|
hp := tmproto.HashedParams{
|
||||||
BlockMaxBytes: params.Block.MaxBytes,
|
BlockMaxBytes: params.Block.MaxBytes,
|
||||||
BlockMaxGas: params.Block.MaxGas,
|
BlockMaxGas: params.Block.MaxGas,
|
||||||
@@ -340,11 +338,9 @@ func (params ConsensusParams) HashConsensusParams() []byte {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = hasher.Write(bz)
|
sum := sha256.Sum256(bz)
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
return sum[:]
|
||||||
}
|
|
||||||
return hasher.Sum(nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (params *ConsensusParams) Equals(params2 *ConsensusParams) bool {
|
func (params *ConsensusParams) Equals(params2 *ConsensusParams) bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user