From 01dbe17d8bef8366c40d9dd0fd3d540f7a4c5989 Mon Sep 17 00:00:00 2001 From: b00f Date: Wed, 20 Nov 2024 14:52:15 +0800 Subject: [PATCH] fix(crypto, state): resolve panic on 32-bit OSes (#1604) --- go.mod | 2 +- go.sum | 8 ++---- state/state.go | 8 +++--- util/persistentmerkle/merkle.go | 38 ++++++++++++++-------------- util/persistentmerkle/merkle_test.go | 30 +++++++++++----------- 5 files changed, 41 insertions(+), 45 deletions(-) diff --git a/go.mod b/go.mod index f8199dd7f..412225f70 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/inancgumus/screen v0.0.0-20190314163918-06e984b86ed3 github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 - github.com/kilic/bls12-381 v0.1.0 + github.com/kilic/bls12-381 v0.1.1-0.20210503002446-7b7597926c69 github.com/libp2p/go-libp2p v0.37.0 github.com/libp2p/go-libp2p-kad-dht v0.28.1 github.com/libp2p/go-libp2p-pubsub v0.12.0 diff --git a/go.sum b/go.sum index cbdbd7603..38b73d9f9 100644 --- a/go.sum +++ b/go.sum @@ -30,7 +30,6 @@ github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7 github.com/c-bata/go-prompt v0.2.6 h1:POP+nrHE+DfLYx370bedwNhsqmpCUynWPxuHi0C5vZI= github.com/c-bata/go-prompt v0.2.6/go.mod h1:/LMAke8wD2FsNu9EXNdHxNLbd9MedkPnCdfpU9wwHfY= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM= @@ -114,7 +113,6 @@ github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ4 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= @@ -226,7 +224,6 @@ github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= github.com/ipfs/go-ipfs-util v0.0.3 h1:2RFdGez6bu2ZlZdI+rWfIdbQb1KudQp3VGwPtdNCmE0= github.com/ipfs/go-ipfs-util v0.0.3/go.mod h1:LHzG1a0Ig4G+iZ26UUOMjHd+lfM84LZCrn17xAKWBvs= -github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8= github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= github.com/ipfs/go-test v0.0.4 h1:DKT66T6GBB6PsDFLoO56QZPrOmzJkqU1FZH5C9ySkew= @@ -247,8 +244,8 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 h1:qGQQKEcAR99REcMpsXCp3lJ03zYT1PkRd3kQGPn9GVg= github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw= -github.com/kilic/bls12-381 v0.1.0 h1:encrdjqKMEvabVQ7qYOKu1OvhqpK4s47wDYtNiPtlp4= -github.com/kilic/bls12-381 v0.1.0/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig= +github.com/kilic/bls12-381 v0.1.1-0.20210503002446-7b7597926c69 h1:kMJlf8z8wUcpyI+FQJIdGjAhfTww1y0AbQEv86bpVQI= +github.com/kilic/bls12-381 v0.1.1-0.20210503002446-7b7597926c69/go.mod h1:tlkavyke+Ac7h8R3gZIjI5LKBcvMlSWnXNMgT3vZXo8= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -704,7 +701,6 @@ golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/state/state.go b/state/state.go index 018335b15..28aa678a6 100644 --- a/state/state.go +++ b/state/state.go @@ -184,7 +184,7 @@ func (st *state) loadMerkels() { panic(fmt.Sprintf( "Account number is out of range: %v >= %v", acc.Number(), totalAccount)) } - st.accountMerkle.SetHash(int(acc.Number()), acc.Hash()) + st.accountMerkle.SetHash(acc.Number(), acc.Hash()) return false }) @@ -196,7 +196,7 @@ func (st *state) loadMerkels() { panic(fmt.Sprintf( "Validator number is out of range: %v >= %v", val.Number(), totalValidator)) } - st.validatorMerkle.SetHash(int(val.Number()), val.Hash()) + st.validatorMerkle.SetHash(val.Number(), val.Hash()) return false }) @@ -529,14 +529,14 @@ func (st *state) commitSandbox(sbx sandbox.Sandbox, round int16) { sbx.IterateAccounts(func(addr crypto.Address, acc *account.Account, updated bool) { if updated { st.store.UpdateAccount(addr, acc) - st.accountMerkle.SetHash(int(acc.Number()), acc.Hash()) + st.accountMerkle.SetHash(acc.Number(), acc.Hash()) } }) sbx.IterateValidators(func(val *validator.Validator, updated bool, _ bool) { if updated { st.store.UpdateValidator(val) - st.validatorMerkle.SetHash(int(val.Number()), val.Hash()) + st.validatorMerkle.SetHash(val.Number(), val.Hash()) } }) diff --git a/util/persistentmerkle/merkle.go b/util/persistentmerkle/merkle.go index 3021f8744..1a5298a3c 100644 --- a/util/persistentmerkle/merkle.go +++ b/util/persistentmerkle/merkle.go @@ -7,14 +7,14 @@ import ( ) type Tree struct { - nodes map[int]*node - maxWidth int - maxHeight int + nodes map[uint32]*node + maxWidth int32 + maxHeight int32 } type node struct { - width int - height int + width int32 + height int32 hash *hash.Hash } @@ -24,30 +24,30 @@ type node struct { // +-+---+ // h: height // w: width -func nodeID(width, height int) int { - return ((height & 0xff) << 24) | (width & 0xffffff) +func nodeID(width, height int32) uint32 { + return (uint32(height&0xff) << 24) | uint32(width&0xffffff) } func New() *Tree { return &Tree{ - nodes: make(map[int]*node), + nodes: make(map[uint32]*node), } } -func (*Tree) createNode(width, height int) *node { +func (*Tree) createNode(width, height int32) *node { return &node{ width: width, height: height, } } -func (t *Tree) getNode(width, height int) *node { +func (t *Tree) getNode(width, height int32) *node { id := nodeID(width, height) return t.nodes[id] } -func (t *Tree) getOrCreateNode(width, height int) *node { +func (t *Tree) getOrCreateNode(width, height int32) *node { id := nodeID(width, height) node, ok := t.nodes[id] if !ok { @@ -58,36 +58,36 @@ func (t *Tree) getOrCreateNode(width, height int) *node { return node } -func (t *Tree) invalidateNode(width, height int) { +func (t *Tree) invalidateNode(width, height int32) { n := t.getOrCreateNode(width, height) n.hash = nil } -func (t *Tree) recalculateHeight(maxWidth int) { +func (t *Tree) recalculateHeight(maxWidth int32) { if maxWidth > t.maxWidth { t.maxWidth = maxWidth maxHeight := math.Log2(float64(maxWidth)) if math.Remainder(maxHeight, 1.0) != 0 { - t.maxHeight = int(math.Trunc(maxHeight)) + 2 + t.maxHeight = int32(math.Trunc(maxHeight)) + 2 } else { - t.maxHeight = int(math.Trunc(maxHeight)) + 1 + t.maxHeight = int32(math.Trunc(maxHeight)) + 1 } } } -func (t *Tree) SetData(leaf int, data []byte) { +func (t *Tree) SetData(leaf int32, data []byte) { t.SetHash(leaf, hash.CalcHash(data)) } -func (t *Tree) SetHash(leaf int, h hash.Hash) { +func (t *Tree) SetHash(leaf int32, h hash.Hash) { t.recalculateHeight(leaf + 1) node := t.getOrCreateNode(leaf, 0) node.hash = &h w := leaf / 2 - for h := 1; h < t.maxHeight; h++ { + for h := int32(1); h < t.maxHeight; h++ { t.invalidateNode(w, h) w /= 2 } @@ -97,7 +97,7 @@ func (t *Tree) Root() hash.Hash { return t.nodeHash(0, t.maxHeight-1) } -func (t *Tree) nodeHash(width, height int) hash.Hash { +func (t *Tree) nodeHash(width, height int32) hash.Hash { node := t.getNode(width, height) if node == nil { node = t.getNode(width-1, height) diff --git a/util/persistentmerkle/merkle_test.go b/util/persistentmerkle/merkle_test.go index e07df1bbb..38cb74525 100644 --- a/util/persistentmerkle/merkle_test.go +++ b/util/persistentmerkle/merkle_test.go @@ -8,38 +8,38 @@ import ( ) func TestNodeID(t *testing.T) { - assert.Equal(t, 0x00000000, nodeID(0, 0)) - assert.Equal(t, 0x01000000, nodeID(0, 1)) - assert.Equal(t, 0x00000001, nodeID(1, 0)) - assert.Equal(t, 0x01000001, nodeID(1, 1)) - assert.Equal(t, 0xffffffff, nodeID(0xffffff, 0xff)) - assert.Equal(t, 0x00ffffff, nodeID(0xffffff, 0x00)) - assert.Equal(t, 0x77ff00ff, nodeID(0xff00ff, 0x77)) + assert.Equal(t, uint32(0x00000000), nodeID(0, 0)) + assert.Equal(t, uint32(0x01000000), nodeID(0, 1)) + assert.Equal(t, uint32(0x00000001), nodeID(1, 0)) + assert.Equal(t, uint32(0x01000001), nodeID(1, 1)) + assert.Equal(t, uint32(0xffffffff), nodeID(0xffffff, 0xff)) + assert.Equal(t, uint32(0x00ffffff), nodeID(0xffffff, 0x00)) + assert.Equal(t, uint32(0x77ff00ff), nodeID(0xff00ff, 0x77)) } func TestCalculateHeight(t *testing.T) { tree := New() tree.recalculateHeight(0) - assert.Equal(t, 0, tree.maxHeight) + assert.Equal(t, int32(0), tree.maxHeight) tree.recalculateHeight(1) - assert.Equal(t, 1, tree.maxHeight) + assert.Equal(t, int32(1), tree.maxHeight) tree.recalculateHeight(2) - assert.Equal(t, 2, tree.maxHeight) + assert.Equal(t, int32(2), tree.maxHeight) tree.recalculateHeight(4) - assert.Equal(t, 3, tree.maxHeight) + assert.Equal(t, int32(3), tree.maxHeight) tree.recalculateHeight(5) - assert.Equal(t, 4, tree.maxHeight) + assert.Equal(t, int32(4), tree.maxHeight) tree.recalculateHeight(8) - assert.Equal(t, 4, tree.maxHeight) + assert.Equal(t, int32(4), tree.maxHeight) tree.recalculateHeight(9) - assert.Equal(t, 5, tree.maxHeight) + assert.Equal(t, int32(5), tree.maxHeight) } func TestMerkleTree(t *testing.T) { @@ -79,7 +79,7 @@ func TestMerkleTree(t *testing.T) { } for i, d := range data { - tree.SetData(i, []byte(d)) + tree.SetData(int32(i), []byte(d)) expected, _ := hex.DecodeString(roots[i]) assert.Equal(t, expected, tree.Root().Bytes(), "Root %d not matched", i) }