@ -0,0 +1,5 @@ |
|||||
|
# slowlorisdb |
||||
|
|
||||
|
Slow and decentralized cryptographically consistent database |
||||
|
|
||||
|
![slowloris](https://04019a5a-a-62cb3a1a-s-sites.googlegroups.com/site/jchristensensdigitalportfolio/slow-loris/IO-moth-eating-frozen-apple-sauce.jpg "slowloris") |
@ -0,0 +1,51 @@ |
|||||
|
package core |
||||
|
|
||||
|
import ( |
||||
|
"bytes" |
||||
|
"crypto/sha256" |
||||
|
) |
||||
|
|
||||
|
// Hash is the type for a hash data packet
|
||||
|
type Hash [32]byte |
||||
|
|
||||
|
// IsZero returns true if the Hash is empty (all zeroes)
|
||||
|
func (h *Hash) IsZero() bool { |
||||
|
z := Hash{} |
||||
|
if bytes.Equal(z[:], h[:]) { |
||||
|
return true |
||||
|
} |
||||
|
return false |
||||
|
} |
||||
|
|
||||
|
// HashBytes performs a hash over a given byte array
|
||||
|
func HashBytes(b []byte) Hash { |
||||
|
h := sha256.Sum256(b) |
||||
|
return h |
||||
|
} |
||||
|
|
||||
|
// PoWData is the interface for the data that have the Nonce parameter to calculate the Proof-of-Work
|
||||
|
type PoWData interface { |
||||
|
Bytes() []byte |
||||
|
GetNonce() uint64 |
||||
|
IncrementNonce() |
||||
|
} |
||||
|
|
||||
|
// CheckPoW verifies the PoW difficulty of a Hash
|
||||
|
func CheckPoW(hash Hash, difficulty int) bool { |
||||
|
var empty [32]byte |
||||
|
if !bytes.Equal(hash[:][0:difficulty], empty[0:difficulty]) { |
||||
|
return false |
||||
|
} |
||||
|
return true |
||||
|
} |
||||
|
|
||||
|
// CalculatePoW calculates the nonce for the given data in order to fit in the current Proof of Work difficulty
|
||||
|
func CalculatePoW(data PoWData, difficulty int) (uint64, error) { |
||||
|
hash := HashBytes(data.Bytes()) |
||||
|
for !CheckPoW(hash, difficulty) { |
||||
|
data.IncrementNonce() |
||||
|
|
||||
|
hash = HashBytes(data.Bytes()) |
||||
|
} |
||||
|
return data.GetNonce(), nil |
||||
|
} |
@ -0,0 +1,54 @@ |
|||||
|
package core |
||||
|
|
||||
|
import ( |
||||
|
"encoding/hex" |
||||
|
"encoding/json" |
||||
|
"testing" |
||||
|
|
||||
|
"github.com/stretchr/testify/assert" |
||||
|
) |
||||
|
|
||||
|
func TestHashBytes(t *testing.T) { |
||||
|
m := []byte("test") |
||||
|
h := HashBytes(m) |
||||
|
assert.Equal(t, hex.EncodeToString(h[:]), "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08") |
||||
|
assert.True(t, !h.IsZero()) |
||||
|
|
||||
|
z := Hash{} |
||||
|
assert.True(t, z.IsZero()) |
||||
|
} |
||||
|
|
||||
|
type testData struct { |
||||
|
Data []byte |
||||
|
Nonce uint64 |
||||
|
} |
||||
|
|
||||
|
func (d *testData) Bytes() []byte { |
||||
|
b, _ := json.Marshal(d) |
||||
|
return b |
||||
|
} |
||||
|
|
||||
|
func (d *testData) GetNonce() uint64 { |
||||
|
return d.Nonce |
||||
|
} |
||||
|
func (d *testData) IncrementNonce() { |
||||
|
d.Nonce++ |
||||
|
} |
||||
|
|
||||
|
func TestPoW(t *testing.T) { |
||||
|
difficulty := 2 |
||||
|
data := &testData{ |
||||
|
Data: []byte("test"), |
||||
|
Nonce: 0, |
||||
|
} |
||||
|
nonce, err := CalculatePoW(data, difficulty) |
||||
|
assert.Nil(t, err) |
||||
|
data.Nonce = nonce |
||||
|
|
||||
|
h := HashBytes(data.Bytes()) |
||||
|
|
||||
|
assert.Equal(t, hex.EncodeToString(h[:]), "0000020881c02f5171b978e74bb710242e95cc67b36416e382118a7ab2a69321") |
||||
|
|
||||
|
// CheckPoW
|
||||
|
assert.True(t, CheckPoW(h, difficulty)) |
||||
|
} |