replaced x/text/cases with our own impl.
This commit is contained in:
parent
e4c637b02a
commit
61de064575
11 changed files with 3229 additions and 23 deletions
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/btcsuite/btcd/claimtrie"
|
"github.com/btcsuite/btcd/claimtrie"
|
||||||
"github.com/btcsuite/btcd/claimtrie/change"
|
"github.com/btcsuite/btcd/claimtrie/change"
|
||||||
"github.com/btcsuite/btcd/claimtrie/node"
|
"github.com/btcsuite/btcd/claimtrie/node"
|
||||||
|
"github.com/btcsuite/btcd/claimtrie/normalization"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *BlockChain) SetClaimtrieHeader(block *btcutil.Block, view *UtxoViewpoint) error {
|
func (b *BlockChain) SetClaimtrieHeader(block *btcutil.Block, view *UtxoViewpoint) error {
|
||||||
|
@ -94,11 +95,11 @@ func (h *handler) handleTxIns(ct *claimtrie.ClaimTrie) error {
|
||||||
switch cs.Opcode() {
|
switch cs.Opcode() {
|
||||||
case txscript.OP_CLAIMNAME: // OP code from previous transaction
|
case txscript.OP_CLAIMNAME: // OP code from previous transaction
|
||||||
id = change.NewClaimID(op) // claimID of the previous item now being spent
|
id = change.NewClaimID(op) // claimID of the previous item now being spent
|
||||||
h.spent[id.Key()] = node.NormalizeIfNecessary(name, ct.Height())
|
h.spent[id.Key()] = normalization.NormalizeIfNecessary(name, ct.Height())
|
||||||
err = ct.SpendClaim(name, op, id)
|
err = ct.SpendClaim(name, op, id)
|
||||||
case txscript.OP_UPDATECLAIM:
|
case txscript.OP_UPDATECLAIM:
|
||||||
copy(id[:], cs.ClaimID())
|
copy(id[:], cs.ClaimID())
|
||||||
h.spent[id.Key()] = node.NormalizeIfNecessary(name, ct.Height())
|
h.spent[id.Key()] = normalization.NormalizeIfNecessary(name, ct.Height())
|
||||||
err = ct.SpendClaim(name, op, id)
|
err = ct.SpendClaim(name, op, id)
|
||||||
case txscript.OP_SUPPORTCLAIM:
|
case txscript.OP_SUPPORTCLAIM:
|
||||||
copy(id[:], cs.ClaimID())
|
copy(id[:], cs.ClaimID())
|
||||||
|
@ -138,7 +139,7 @@ func (h *handler) handleTxOuts(ct *claimtrie.ClaimTrie) error {
|
||||||
// that was a safety feature, but it should have rejected the transaction instead
|
// that was a safety feature, but it should have rejected the transaction instead
|
||||||
// TODO: reject transactions with invalid update commands
|
// TODO: reject transactions with invalid update commands
|
||||||
copy(id[:], cs.ClaimID())
|
copy(id[:], cs.ClaimID())
|
||||||
normName := node.NormalizeIfNecessary(name, ct.Height())
|
normName := normalization.NormalizeIfNecessary(name, ct.Height())
|
||||||
if !bytes.Equal(h.spent[id.Key()], normName) {
|
if !bytes.Equal(h.spent[id.Key()], normName) {
|
||||||
node.LogOnce(fmt.Sprintf("Invalid update operation: name or ID mismatch at %d for: %s, %s",
|
node.LogOnce(fmt.Sprintf("Invalid update operation: name or ID mismatch at %d for: %s, %s",
|
||||||
ct.Height(), normName, id.String()))
|
ct.Height(), normName, id.String()))
|
||||||
|
@ -164,7 +165,7 @@ func (b *BlockChain) GetNamesChangedInBlock(height int32) ([]string, error) {
|
||||||
|
|
||||||
func (b *BlockChain) GetClaimsForName(height int32, name string) (string, *node.Node, error) {
|
func (b *BlockChain) GetClaimsForName(height int32, name string) (string, *node.Node, error) {
|
||||||
|
|
||||||
normalizedName := node.NormalizeIfNecessary([]byte(name), height)
|
normalizedName := normalization.NormalizeIfNecessary([]byte(name), height)
|
||||||
|
|
||||||
b.chainLock.RLock()
|
b.chainLock.RLock()
|
||||||
defer b.chainLock.RUnlock()
|
defer b.chainLock.RUnlock()
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/btcsuite/btcd/claimtrie/merkletrie/merkletrierepo"
|
"github.com/btcsuite/btcd/claimtrie/merkletrie/merkletrierepo"
|
||||||
"github.com/btcsuite/btcd/claimtrie/node"
|
"github.com/btcsuite/btcd/claimtrie/node"
|
||||||
"github.com/btcsuite/btcd/claimtrie/node/noderepo"
|
"github.com/btcsuite/btcd/claimtrie/node/noderepo"
|
||||||
|
"github.com/btcsuite/btcd/claimtrie/normalization"
|
||||||
"github.com/btcsuite/btcd/claimtrie/param"
|
"github.com/btcsuite/btcd/claimtrie/param"
|
||||||
"github.com/btcsuite/btcd/claimtrie/temporal"
|
"github.com/btcsuite/btcd/claimtrie/temporal"
|
||||||
"github.com/btcsuite/btcd/claimtrie/temporal/temporalrepo"
|
"github.com/btcsuite/btcd/claimtrie/temporal/temporalrepo"
|
||||||
|
@ -250,7 +251,7 @@ func (ct *ClaimTrie) AppendBlock() error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
newName := node.NormalizeIfNecessary(nhn.Name, nhn.Next)
|
newName := normalization.NormalizeIfNecessary(nhn.Name, nhn.Next)
|
||||||
updateNames = append(updateNames, newName)
|
updateNames = append(updateNames, newName)
|
||||||
updateHeights = append(updateHeights, nhn.Next)
|
updateHeights = append(updateHeights, nhn.Next)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/claimtrie/change"
|
"github.com/btcsuite/btcd/claimtrie/change"
|
||||||
|
"github.com/btcsuite/btcd/claimtrie/normalization"
|
||||||
"github.com/btcsuite/btcd/claimtrie/param"
|
"github.com/btcsuite/btcd/claimtrie/param"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ func NewNormalizingManager(baseManager Manager) Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (nm *NormalizingManager) AppendChange(chg change.Change) {
|
func (nm *NormalizingManager) AppendChange(chg change.Change) {
|
||||||
chg.Name = NormalizeIfNecessary(chg.Name, chg.Height)
|
chg.Name = normalization.NormalizeIfNecessary(chg.Name, chg.Height)
|
||||||
nm.Manager.AppendChange(chg)
|
nm.Manager.AppendChange(chg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ func (nm *NormalizingManager) addNormalizationForkChangesIfNecessary(height int3
|
||||||
// the original code had an unfortunate bug where many unnecessary takeovers
|
// the original code had an unfortunate bug where many unnecessary takeovers
|
||||||
// were triggered at the normalization fork
|
// were triggered at the normalization fork
|
||||||
predicate := func(name []byte) bool {
|
predicate := func(name []byte) bool {
|
||||||
norm := Normalize(name)
|
norm := normalization.Normalize(name)
|
||||||
eq := bytes.Equal(name, norm)
|
eq := bytes.Equal(name, norm)
|
||||||
if eq {
|
if eq {
|
||||||
return true
|
return true
|
||||||
|
|
1574
claimtrie/normalization/CaseFolding_v11.txt
Normal file
1574
claimtrie/normalization/CaseFolding_v11.txt
Normal file
File diff suppressed because it is too large
Load diff
1584
claimtrie/normalization/CaseFolding_v13.txt
Normal file
1584
claimtrie/normalization/CaseFolding_v13.txt
Normal file
File diff suppressed because it is too large
Load diff
52
claimtrie/normalization/case_folder.go
Normal file
52
claimtrie/normalization/case_folder.go
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
package normalization
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
_ "embed"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed CaseFolding_v11.txt
|
||||||
|
var v11 string
|
||||||
|
|
||||||
|
var foldMap map[rune][]rune
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
foldMap = map[rune][]rune{}
|
||||||
|
r, _ := regexp.Compile(`([[:xdigit:]]+?); (.); ([[:xdigit:] ]+?);`)
|
||||||
|
matches := r.FindAllStringSubmatch(v11, 1000000000)
|
||||||
|
for i := range matches {
|
||||||
|
if matches[i][2] == "C" || matches[i][2] == "F" {
|
||||||
|
key, _ := strconv.Unquote(`"\u` + matches[i][1] + `"`)
|
||||||
|
splits := strings.Split(matches[i][3], " ")
|
||||||
|
var values []rune
|
||||||
|
for j := range splits {
|
||||||
|
value, _ := strconv.Unquote(`"\u` + splits[j] + `"`)
|
||||||
|
values = append(values, []rune(value)[0])
|
||||||
|
}
|
||||||
|
foldMap[[]rune(key)[0]] = values
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CaseFold(name []byte) []byte {
|
||||||
|
var b bytes.Buffer
|
||||||
|
b.Grow(len(name))
|
||||||
|
for _, r := range string(name) {
|
||||||
|
if r == utf8.RuneError {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
replacements := foldMap[r]
|
||||||
|
if len(replacements) > 0 {
|
||||||
|
for j := range replacements {
|
||||||
|
b.WriteRune(replacements[j])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
b.WriteRune(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b.Bytes()
|
||||||
|
}
|
|
@ -1,17 +1,10 @@
|
||||||
package node
|
package normalization
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/btcsuite/btcd/claimtrie/param"
|
"github.com/btcsuite/btcd/claimtrie/param"
|
||||||
"golang.org/x/text/cases"
|
|
||||||
"golang.org/x/text/unicode/norm"
|
"golang.org/x/text/unicode/norm"
|
||||||
)
|
)
|
||||||
|
|
||||||
//func init() {
|
|
||||||
// if cases.UnicodeVersion[:2] != "11" {
|
|
||||||
// panic("Wrong unicode version!")
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
var Normalize = normalizeGo
|
var Normalize = normalizeGo
|
||||||
|
|
||||||
func NormalizeIfNecessary(name []byte, height int32) []byte {
|
func NormalizeIfNecessary(name []byte, height int32) []byte {
|
||||||
|
@ -21,10 +14,9 @@ func NormalizeIfNecessary(name []byte, height int32) []byte {
|
||||||
return Normalize(name)
|
return Normalize(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
var folder = cases.Fold()
|
|
||||||
|
|
||||||
func normalizeGo(value []byte) []byte {
|
func normalizeGo(value []byte) []byte {
|
||||||
|
|
||||||
normalized := norm.NFD.Bytes(value)
|
normalized := norm.NFD.Bytes(value) // may need to hard-code the version on this
|
||||||
return folder.Bytes(normalized)
|
// not using x/text/cases because it does too good of a job; it seems to use v14 tables even when it claims v13
|
||||||
|
return CaseFold(normalized)
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
// +build use_icu_normalization
|
// +build use_icu_normalization
|
||||||
|
|
||||||
package node
|
package normalization
|
||||||
|
|
||||||
// #cgo CFLAGS: -O2
|
// #cgo CFLAGS: -O2
|
||||||
// #cgo LDFLAGS: -licuio -licui18n -licuuc -licudata
|
// #cgo LDFLAGS: -licuio -licui18n -licuuc -licudata
|
|
@ -1,6 +1,6 @@
|
||||||
// +build use_icu_normalization
|
// +build use_icu_normalization
|
||||||
|
|
||||||
package node
|
package normalization
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
|
@ -1,4 +1,4 @@
|
||||||
package node
|
package normalization
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/rand"
|
"math/rand"
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/btcsuite/btcd/btcjson"
|
"github.com/btcsuite/btcd/btcjson"
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/claimtrie/node"
|
"github.com/btcsuite/btcd/claimtrie/node"
|
||||||
|
"github.com/btcsuite/btcd/claimtrie/normalization"
|
||||||
"github.com/btcsuite/btcd/database"
|
"github.com/btcsuite/btcd/database"
|
||||||
"github.com/btcsuite/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
@ -336,7 +337,7 @@ func lookupValue(s *rpcServer, outpoint wire.OutPoint, includeValues *bool) (str
|
||||||
func handleGetNormalized(_ *rpcServer, cmd interface{}, _ <-chan struct{}) (interface{}, error) {
|
func handleGetNormalized(_ *rpcServer, cmd interface{}, _ <-chan struct{}) (interface{}, error) {
|
||||||
c := cmd.(*btcjson.GetNormalizedCmd)
|
c := cmd.(*btcjson.GetNormalizedCmd)
|
||||||
r := btcjson.GetNormalizedResult{
|
r := btcjson.GetNormalizedResult{
|
||||||
NormalizedName: string(node.Normalize([]byte(c.Name))),
|
NormalizedName: string(normalization.Normalize([]byte(c.Name))),
|
||||||
}
|
}
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue