diff --git a/consensus/eccpow/consensus.go b/consensus/eccpow/consensus.go new file mode 100644 index 0000000000..65cff8079e --- /dev/null +++ b/consensus/eccpow/consensus.go @@ -0,0 +1,540 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package eccpow + +import ( + "bytes" + "errors" + "fmt" + "math/big" + "runtime" + "time" + "github.com/cryptoecc/ETH-ECC/common" + "github.com/cryptoecc/ETH-ECC/consensus" + "github.com/cryptoecc/ETH-ECC/consensus/misc" + "github.com/cryptoecc/ETH-ECC/core/state" + "github.com/cryptoecc/ETH-ECC/core/types" + "github.com/cryptoecc/ETH-ECC/params" + "github.com/cryptoecc/ETH-ECC/rlp" + "github.com/cryptoecc/ETH-ECC/trie" + mapset "github.com/deckarep/golang-set" + "golang.org/x/crypto/sha3" +) + +// ecc proof-of-work protocol constants. +var ( + FrontierBlockReward = big.NewInt(5e+18) // Block reward in wei for successfully mining a block + ByzantiumBlockReward = big.NewInt(3e+18) // Block reward in wei for successfully mining a block upward from Byzantium + ConstantinopleBlockReward = big.NewInt(2e+18) // Block reward in wei for successfully mining a block upward from Constantinople + WorldLandBlockReward = big.NewInt(4e+18) //Block reward in wei for successfully mining a block upward from WorldLand + //WorldLandFirstBlockReward = big.NewInt(9e+18) //Block reward in wei for successfully mining a genesisblock upward from WorldLand + + HALVING_INTERVAL = uint64(6307200) //Block per year * 2year + MATURITY_INTERVAL = uint64(3153600) //Block per year + + SumRewardUntilMaturity = big.NewInt(47304000) //Total supply of token until maturity + + MaxHalving = int64(4) + + maxUncles = 2 // Maximum number of uncles allowed in a single block + allowedFutureBlockTimeSeconds = int64(15) // Max seconds from current time allowed for blocks, before they're considered future blocks + +) + +// Various error messages to mark blocks invalid. These should be private to +// prevent engine specific errors from being referenced in the remainder of the +// codebase, inherently breaking if the engine is swapped out. Please put common +// error types into the consensus package. +var ( + errLargeBlockTime = errors.New("timestamp too big") + errZeroBlockTime = errors.New("timestamp equals parent's") + errTooManyUncles = errors.New("too many uncles") + errDuplicateUncle = errors.New("duplicate uncle") + errUncleIsAncestor = errors.New("uncle is ancestor") + errDanglingUncle = errors.New("uncle's parent is not ancestor") + errInvalidDifficulty = errors.New("non-positive difficulty") + errInvalidMixDigest = errors.New("invalid mix digest") + errInvalidPoW = errors.New("invalid proof-of-work") +) + +// Author implements consensus.Engine, returning the header's coinbase as the +// proof-of-work verified author of the block. +func (ecc *ECC) Author(header *types.Header) (common.Address, error) { + return header.Coinbase, nil +} + +// VerifyHeader checks whether a header conforms to the consensus rules of the +// stock Ethereum ecc engine. +func (ecc *ECC) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { + // If we're running a full engine faking, accept any input as valid + if ecc.config.PowMode == ModeFullFake { + return nil + } + // Short circuit if the header is known, or it's parent not + number := header.Number.Uint64() + if chain.GetHeader(header.Hash(), number) != nil { + return nil + } + parent := chain.GetHeader(header.ParentHash, number-1) + if parent == nil { + return consensus.ErrUnknownAncestor + } + // Sanity checks passed, do a proper verification + return ecc.verifyHeader(chain, header, parent, false, seal, time.Now().Unix()) +} + +// VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers +// concurrently. The method returns a quit channel to abort the operations and +// a results channel to retrieve the async verifications. +func (ecc *ECC) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { + // If we're running a full engine faking, accept any input as valid + if ecc.config.PowMode == ModeFullFake || len(headers) == 0 { + abort, results := make(chan struct{}), make(chan error, len(headers)) + for i := 0; i < len(headers); i++ { + results <- nil + } + return abort, results + } + // Spawn as many workers as allowed threads + workers := runtime.GOMAXPROCS(0) + if len(headers) < workers { + workers = len(headers) + } + + // Create a task channel and spawn the verifiers + var ( + inputs = make(chan int) + done = make(chan int, workers) + errors = make([]error, len(headers)) + abort = make(chan struct{}) + unixNow = time.Now().Unix() + ) + for i := 0; i < workers; i++ { + go func() { + for index := range inputs { + errors[index] = ecc.verifyHeaderWorker(chain, headers, seals, index, unixNow) + done <- index + } + }() + } + + errorsOut := make(chan error, len(headers)) + go func() { + defer close(inputs) + var ( + in, out = 0, 0 + checked = make([]bool, len(headers)) + inputs = inputs + ) + for { + select { + case inputs <- in: + if in++; in == len(headers) { + // Reached end of headers. Stop sending to workers. + inputs = nil + } + case index := <-done: + for checked[index] = true; checked[out]; out++ { + errorsOut <- errors[out] + if out == len(headers)-1 { + return + } + } + case <-abort: + return + } + } + }() + return abort, errorsOut +} + +func (ecc *ECC) verifyHeaderWorker(chain consensus.ChainHeaderReader, headers []*types.Header, seals []bool, index int, unixNow int64) error { + var parent *types.Header + if index == 0 { + parent = chain.GetHeader(headers[0].ParentHash, headers[0].Number.Uint64()-1) + } else if headers[index-1].Hash() == headers[index].ParentHash { + parent = headers[index-1] + } + if parent == nil { + return consensus.ErrUnknownAncestor + } + return ecc.verifyHeader(chain, headers[index], parent, false, seals[index], unixNow) +} + +// VerifyUncles verifies that the given block's uncles conform to the consensus +// rules of the stock Ethereum ecc engine. +func (ecc *ECC) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { + // If we're running a full engine faking, accept any input as valid + if ecc.config.PowMode == ModeFullFake { + return nil + } + // Verify that there are at most 2 uncles included in this block + if len(block.Uncles()) > maxUncles { + return errTooManyUncles + } + if len(block.Uncles()) == 0 { + return nil + } + // Gather the set of past uncles and ancestors + uncles, ancestors := mapset.NewSet(), make(map[common.Hash]*types.Header) + + number, parent := block.NumberU64()-1, block.ParentHash() + + for i := 0; i < 7; i++ { + ancestorHeader := chain.GetHeader(parent, number) + if ancestorHeader == nil { + break + } + ancestors[parent] = ancestorHeader + // If the ancestor doesn't have any uncles, we don't have to iterate them + if ancestorHeader.UncleHash != types.EmptyUncleHash { + // Need to add those uncles to the banned list too + ancestor := chain.GetBlock(parent, number) + if ancestor == nil { + break + } + for _, uncle := range ancestor.Uncles() { + uncles.Add(uncle.Hash()) + } + } + parent, number = ancestorHeader.ParentHash, number-1 + } + ancestors[block.Hash()] = block.Header() + uncles.Add(block.Hash()) + + // Verify each of the uncles that it's recent, but not an ancestor + for _, uncle := range block.Uncles() { + // Make sure every uncle is rewarded only once + hash := uncle.Hash() + if uncles.Contains(hash) { + return errDuplicateUncle + } + uncles.Add(hash) + + // Make sure the uncle has a valid ancestry + if ancestors[hash] != nil { + return errUncleIsAncestor + } + if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == block.ParentHash() { + return errDanglingUncle + } + if err := ecc.verifyHeader(chain, uncle, ancestors[uncle.ParentHash], true, true, time.Now().Unix()); err != nil { + return err + } + } + return nil +} + +// verifyHeader checks whether a header conforms to the consensus rules of the +// stock Ethereum ecc engine. +// See YP section 4.3.4. "Block Header Validity" +func (ecc *ECC) verifyHeader(chain consensus.ChainHeaderReader, header, parent *types.Header, uncle bool, seal bool, unixNow int64) error { + // Ensure that the header's extra-data section is of a reasonable size + if uint64(len(header.Extra)) > params.MaximumExtraDataSize { + return fmt.Errorf("extra-data too long: %d > %d", len(header.Extra), params.MaximumExtraDataSize) + } + // Verify the header's timestamp + if !uncle { + if header.Time > uint64(unixNow+allowedFutureBlockTimeSeconds) { + //log.Println(unixNow) + //log.Println(allowedFutureBlockTimeSeconds) + //log.Println(header.Time) + return consensus.ErrFutureBlock + } + } + + if header.Time <= parent.Time { + return errZeroBlockTime + } + // Verify the block's difficulty based in it's timestamp and parent's difficulty + expectDiff := ecc.CalcDifficulty(chain, header.Time, parent) + + if expectDiff.Cmp(header.Difficulty) != 0 { + return fmt.Errorf("invalid ecc difficulty: have %v, want %v", header.Difficulty, expectDiff) + } + + // Verify that the gas limit is <= 2^63-1 + if header.GasLimit > params.MaxGasLimit { + return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit) + } + // Verify that the gasUsed is <= gasLimit + if header.GasUsed > header.GasLimit { + return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) + } + + // Verify the block's gas usage and (if applicable) verify the base fee. + if !chain.Config().IsLondon(header.Number) { + // Verify BaseFee not present before EIP-1559 fork. + if header.BaseFee != nil { + return fmt.Errorf("invalid baseFee before fork: have %d, expected 'nil'", header.BaseFee) + } + if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil { + return err + } + } else if err := misc.VerifyEip1559Header(chain.Config(), parent, header); err != nil { + // Verify the header's EIP-1559 attributes. + return err + } + // Verify that the block number is parent's +1 + if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 { + return consensus.ErrInvalidNumber + } + // Verify the engine specific seal securing the block + if seal { + if err := ecc.verifySeal(chain, header); err != nil { + return err + } + } + // If all checks passed, validate any special fields for hard forks + if err := misc.VerifyDAOHeaderExtraData(chain.Config(), header); err != nil { + return err + } + if err := misc.VerifyForkHashes(chain.Config(), header, uncle); err != nil { + return err + } + return nil +} + +// CalcDifficulty is the difficulty adjustment algorithm. It returns +// the difficulty that a new block should have when created at time +// given the parent block's time and difficulty. +func (ecc *ECC) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { + next := new(big.Int).Add(parent.Number, big1) + switch { + case chain.Config().IsSeoul(next): + return calcDifficultySeoul(chain, time, parent) + //return calcDifficultyFrontier(time, parent) + default: + //fmt.Println("frontier") + return calcDifficultyFrontier(time, parent) + } + + //return CalcDifficulty(chain.Config(), time, parent) +} + +// CalcDifficulty is the difficulty adjustment algorithm. It returns +// the difficulty that a new block should have when created at time +// given the parent block's time and difficulty. +/*func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int { + next := new(big.Int).Add(parent.Number, big1) + switch { + case config.IsSeoul(next): + return calcDifficultySeoul(time, parent) + default: + //fmt.Println("frontier") + return calcDifficultyFrontier(time, parent) + } +}*/ + +// Some weird constants to avoid constant memory allocs for them. +var ( + expDiffPeriod = big.NewInt(100000) + big1 = big.NewInt(1) + big2 = big.NewInt(2) + big9 = big.NewInt(9) + big10 = big.NewInt(10) + bigMinus99 = big.NewInt(-99) +) + +// makeDifficultyCalculator creates a difficultyCalculator with the given bomb-delay. +// the difficulty is calculated with Byzantium rules, which differs from Homestead in +// how uncles affect the calculation +func makeDifficultyCalculator(bombDelay *big.Int) func(time uint64, parent *types.Header) *big.Int { + return MakeLDPCDifficultyCalculator() +} + +// calcDifficultyFrontier is the difficulty adjustment algorithm. It returns the +// difficulty that a new block should have when created at time given the parent +// block's time and difficulty. The calculation uses the Frontier rules. +func calcDifficultyFrontier(time uint64, parent *types.Header) *big.Int { + difficultyCalculator := MakeLDPCDifficultyCalculator() + return difficultyCalculator(time, parent) +} + +func calcDifficultySeoul(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { + difficultyCalculator := MakeLDPCDifficultyCalculator_Seoul() + //return difficultyCalculator(chain, time, parent) + return difficultyCalculator(time, parent) +} + +// Exported for fuzzing +var FrontierDifficultyCalculator = calcDifficultyFrontier +var DynamicDifficultyCalculator = makeDifficultyCalculator + +// verifySeal checks whether a block satisfies the PoW difficulty requirements, +// either using the usual ecc cache for it, or alternatively using a full DAG +// to make remote mining fast. +func (ecc *ECC) verifySeal(chain consensus.ChainHeaderReader, header *types.Header) error { + // If we're running a fake PoW, accept any seal as valid + if ecc.config.PowMode == ModeFake || ecc.config.PowMode == ModeFullFake { + time.Sleep(ecc.fakeDelay) + if ecc.fakeFail == header.Number.Uint64() { + return errInvalidPoW + } + return nil + } + // If we're running a shared PoW, delegate verification to it + if ecc.shared != nil { + return ecc.shared.verifySeal(chain, header) + } + // Ensure that we have a valid difficulty for the block + if header.Difficulty.Sign() <= 0 { + return errInvalidDifficulty + } + + var ( + digest []byte + flag bool + ) + if chain.Config().IsSeoul(header.Number){ + //fmt.Println("Seoul") + flag, _, _, digest = VerifyOptimizedDecodingSeoul(header, ecc.SealHash(header).Bytes()) + } else{ + flag, _, _, digest = VerifyOptimizedDecoding(header, ecc.SealHash(header).Bytes()) + } + + encodedDigest := common.BytesToHash(digest) + if !bytes.Equal(header.MixDigest[:], encodedDigest[:]) { + return errInvalidMixDigest + } + + if flag == false { + return errInvalidPoW + } + + return nil +} + +// Prepare implements consensus.Engine, initializing the difficulty field of a +// header to conform to the ecc protocol. The changes are done inline. +func (ecc *ECC) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { + parent := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) + if parent == nil { + return consensus.ErrUnknownAncestor + } + header.Difficulty = ecc.CalcDifficulty(chain, header.Time, parent) + + return nil +} + +// Finalize implements consensus.Engine, accumulating the block and uncle rewards, +// setting the final state and assembling the block. +func (ecc *ECC) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) { + // Accumulate any block and uncle rewards and commit the final state root + accumulateRewards(chain.Config(), state, header, uncles) + header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) +} + +func (ecc *ECC) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { + // Accumulate any block and uncle rewards and commit the final state root + ecc.Finalize(chain, header, state, txs, uncles) + + // Header seems complete, assemble into a block and return + return types.NewBlock(header, txs, uncles, receipts, trie.NewStackTrie(nil)), nil +} + +// SealHash returns the hash of a block prior to it being sealed. +func (ecc *ECC) SealHash(header *types.Header) (hash common.Hash) { + hasher := sha3.NewLegacyKeccak256() + + enc := []interface{}{ + header.ParentHash, + header.UncleHash, + header.Coinbase, + header.Root, + header.TxHash, + header.ReceiptHash, + header.Bloom, + header.Difficulty, + header.Number, + header.GasLimit, + header.GasUsed, + header.Time, + header.Extra, + } + if header.BaseFee != nil { + enc = append(enc, header.BaseFee) + } + + rlp.Encode(hasher, enc) + hasher.Sum(hash[:0]) + return hash +} + +// Some weird constants to avoid constant memory allocs for them. +var ( + big8 = big.NewInt(8) + big32 = big.NewInt(32) +) + +// AccumulateRewards credits the coinbase of the given block with the mining +// reward. The total reward consists of the static block reward and rewards for +// included uncles. The coinbase of each uncle block is also rewarded. +func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) { + // Select the correct block reward based on chain progression + var blockReward = big.NewInt(FrontierBlockReward.Int64()) + + //blockReward := FrontierBlockReward + if config.IsByzantium(header.Number) { + blockReward = ByzantiumBlockReward + } + if config.IsConstantinople(header.Number) { + blockReward = ConstantinopleBlockReward + } + if config.IsWorldland(header.Number) { + blockReward = big.NewInt(WorldLandBlockReward.Int64()) + + if config.IsWorldLandHalving(header.Number) { + blockHeight := header.Number.Uint64() + HalvingLevel := (blockHeight - 1 - config.WorldlandBlock.Uint64()) / HALVING_INTERVAL + + blockReward.Rsh(blockReward, uint(HalvingLevel)) + + } else if config.IsWorldLandMaturity(header.Number) { + blockHeight := header.Number.Uint64() + blockReward = big.NewInt(1e+18) + + MaturityLevel := (blockHeight - 1 - config.HalvingEndTime.Uint64()) / MATURITY_INTERVAL + + blockReward.Mul(blockReward, SumRewardUntilMaturity) + blockReward.Div(blockReward, new(big.Int).SetUint64(MATURITY_INTERVAL)) + + blockReward.Mul(blockReward, big.NewInt(4)) + blockReward.Div(blockReward, big.NewInt(100)) + + for i := 0; i < int(MaturityLevel); i++ { + blockReward.Mul(blockReward, big.NewInt(104)) + blockReward.Div(blockReward, big.NewInt(100)) + } + } + } + + // Accumulate the rewards for the miner and any included uncles + reward := new(big.Int).Set(blockReward) + r := new(big.Int) + for _, uncle := range uncles { + r.Add(uncle.Number, big8) + r.Sub(r, header.Number) + r.Mul(r, blockReward) + r.Div(r, big8) + state.AddBalance(uncle.Coinbase, r) + + r.Div(blockReward, big32) + reward.Add(reward, r) + } + state.AddBalance(header.Coinbase, reward) +} diff --git a/consensus/eccpow/consensus_test.go b/consensus/eccpow/consensus_test.go new file mode 100644 index 0000000000..97fb6e78c9 --- /dev/null +++ b/consensus/eccpow/consensus_test.go @@ -0,0 +1,156 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package eccpow + +import ( + "bytes" + "encoding/json" + "fmt" + "math/big" + "os" + "path/filepath" + "testing" + + "github.com/cryptoecc/ETH-ECC/common" + "github.com/cryptoecc/ETH-ECC/common/math" + "github.com/cryptoecc/ETH-ECC/core/types" + "github.com/cryptoecc/ETH-ECC/params" +) + +type diffTest struct { + ParentTimestamp uint64 + ParentDifficulty *big.Int + CurrentTimestamp uint64 + CurrentBlocknumber *big.Int + CurrentDifficulty *big.Int +} + +func (d *diffTest) UnmarshalJSON(b []byte) (err error) { + var ext struct { + ParentTimestamp string + ParentDifficulty string + CurrentTimestamp string + CurrentBlocknumber string + CurrentDifficulty string + } + if err := json.Unmarshal(b, &ext); err != nil { + return err + } + + d.ParentTimestamp = math.MustParseUint64(ext.ParentTimestamp) + d.ParentDifficulty = math.MustParseBig256(ext.ParentDifficulty) + d.CurrentTimestamp = math.MustParseUint64(ext.CurrentTimestamp) + d.CurrentBlocknumber = math.MustParseBig256(ext.CurrentBlocknumber) + d.CurrentDifficulty = math.MustParseBig256(ext.CurrentDifficulty) + + return nil +} + +func TestCalcDifficulty(t *testing.T) { + file, err := os.Open(filepath.Join("..", "..", "tests", "testdata", "BasicTests", "difficulty.json")) + if err != nil { + t.Skip(err) + } + defer file.Close() + + tests := make(map[string]diffTest) + err = json.NewDecoder(file).Decode(&tests) + if err != nil { + t.Fatal(err) + } + + config := ¶ms.ChainConfig{HomesteadBlock: big.NewInt(1150000)} + + for name, test := range tests { + number := new(big.Int).Sub(test.CurrentBlocknumber, big.NewInt(1)) + diff := CalcDifficulty(config, test.CurrentTimestamp, &types.Header{ + Number: number, + Time: test.ParentTimestamp, + Difficulty: test.ParentDifficulty, + }) + if diff.Cmp(test.CurrentDifficulty) != 0 { + t.Error(name, "failed. Expected", test.CurrentDifficulty, "and calculated", diff) + } + } +} + +func TestDecodingVerification(t *testing.T) { + for i := 0; i < 8; i++ { + ecc := ECC{} + header := new(types.Header) + header.Difficulty = ProbToDifficulty(Table[0].miningProb) + hash := ecc.SealHash(header).Bytes() + + _, hashVector, outputWord, LDPCNonce, digest := RunOptimizedConcurrencyLDPC(header, hash) + + headerForTest := types.CopyHeader(header) + headerForTest.MixDigest = common.BytesToHash(digest) + headerForTest.Nonce = types.EncodeNonce(LDPCNonce) + hashForTest := ecc.SealHash(headerForTest).Bytes() + + flag, hashVectorOfVerification, outputWordOfVerification, digestForValidation := VerifyOptimizedDecoding(headerForTest, hashForTest) + + encodedDigestForValidation := common.BytesToHash(digestForValidation) + + //fmt.Printf("%+v\n", header) + //fmt.Printf("Hash : %v\n", hash) + //fmt.Println() + + //fmt.Printf("%+v\n", headerForTest) + //fmt.Printf("headerForTest : %v\n", headerForTest) + //fmt.Println() + + // * means padding for compare easily + if flag && bytes.Equal(headerForTest.MixDigest[:], encodedDigestForValidation[:]) { + fmt.Printf("Hash vector ** ************ : %v\n", hashVector) + fmt.Printf("Hash vector of verification : %v\n", hashVectorOfVerification) + + fmt.Printf("Outputword ** ************ : %v\n", outputWord) + fmt.Printf("Outputword of verification : %v\n", outputWordOfVerification) + + fmt.Printf("LDPC Nonce : %v\n", LDPCNonce) + fmt.Printf("Digest : %v\n", headerForTest.MixDigest[:]) + /* + t.Logf("Hash vector : %v\n", hashVector) + t.Logf("Outputword : %v\n", outputWord) + t.Logf("LDPC Nonce : %v\n", LDPCNonce) + t.Logf("Digest : %v\n", header.MixDigest[:]) + */ + } else { + fmt.Printf("Hash vector ** ************ : %v\n", hashVector) + fmt.Printf("Hash vector of verification : %v\n", hashVectorOfVerification) + + fmt.Printf("Outputword ** ************ : %v\n", outputWord) + fmt.Printf("Outputword of verification : %v\n", outputWordOfVerification) + + fmt.Printf("flag : %v\n", flag) + fmt.Printf("Digest compare result : %v\n", bytes.Equal(headerForTest.MixDigest[:], encodedDigestForValidation[:])) + fmt.Printf("Digest *** ********** : %v\n", headerForTest.MixDigest[:]) + fmt.Printf("Digest for validation : %v\n", encodedDigestForValidation) + + t.Errorf("Test Fail") + /* + t.Errorf("flag : %v\n", flag) + t.Errorf("Digest compare result : %v", bytes.Equal(header.MixDigest[:], digestForValidation) + t.Errorf("Digest : %v\n", digest) + t.Errorf("Digest for validation : %v\n", digestForValidation) + */ + } + //t.Logf("\n") + fmt.Println() + } +}