mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-21 00:46:32 +00:00
remove PoW from ID
This commit is contained in:
@ -368,11 +368,8 @@ func (n *Node) OnStart() error {
|
||||
n.sw.AddListener(l)
|
||||
|
||||
// Generate node PrivKey
|
||||
// TODO: both the loading function and the target
|
||||
// will need to be configurable
|
||||
difficulty := uint8(16) // number of leading 0s in bitstring
|
||||
target := p2p.MakePoWTarget(difficulty)
|
||||
nodeKey, err := p2p.LoadOrGenNodeKey(n.config.NodeKeyFile(), target)
|
||||
// TODO: the loading function will need to be configurable
|
||||
nodeKey, err := p2p.LoadOrGenNodeKey(n.config.NodeKeyFile())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -381,7 +378,6 @@ func (n *Node) OnStart() error {
|
||||
// Start the switch
|
||||
n.sw.SetNodeInfo(n.makeNodeInfo(nodeKey.PubKey()))
|
||||
n.sw.SetNodeKey(nodeKey)
|
||||
n.sw.SetPeerIDTarget(target)
|
||||
err = n.sw.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
|
64
p2p/key.go
64
p2p/key.go
@ -6,7 +6,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
cmn "github.com/tendermint/tmlibs/common"
|
||||
@ -42,37 +41,20 @@ func (nodeKey *NodeKey) SatisfiesTarget(target []byte) bool {
|
||||
return bytes.Compare(nodeKey.id(), target) < 0
|
||||
}
|
||||
|
||||
// LoadOrGenNodeKey attempts to load the NodeKey from the given filePath,
|
||||
// and checks that the corresponding ID is less than the target.
|
||||
// If the file does not exist, it generates and saves a new NodeKey
|
||||
// with ID less than target.
|
||||
func LoadOrGenNodeKey(filePath string, target []byte) (*NodeKey, error) {
|
||||
// LoadOrGenNodeKey attempts to load the NodeKey from the given filePath.
|
||||
// If the file does not exist, it generates and saves a new NodeKey.
|
||||
func LoadOrGenNodeKey(filePath string) (*NodeKey, error) {
|
||||
if cmn.FileExists(filePath) {
|
||||
nodeKey, err := loadNodeKey(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !nodeKey.SatisfiesTarget(target) {
|
||||
return nil, fmt.Errorf("Loaded ID (%s) does not satisfy target (%X)", nodeKey.ID(), target)
|
||||
}
|
||||
return nodeKey, nil
|
||||
} else {
|
||||
return genNodeKey(filePath, target)
|
||||
return genNodeKey(filePath)
|
||||
}
|
||||
}
|
||||
|
||||
// MakePoWTarget returns a 20 byte target byte array.
|
||||
func MakePoWTarget(difficulty uint8) []byte {
|
||||
zeroPrefixLen := (int(difficulty) / 8)
|
||||
prefix := bytes.Repeat([]byte{0}, zeroPrefixLen)
|
||||
mod := (difficulty % 8)
|
||||
if mod > 0 {
|
||||
nonZeroPrefix := byte(1 << (8 - mod))
|
||||
prefix = append(prefix, nonZeroPrefix)
|
||||
}
|
||||
return append(prefix, bytes.Repeat([]byte{255}, 20-len(prefix))...)
|
||||
}
|
||||
|
||||
func loadNodeKey(filePath string) (*NodeKey, error) {
|
||||
jsonBytes, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
@ -86,8 +68,8 @@ func loadNodeKey(filePath string) (*NodeKey, error) {
|
||||
return nodeKey, nil
|
||||
}
|
||||
|
||||
func genNodeKey(filePath string, target []byte) (*NodeKey, error) {
|
||||
privKey := genPrivKeyEd25519PoW(target).Wrap()
|
||||
func genNodeKey(filePath string) (*NodeKey, error) {
|
||||
privKey := crypto.GenPrivKeyEd25519().Wrap()
|
||||
nodeKey := &NodeKey{
|
||||
PrivKey: privKey,
|
||||
}
|
||||
@ -103,20 +85,26 @@ func genNodeKey(filePath string, target []byte) (*NodeKey, error) {
|
||||
return nodeKey, nil
|
||||
}
|
||||
|
||||
// generate key with address satisfying the difficult target
|
||||
func genPrivKeyEd25519PoW(target []byte) crypto.PrivKeyEd25519 {
|
||||
secret := crypto.CRandBytes(32)
|
||||
var privKey crypto.PrivKeyEd25519
|
||||
for i := 0; ; i++ {
|
||||
privKey = crypto.GenPrivKeyEd25519FromSecret(secret)
|
||||
if bytes.Compare(privKey.PubKey().Address(), target) < 0 {
|
||||
break
|
||||
}
|
||||
z := new(big.Int)
|
||||
z.SetBytes(secret)
|
||||
z = z.Add(z, big.NewInt(1))
|
||||
secret = z.Bytes()
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// MakePoWTarget returns the big-endian encoding of 2^(targetBits - difficulty) - 1.
|
||||
// It can be used as a Proof of Work target.
|
||||
// NOTE: targetBits must be a multiple of 8 and difficulty must be less than targetBits.
|
||||
func MakePoWTarget(difficulty, targetBits uint) []byte {
|
||||
if targetBits%8 != 0 {
|
||||
panic(fmt.Sprintf("targetBits (%d) not a multiple of 8", targetBits))
|
||||
}
|
||||
return privKey
|
||||
if difficulty >= targetBits {
|
||||
panic(fmt.Sprintf("difficulty (%d) >= targetBits (%d)", difficulty, targetBits))
|
||||
}
|
||||
targetBytes := targetBits / 8
|
||||
zeroPrefixLen := (int(difficulty) / 8)
|
||||
prefix := bytes.Repeat([]byte{0}, zeroPrefixLen)
|
||||
mod := (difficulty % 8)
|
||||
if mod > 0 {
|
||||
nonZeroPrefix := byte(1<<(8-mod) - 1)
|
||||
prefix = append(prefix, nonZeroPrefix)
|
||||
}
|
||||
tailLen := int(targetBytes) - len(prefix)
|
||||
return append(prefix, bytes.Repeat([]byte{0xFF}, tailLen)...)
|
||||
}
|
||||
|
@ -13,37 +13,38 @@ import (
|
||||
func TestLoadOrGenNodeKey(t *testing.T) {
|
||||
filePath := filepath.Join(os.TempDir(), cmn.RandStr(12)+"_peer_id.json")
|
||||
|
||||
target := MakePoWTarget(2)
|
||||
nodeKey, err := LoadOrGenNodeKey(filePath, target)
|
||||
nodeKey, err := LoadOrGenNodeKey(filePath)
|
||||
assert.Nil(t, err)
|
||||
|
||||
nodeKey2, err := LoadOrGenNodeKey(filePath, target)
|
||||
nodeKey2, err := LoadOrGenNodeKey(filePath)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, nodeKey, nodeKey2)
|
||||
}
|
||||
|
||||
func repeatBytes(val byte, n int) []byte {
|
||||
return bytes.Repeat([]byte{val}, n)
|
||||
//----------------------------------------------------------
|
||||
|
||||
func padBytes(bz []byte, targetBytes int) []byte {
|
||||
return append(bz, bytes.Repeat([]byte{0xFF}, targetBytes-len(bz))...)
|
||||
}
|
||||
|
||||
func TestPoWTarget(t *testing.T) {
|
||||
|
||||
targetBytes := 20
|
||||
cases := []struct {
|
||||
difficulty uint8
|
||||
difficulty uint
|
||||
target []byte
|
||||
}{
|
||||
{0, bytes.Repeat([]byte{255}, 20)},
|
||||
{1, append([]byte{128}, repeatBytes(255, 19)...)},
|
||||
{8, append([]byte{0}, repeatBytes(255, 19)...)},
|
||||
{9, append([]byte{0, 128}, repeatBytes(255, 18)...)},
|
||||
{10, append([]byte{0, 64}, repeatBytes(255, 18)...)},
|
||||
{16, append([]byte{0, 0}, repeatBytes(255, 18)...)},
|
||||
{17, append([]byte{0, 0, 128}, repeatBytes(255, 17)...)},
|
||||
{0, padBytes([]byte{}, targetBytes)},
|
||||
{1, padBytes([]byte{127}, targetBytes)},
|
||||
{8, padBytes([]byte{0}, targetBytes)},
|
||||
{9, padBytes([]byte{0, 127}, targetBytes)},
|
||||
{10, padBytes([]byte{0, 63}, targetBytes)},
|
||||
{16, padBytes([]byte{0, 0}, targetBytes)},
|
||||
{17, padBytes([]byte{0, 0, 127}, targetBytes)},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
assert.Equal(t, MakePoWTarget(c.difficulty), c.target)
|
||||
assert.Equal(t, MakePoWTarget(c.difficulty, 20*8), c.target)
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user