mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-02-26 07:37:20 +00:00
common/bitutil: deprecate XORBytes in favor of stdlib crypto/subtle (#33331)
XORBytes was added to package crypto/subtle in Go 1.20, and it's faster than our bitutil.XORBytes. There is only one use of this function across go-ethereum so we can simply deprecate the custom implementation. --------- Co-authored-by: Felix Lange <fjl@twurst.com>
This commit is contained in:
parent
af47d9b472
commit
31f9c9ff75
3 changed files with 26 additions and 43 deletions
|
|
@ -8,6 +8,7 @@
|
|||
package bitutil
|
||||
|
||||
import (
|
||||
"crypto/subtle"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
|
@ -17,46 +18,16 @@ const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64" |
|
|||
|
||||
// XORBytes xors the bytes in a and b. The destination is assumed to have enough
|
||||
// space. Returns the number of bytes xor'd.
|
||||
//
|
||||
// If dst does not have length at least n,
|
||||
// XORBytes panics without writing anything to dst.
|
||||
//
|
||||
// dst and x or y may overlap exactly or not at all,
|
||||
// otherwise XORBytes may panic.
|
||||
//
|
||||
// Deprecated: use crypto/subtle.XORBytes
|
||||
func XORBytes(dst, a, b []byte) int {
|
||||
if supportsUnaligned {
|
||||
return fastXORBytes(dst, a, b)
|
||||
}
|
||||
return safeXORBytes(dst, a, b)
|
||||
}
|
||||
|
||||
// fastXORBytes xors in bulk. It only works on architectures that support
|
||||
// unaligned read/writes.
|
||||
func fastXORBytes(dst, a, b []byte) int {
|
||||
n := len(a)
|
||||
if len(b) < n {
|
||||
n = len(b)
|
||||
}
|
||||
w := n / wordSize
|
||||
if w > 0 {
|
||||
dw := *(*[]uintptr)(unsafe.Pointer(&dst))
|
||||
aw := *(*[]uintptr)(unsafe.Pointer(&a))
|
||||
bw := *(*[]uintptr)(unsafe.Pointer(&b))
|
||||
for i := 0; i < w; i++ {
|
||||
dw[i] = aw[i] ^ bw[i]
|
||||
}
|
||||
}
|
||||
for i := n - n%wordSize; i < n; i++ {
|
||||
dst[i] = a[i] ^ b[i]
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// safeXORBytes xors one by one. It works on all architectures, independent if
|
||||
// it supports unaligned read/writes or not.
|
||||
func safeXORBytes(dst, a, b []byte) int {
|
||||
n := len(a)
|
||||
if len(b) < n {
|
||||
n = len(b)
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
dst[i] = a[i] ^ b[i]
|
||||
}
|
||||
return n
|
||||
return subtle.XORBytes(dst, a, b)
|
||||
}
|
||||
|
||||
// ANDBytes ands the bytes in a and b. The destination is assumed to have enough
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ func TestXOR(t *testing.T) {
|
|||
d2 := make([]byte, 1023+alignD)[alignD:]
|
||||
|
||||
XORBytes(d1, p, q)
|
||||
safeXORBytes(d2, p, q)
|
||||
naiveXOR(d2, p, q)
|
||||
if !bytes.Equal(d1, d2) {
|
||||
t.Error("not equal", d1, d2)
|
||||
}
|
||||
|
|
@ -38,6 +38,18 @@ func TestXOR(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// naiveXOR xors bytes one by one.
|
||||
func naiveXOR(dst, a, b []byte) int {
|
||||
n := len(a)
|
||||
if len(b) < n {
|
||||
n = len(b)
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
dst[i] = a[i] ^ b[i]
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// Tests that bitwise AND works for various alignments.
|
||||
func TestAND(t *testing.T) {
|
||||
for alignP := 0; alignP < 2; alignP++ {
|
||||
|
|
@ -134,7 +146,7 @@ func benchmarkBaseXOR(b *testing.B, size int) {
|
|||
p, q := make([]byte, size), make([]byte, size)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
safeXORBytes(p, p, q)
|
||||
naiveXOR(p, p, q)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/subtle"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
|
@ -33,7 +34,6 @@ import (
|
|||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/bitutil"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/crypto/ecies"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
|
|
@ -677,6 +677,6 @@ func exportPubkey(pub *ecies.PublicKey) []byte {
|
|||
|
||||
func xor(one, other []byte) (xor []byte) {
|
||||
xor = make([]byte, len(one))
|
||||
bitutil.XORBytes(xor, one, other)
|
||||
subtle.XORBytes(xor, one, other)
|
||||
return xor
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue