derohe-miniblock-mod/block/miniblockdag_test.go
2021-11-08 16:39:17 +00:00

246 lines
7.3 KiB
Go

// Copyright 2017-2018 DERO Project. All rights reserved.
// Use of this source code in any form is governed by RESEARCH license.
// license can be found in the LICENSE file.
// GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8
//
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package block
//import "bytes"
import "testing"
import "crypto/rand"
import "encoding/binary"
import "github.com/deroproject/derohe/cryptography/crypto"
// tests whether the purge is working as it should
func Test_blockmini_purge(t *testing.T) {
c := CreateMiniBlockCollection()
for i := 0; i < 10; i++ {
mbl := MiniBlock{Version: 1, Genesis: true, PastCount: 1}
rand.Read(mbl.Nonce[:]) // fill with randomness
binary.BigEndian.PutUint64(mbl.Check[:], uint64(i))
if err, ok := c.InsertMiniBlock(mbl); !ok {
t.Fatalf("error inserting miniblock err: %s", err)
}
}
c.PurgeHeight(5) // purge all miniblock <= height 5
if len(c.Collection) != 4 {
t.Fatalf("miniblocks not purged")
}
for _, v := range c.Collection {
if v.Height <= 5 {
t.Fatalf("purge not working correctly")
}
}
}
// tests whether collision is working correctly
// also tests whether genesis blocks returns connected always
func Test_blockmini_collision(t *testing.T) {
c := CreateMiniBlockCollection()
mbl := MiniBlock{Version: 1, Genesis: true, PastCount: 1}
rand.Read(mbl.Nonce[:]) // fill with randomness
binary.BigEndian.PutUint64(mbl.Check[:], uint64(8))
if !c.IsConnected(mbl) { // even before inserting it should return connectd
t.Fatalf("genesis blocks are already connected")
}
if err, ok := c.InsertMiniBlock(mbl); !ok {
t.Fatalf("error inserting miniblock err: %s", err)
}
if !c.IsAlreadyInserted(mbl) {
t.Fatalf("already inserted block not detected")
}
if c.IsAlreadyInserted(mbl) != c.IsCollision(mbl) {
t.Fatalf("already inserted block not detected")
}
if !c.IsConnected(mbl) {
t.Fatalf("genesis blocks are already connected")
}
if c.CalculateDistance(mbl) != 0 {
t.Fatalf("genesis blocks should always be 0 distance")
}
}
// tests whether the timestamp sorting is working as it should
//
func Test_blockmini_timestampsorting(t *testing.T) {
for tries := 0; tries < 10000; tries++ {
c := CreateMiniBlockCollection()
total_count := 10
for i := 0; i < total_count; i++ {
mbl := MiniBlock{Version: 1, Genesis: true, PastCount: 1, Timestamp: uint64(256 - i)}
//rand.Read(mbl.Nonce[:]) // fill with randomness
binary.BigEndian.PutUint64(mbl.Check[:], uint64(i))
if err, ok := c.InsertMiniBlock(mbl); !ok {
t.Fatalf("error inserting miniblock err: %s", err)
}
//t.Logf("presorted %+v", mbl)
}
all_genesis := c.GetAllGenesisMiniBlocks()
if len(all_genesis) != total_count {
panic("corruption")
}
sorted_all_genesis := MiniBlocks_SortByTimeAsc(all_genesis)
for i := 0; i < len(sorted_all_genesis)-1; i++ {
//t.Logf("sorted %+v", sorted_all_genesis[i])
if sorted_all_genesis[i].Timestamp > sorted_all_genesis[i+1].Timestamp {
t.Fatalf("sorting of Timestamp failed")
}
}
// insert a miniblock which has timestamp collision
{
mbl := MiniBlock{Version: 1, Genesis: true, PastCount: 1, Timestamp: uint64(254)}
binary.BigEndian.PutUint64(mbl.Check[:], uint64(9900))
if err, ok := c.InsertMiniBlock(mbl); !ok {
t.Fatalf("error inserting miniblock err: %s", err)
}
}
all_genesis = c.GetAllGenesisMiniBlocks()
if len(all_genesis) != (total_count + 1) {
panic("corruption")
}
sorted_all_genesis = MiniBlocks_SortByTimeAsc(all_genesis)
for i := 0; i < len(sorted_all_genesis)-1; i++ {
//t.Logf("sorted %d %+v", sorted_all_genesis[i].GetMiniID(),sorted_all_genesis[i+1])
if sorted_all_genesis[i].Timestamp > sorted_all_genesis[i+1].Timestamp {
t.Fatalf("sorting of Timestamp failed")
}
}
if sorted_all_genesis[total_count-2].Height != 9900 { /// this element will be moved to this, if everything is current
t.Fatalf("test failed %+v", sorted_all_genesis[total_count-2])
}
}
}
// tests whether the distance sorting is working as it should
func Test_blockmini_distancesorting(t *testing.T) {
var unsorted []MiniBlock
total_count := 10
for i := 0; i < total_count; i++ {
mbl := MiniBlock{Version: 1, Genesis: true, PastCount: 1, Timestamp: uint64(256 - i), Distance: uint32(256 - i)}
binary.BigEndian.PutUint64(mbl.Check[:], uint64(i))
unsorted = append(unsorted, mbl)
}
// insert a miniblock which has timestamp and distance collision
{
mbl := MiniBlock{Version: 1, Genesis: true, PastCount: 1, Timestamp: uint64(254), Distance: uint32(254)}
mbl.Height = int64(9900)
unsorted = append(unsorted, mbl)
}
sorted_d := MiniBlocks_SortByDistanceDesc(unsorted)
for i := 0; i < len(sorted_d)-1; i++ {
// t.Logf("sorted %d %d %+v", i, sorted_d[i].GetMiniID(),sorted_d[i])
if sorted_d[i].Distance < sorted_d[i+1].Distance {
t.Fatalf("sorting of Distance failed")
}
}
if sorted_d[3].Height != 9900 { /// this element will be moved to this, if everything is current
t.Fatalf("test failed %+v", sorted_d[3])
}
}
// tests whether filtering is working as it should
func Test_MiniBlocks_Filter(t *testing.T) {
var mbls []MiniBlock
total_count := uint32(10)
for i := uint32(0); i < total_count; i++ {
mbl := MiniBlock{Version: 1, Genesis: true}
if i%2 == 0 {
mbl.PastCount = 1
mbl.Past[0] = i
} else {
mbl.PastCount = 2
mbl.Past[0] = i
mbl.Past[1] = i + 1
}
binary.BigEndian.PutUint64(mbl.Check[:], uint64(i))
mbls = append(mbls, mbl)
}
for i := uint32(0); i < total_count; i++ {
if i%2 == 0 {
result := MiniBlocks_Filter(mbls, []uint32{i})
if len(result) != 1 {
t.Fatalf("failed filter")
}
if result[0].PastCount != 1 || result[0].Past[0] != i {
t.Fatalf("failed filter")
}
} else {
result := MiniBlocks_Filter(mbls, []uint32{i, i + 1})
if len(result) != 1 {
t.Fatalf("failed filter")
}
if result[0].PastCount != 2 || result[0].Past[0] != i || result[0].Past[1] != i+1 {
t.Fatalf("failed filter")
}
}
}
for i := uint32(0); i < total_count; i++ {
if i%2 == 0 {
var tips [1]crypto.Hash
binary.BigEndian.PutUint32(tips[0][:], i)
result := MiniBlocks_FilterOnlyGenesis(mbls, tips[:])
if len(result) != 1 {
t.Fatalf("failed filter")
}
if result[0].PastCount != 1 || result[0].Past[0] != i {
t.Fatalf("failed filter")
}
} else {
var tips [2]crypto.Hash
binary.BigEndian.PutUint32(tips[0][:], i)
binary.BigEndian.PutUint32(tips[1][:], i+1)
result := MiniBlocks_FilterOnlyGenesis(mbls, tips[:])
if len(result) != 1 {
t.Fatalf("failed filter")
}
if result[0].PastCount != 2 || result[0].Past[0] != i || result[0].Past[1] != i+1 {
t.Fatalf("failed filter")
}
}
}
}