@ -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)) |
|||
} |