github.com/deroproject/derosuite@v2.1.6-1.0.20200307070847-0f2e589c7a2b+incompatible/checkpoints/checkpoints.go (about)

     1  // Copyright 2017-2018 DERO Project. All rights reserved.
     2  // Use of this source code in any form is governed by RESEARCH license.
     3  // license can be found in the LICENSE file.
     4  // GPG: 0F39 E425 8C65 3947 702A  8234 08B2 0360 A03A 9DE8
     5  //
     6  //
     7  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
     8  // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     9  // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
    10  // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    11  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    12  // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    13  // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
    14  // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
    15  // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    16  
    17  package checkpoints
    18  
    19  // generate checksums automatically from file mainnet_checksums.dat
    20  
    21  // generate blank file if no testnet checkpoints
    22  //go:generate sh -c "echo package checkpoints > testnet_checksums.go"
    23  //go:generate sh -c "if [ ! -s testnet_checksums.dat ]; then echo var testnet_checksums_base64 = \"\" >> testnet_checksums.go; fi;"
    24  //go:generate sh -c " if [  -s testnet_checksums.dat ]; then echo var testnet_checksums_base64 = \\\x60 >> testnet_checksums.go; fi"
    25  //go:generate sh -c "if [  -s testnet_checksums.dat ]; then base64 -w 80 <  testnet_checksums.dat >> testnet_checksums.go;fi"
    26  //go:generate sh -c "if [  -s testnet_checksums.dat ]; then echo \\\x60 >> testnet_checksums.go;fi "
    27  
    28  //go:generate sh -c "echo // Code generated by go generate DO NOT EDIT. > mainnet_checksums.go"
    29  //go:generate sh -c "echo // This file contains all the mainnet checksums > mainnet_checksums.go"
    30  //go:generate sh -c "echo // please read checkpoints.go comments > mainnet_checksums.go"
    31  //go:generate sh -c "echo package checkpoints >> mainnet_checksums.go"
    32  //go:generate sh -c "echo  >> mainnet_checksums.go"
    33  //go:generate sh -c "echo var mainnet_checksums_base64 = \\\x60 >> mainnet_checksums.go" 
    34  //go:generate sh -c "base64 -w 80 <  mainnet_checksums.dat >> mainnet_checksums.go"
    35  //go:generate sh -c "echo  \\\x60 >> mainnet_checksums.go" 
    36  
    37  import "fmt"
    38  
    39  //import "bytes"
    40  import "io/ioutil"
    41  import "path/filepath"
    42  import "encoding/base64"
    43  
    44  import "github.com/romana/rlog"
    45  import log "github.com/sirupsen/logrus"
    46  import "github.com/armon/go-radix"
    47  
    48  //import "github.com/deroproject/derosuite/crypto"
    49  import "github.com/deroproject/derosuite/globals"
    50  
    51  // this file handles and maintains checkpoints which are used by blockchain to skip some checks on known parts of the chain
    52  // the skipping of the checks can be disabled by command line arguments
    53  
    54  //var mainnet_checkpoints_height uint64 = uint64(len(mainnet_checkpoints) / 32) // each checkpoint is 32 bytes in size
    55  //var testnet_checkpoints_height uint64 = uint64(len(testnet_checkpoints) / 32) // each checkpoint is 32 bytes in size
    56  
    57  var mainnet_checksums_height uint64 = uint64(len(mainnet_checksums) / 32) // each checksum is 32 bytes in size
    58  var testnet_checksums_height uint64 = uint64(len(testnet_checksums) / 32) // each checksum is 32 bytes in size
    59  
    60  var checksum_tree *radix.Tree
    61  
    62  func init() {
    63  	//	rlog.Tracef(1, "Loaded %d checkpoints for mainnet hardcoded", mainnet_checkpoints_height)
    64  	//	rlog.Tracef(1, "Loaded %d checkpoints for testnet hardcoded", testnet_checkpoints_height)
    65  
    66  	rlog.Tracef(1, "Loaded %d checksums for mainnet hardcoded", mainnet_checksums_height)
    67  	rlog.Tracef(1, "Loaded %d checksums for testnet hardcoded", mainnet_checksums_height)
    68  	checksum_tree = radix.New()
    69  }
    70  
    71  var mainnet_checksums = load_base64(mainnet_checksums_base64)
    72  var testnet_checksums = load_base64(testnet_checksums_base64)
    73  
    74  func load_base64(input string) []byte {
    75      
    76      data, err := base64.StdEncoding.DecodeString(input)
    77      if err != nil {
    78          rlog.Tracef(1, "Loaded checksums failed base64 decoding input length %d", len(input))
    79      }
    80      
    81      return data
    82      
    83  }
    84  
    85  // load checkpoints from the data directory
    86  // a line should be printed on console when we are doing this
    87  func LoadCheckPoints(logger *log.Entry) {
    88  	/*
    89  		if globals.IsMainnet() { // load mainnet checkpoints
    90  			data_loaded, err := ioutil.ReadFile(filepath.Join(globals.GetDataDirectory(), "mainnet_checkpoints.dat"))
    91  			if err == nil && uint64(len(data_loaded)%32) == 0 {
    92  				mainnet_checkpoints = data_loaded
    93  				mainnet_checkpoints_height = uint64(len(mainnet_checkpoints) / 32)
    94  				rlog.Tracef(1, "Loaded %d checkpoints for mainnet from file  mainnet_checkpoints.dat", mainnet_checkpoints_height)
    95  				logger.Infof("Loaded %d checkpoints for mainnet from file  mainnet_checkpoints.dat", mainnet_checkpoints_height)
    96  			} else {
    97  				rlog.Warnf("Loading checkpoints for mainnet from file mainnet_checkpoints.dat failed err %s len %d", err, uint64(len(mainnet_checkpoints)))
    98  				if len(data_loaded) > 0 {
    99  					logger.Warnf("Loading checkpoints for mainnet from file mainnet_checkpoints.dat failed err %s len %d", err, uint64(len(mainnet_checkpoints)))
   100  				}
   101  			}
   102  		}
   103  
   104  		if !globals.IsMainnet() { // load testnet checkpoints
   105  			data_loaded, err := ioutil.ReadFile(filepath.Join(globals.GetDataDirectory(), "testnet_checkpoints.dat"))
   106  			if err == nil && uint64(len(data_loaded)%32) == 0 {
   107  				testnet_checkpoints = data_loaded
   108  				testnet_checkpoints_height = uint64(len(testnet_checkpoints) / 32)
   109  				rlog.Tracef(1, "Loaded %d checkpoints for testnet from file  testnet_checkpoints.dat", testnet_checkpoints_height)
   110  				logger.Info(1, "Loaded %d checkpoints for testnet from file  testnet_checkpoints.dat", testnet_checkpoints_height)
   111  			} else {
   112  				rlog.Warnf("Loading checkpoints for testnet from file testnet_checkpoints.dat failed err %s len %d", err, uint64(len(testnet_checkpoints)))
   113  				if len(data_loaded) > 0 {
   114  					logger.Warnf("Loading checkpoints for testnet from file testnet_checkpoints.dat failed err %s len %d", err, uint64(len(testnet_checkpoints)))
   115  				}
   116  			}
   117  		}
   118  	*/
   119  	if globals.IsMainnet() { // load mainnet checksum
   120  		data_loaded, err := ioutil.ReadFile(filepath.Join(globals.GetDataDirectory(), "mainnet_checksums.dat"))
   121  		if err == nil && uint64(len(data_loaded)%32) == 0 {
   122  			mainnet_checksums = data_loaded
   123  			mainnet_checksums_height = uint64(len(mainnet_checksums) / 32)
   124  			rlog.Tracef(1, "Loaded %d checksums for mainnet from file  mainnet_checksum.dat", mainnet_checksums_height)
   125  			logger.Infof("Loaded %d checksums for mainnet from file  mainnet_checksum.dat", mainnet_checksums_height)
   126  		} else {
   127  			rlog.Warnf("Loading checksums for mainnet from file mainnet_checksum.dat failed err %s len %d", err, uint64(len(mainnet_checksums)))
   128  			if len(data_loaded) > 0 {
   129  				logger.Warnf("Loading checksums for mainnet from file mainnet_checksum.dat failed err %s len %d", err, uint64(len(mainnet_checksums)))
   130  			}
   131  		}
   132  	}
   133  
   134  	if !globals.IsMainnet() { // load testnet checksum
   135  		data_loaded, err := ioutil.ReadFile(filepath.Join(globals.GetDataDirectory(), "testnet_checksums.dat"))
   136  		if err == nil && uint64(len(data_loaded)%32) == 0 {
   137  			testnet_checksums = data_loaded
   138  			testnet_checksums_height = uint64(len(testnet_checksums) / 32)
   139  			rlog.Tracef(1, "Loaded %d checksums for testnet from file  testnet_checksum.dat", testnet_checksums_height)
   140  			logger.Infof("Loaded %d checksums for testnet from file  testnet_checksum.dat", testnet_checksums_height)
   141  		} else {
   142  			rlog.Warnf("Loading checksums for testnet from file testnet_checksums.dat failed err %s len %d", err, uint64(len(testnet_checksums)))
   143  			if len(data_loaded) > 0 {
   144  				logger.Warnf("Loading checksums for testnet from file testnet_checksums.dat failed err %s len %d", err, uint64(len(testnet_checksums)))
   145  			}
   146  		}
   147  	}
   148  
   149  	// lets build a trie for checksums for faster lookup
   150  	checksum_tree = radix.New()
   151  	if globals.IsMainnet() {
   152  		for i := uint64(0); i < mainnet_checksums_height; i++ {
   153  			checksum_tree.Insert(string(mainnet_checksums[32*i:32*(i+1)]), nil)
   154  		}
   155  	} else {
   156  		for i := uint64(0); i < testnet_checksums_height; i++ {
   157  			checksum_tree.Insert(string(testnet_checksums[32*i:32*(i+1)]), nil)
   158  		}
   159  	}
   160  
   161  	logger.Debugf("Succesfully built checksum tree count %d", checksum_tree.Len())
   162  
   163  }
   164  
   165  /*
   166  // gives length of currently available checkpoints
   167  func Length() uint64 {
   168  	switch globals.Config.Name {
   169  	case "mainnet":
   170  		return mainnet_checkpoints_height
   171  	case "testnet":
   172  		return testnet_checkpoints_height
   173  	default:
   174  		return 0
   175  	}
   176  
   177  	// we can never reach here
   178  	//return 0
   179  }
   180  */
   181  func ChecksumLength() uint64 {
   182  	switch globals.Config.Name {
   183  	case "mainnet":
   184  		return mainnet_checksums_height
   185  	case "testnet":
   186  		return testnet_checksums_height // no checksums for testnet
   187  	default:
   188  		return 0
   189  	}
   190  
   191  	// we can never reach here
   192  	//return 0
   193  }
   194  
   195  /*
   196  // tell whether a checkpoint is known in the current selected network
   197  func IsCheckPointKnown(hash crypto.Hash, height uint64) (result bool) {
   198  
   199  	var known_hash crypto.Hash
   200  
   201  	switch globals.Config.Name {
   202  	case "mainnet":
   203  		if height < mainnet_checkpoints_height {
   204  			copy(known_hash[:], mainnet_checkpoints[32*height:])
   205  			if known_hash == hash {
   206  				result = true
   207  				return
   208  			}
   209  		}
   210  
   211  	case "testnet":
   212  		if height < testnet_checkpoints_height {
   213  			copy(known_hash[:], testnet_checkpoints[32*height:])
   214  			if known_hash == hash {
   215  				result = true
   216  				return
   217  			}
   218  		}
   219  
   220  	default:
   221  		panic(fmt.Sprintf("Unknown Network \"%s\"", globals.Config.Name))
   222  	}
   223  	return
   224  }
   225  
   226  */
   227  // tell whether a checkpoint is known in the current selected network
   228  func IsCheckSumKnown(hash []byte) (result bool) {
   229  	switch globals.Config.Name {
   230  	case "mainnet":
   231  		if _, ok := checksum_tree.Get(string(hash)); ok {
   232  			return true
   233  		}
   234  
   235  	case "testnet":
   236  		if _, ok := checksum_tree.Get(string(hash)); ok {
   237  			return true
   238  		}
   239  		return false
   240  
   241  	default:
   242  		panic(fmt.Sprintf("Unknown Network \"%s\"", globals.Config.Name))
   243  	}
   244  	return
   245  }