     1	/*
     2	  My Block Chain: Block & Block Chain Management module
     3	*/
     4	package Block
     5	
     6	import (
     7		"bytes"
     8		"crypto/sha256"
     9		"encoding/binary"
    10		"encoding/json"
    11		"errors"
    12		"fmt"
    13		"math/rand"
    14		"strconv"
    15		"strings"
    16		"sync"
    17		"time"
    18	
    19		"../P2P"
    20	)
    21	
    22	const (
    23		ORPHAN_DELTA  = 300
    24		MAX_POW_COUNT = 60
    25		DIFFICULTY    = "00"
    26		debug_mode    = false
    27	)
    28	
    29	// ブロックの定義
    30	type Block struct {
    31		Hight     int      `json:"hight"`
    32		Prev      string   `json:"prev"`
    33		Hash      string   `json:"hash"`
    34		Nonce     string   `json:"nonce"`
    35		PowCount  int      `json:"powcount"`
    36		Data      string   `json:"data"`
    37		Timestamp int64    `json:"timestamp"`
    38		Child     []*Block // このブロックの子ブロックが入る。分岐が解消されるまではここに以降のブロックが入る
    39		Sibling   []*Block // 同じ親を持つブロック。兄弟ブロックで、この中の１つのみが最終的に残る
    40	}
    41	
    42	// ブロックチェーン管理構造体
    43	type BlockChain struct {
    44		Info           string
    45		p2p            *P2P.P2PNetwork
    46		initialized    bool
    47		mining         bool
    48		blocks         []*Block
    49		last_block     int
    50		fix_block      int
    51		orphan_blocks  []*Block
    52		invalid_blocks []*Block
    53		retry_blocks   []*Block
    54		mu             sync.Mutex
    55	}
    56	
    57	
    58	// Hash計算
    59	func (b *Block) calcHash() string {
    60		return fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprintf("%d%d%s%s%s", b.Hight, b.Prev, b.Nonce, b.PowCount, b.Data, b.Timestamp))))
    61	}
    62	
    63	// Hash計算してブロックに設定
    64	func (b *Block) hash() string {
    65		b.Hash = b.calcHash()
    66		return b.Hash
    67	}
    68	
    69	// ブロック検証
    70	func (b *Block) isValid() bool {
    71	
    72		if debug_mode {
    73			fmt.Println("Hash = ", b.Hash)
    74			fmt.Println("cal Hash = ", b.calcHash())
    75		}
    76	
    77		if b.Hash != b.calcHash() {
    78			return false
    79		}
    80		return true
    81	}
    82	
    83	// マイニング中か判断
    84	func (bc *BlockChain) IsMining() bool {
    85		return bc.mining
    86	}
    87	
    88	// ブロックチェーン管理構造の初期化
    89	func (bc *BlockChain) Init(p2p *P2P.P2PNetwork, first bool) (*BlockChain, error) {
    90		fmt.Println("Block_init")
    91		bc.blocks = make([]*Block, 0)
    92		bc.orphan_blocks = make([]*Block, 0)
    93		bc.invalid_blocks = make([]*Block, 0)
    94		bc.retry_blocks = make([]*Block, 0)
    95		bc.p2p = p2p
    96		bc.initialized = false
    97		bc.mining = false
    98		bc.Info = "My Block Chain Ver0.1"
    99	
   100		if first {
   101			// genesisブロック
   102			genesis_block := new(Block)
   103			genesis_block.Timestamp = 0
   104			genesis_block.Hight = 0
   105			genesis_block.Data = "Genesis Block"
   106			genesis_block.hash()
   107			bc.blocks = append(bc.blocks, genesis_block)
   108		}
   109	
   110		return bc, nil
   111	}
   112	
   113	// ブロックチェーンの同期
   114	func (bc *BlockChain) SyncBlockChain(hight int) error {
   115		/* 隙間のブロックを要求 */
   116		bc.RequestBlock(hight)
   117		time.Sleep(1 * time.Second)
   118		bc.initialized = true
   119		return nil
   120	}
   121	
   122	// 初期化完了し動作可能とする
   123	func (bc *BlockChain) Initialized() error {
   124		bc.initialized = true
   125		return nil
   126	}
   127	
   128	// 初期化完了し動作可能な状態か確認
   129	func (bc *BlockChain) IsInitialized() bool {
   130		return bc.initialized
   131	}
   132	
   133	// ブロック作成(マイニング)
   134	func (bc *BlockChain) Create(data string, pow bool, primary bool) (*Block, error) {
   135	
   136		if debug_mode {
   137			fmt.Println("Create:", data)
   138		}
   139	
   140		block := new(Block)
   141		block.Child = make([]*Block, 0)
   142		block.Sibling = make([]*Block, 0)
   143	
   144		// 競合、フォークを解消するために、一番長いチェーンの後につなげるようにする
   145		last_block := bc.getPrevBlock()
   146	
   147		// ブロックの中身を詰める
   148		block.Prev = last_block.Hash
   149		block.Timestamp = time.Now().UnixNano()
   150		block.Data = data
   151		block.Hight = last_block.Hight + 1
   152	
   153		// PoW
   154		if pow {
   155			/*
   156			Nonceを変えながら、条件を満たすハッシュを計算するループを回す。
   157			実験では、あまり終わらないと大変なので、60回(60秒)やってだめなら、とりえず進むことにする。
   158			*/
   159			for i := 0; i < MAX_POW_COUNT; i++ {
   160				block.Nonce = fmt.Sprintf("%x", rand.New(rand.NewSource(block.Timestamp/int64(i+1))))
   161				block.PowCount = i
   162				block.hash()
   163				if debug_mode {
   164					fmt.Println("Try ", i, block)
   165				} else {
   166					fmt.Println("Try ", i, block.Hash)
   167				}
   168				// 求めたハッシュが条件を満たすか確認する
   169				if strings.HasPrefix(block.Hash, DIFFICULTY) {
   170					fmt.Println("Found!!")
   171					break
   172				}
   173				time.Sleep(1 * time.Second)
   174			}
   175			if primary == false && !strings.HasPrefix(block.Hash, DIFFICULTY) {
   176				return nil, errors.New("Failed to Mine.")
   177			}
   178		} else {
   179			block.hash()
   180		}
   181	
   182		return block, nil
   183	}
   184	
   185	// チェーンの親ブロックを見つける
   186	func (bc *BlockChain) getPrevBlock() *Block {
   187	
   188		// 一番長いチェーンから親を決める
   189		// ロック
   190		bc.mu.Lock()
   191	
   192		last_block := bc.blocks[len(bc.blocks)-1]
   193	
   194		block := last_block
   195		if len(last_block.Sibling) > 0 {
   196			for _, b := range last_block.Sibling {
   197				if len(block.Child) < len(b.Child) {
   198					block = b
   199				}
   200			}
   201		}
   202	
   203		// アンロック
   204		bc.mu.Unlock()
   205	
   206		return block
   207	}
   208	
   209	// ブロックチェーンの整合性確認
   210	func (bc *BlockChain) Check(data []byte) error {
   211		fmt.Println("Checking My Block Chain...")
   212		bc.mu.Lock()
   213		prev := bc.blocks[0]
   214		for i := 1; i < len(bc.blocks); i++ {
   215			fmt.Println(".")
   216			if prev.calcHash() != bc.blocks[i].Prev {
   217				fmt.Println("Invalid Block Found!")
   218				fmt.Println(prev)
   219				bc.invalid_blocks = append(bc.invalid_blocks, prev)
   220			}
   221			prev = bc.blocks[i]
   222		}
   223		bc.mu.Unlock()
   224		fmt.Println("... Done")
   225	
   226		return nil
   227	}
   228	
   229	
   230	// ブロックをチェーンにつなぐ
   231	func (bc *BlockChain) blockAppendSimple(block *Block) error {
   232		if debug_mode {
   233			fmt.Println("blockAppendSimple:", block)
   234		}
   235		// チェーンの最後
   236		last_block := bc.blocks[len(bc.blocks)-1]
   237		// Blockの親がblocksの最後か？
   238		if block.Prev == last_block.Hash {
   239			// つなぐ
   240			bc.blocks = append(bc.blocks, block)
   241		} else if last_block.Prev == block.Prev {
   242			if last_block.Timestamp > block.Timestamp {
   243				// 入れ替え＆last_block解放
   244				bc.blocks[len(bc.blocks)-1] = block
   245				fmt.Println("Purge Block:", last_block)
   246			}
   247		} else if block.Hight > last_block.Hight {
   248			// 親がいなければorphanにつなぐ
   249			bc.orphan_blocks = append(bc.orphan_blocks, block)
   250	
   251			// 隙間があったら、間のブロックの送信を依頼
   252			for i := last_block.Hight + 1; i < block.Hight; i++ {
   253				/* 隙間のブロックを要求 */
   254				bc.RequestBlock(i)
   255				time.Sleep(1 * time.Second / 2)
   256			}
   257		} else {
   258			// それ以外がチェーンに繋げないので破棄
   259			fmt.Println("Purge Block:", block)
   260		}
   261	
   262		return nil
   263	
   264	}
   265	
   266	// ブロックをつなぐ
   267	func (bc *BlockChain) AddBlock(block *Block) error {
   268	
   269		if debug_mode {
   270			fmt.Println("AddBlock:", block)
   271		}
   272	
   273		// ロック
   274		bc.mu.Lock()
   275	
   276		// ブロックをチェーンにつなぐ
   277		err := bc.blockAppendSimple(block)
   278		if err != nil {
   279			// アンロック
   280			bc.mu.Unlock()
   281			return err
   282		}
   283	
   284		// orphan_blocksに繋がっているものの親が繋がったか確認する
   285		last_block := bc.blocks[len(bc.blocks)-1]
   286		for i, b := range bc.orphan_blocks {
   287			if b.Prev == last_block.Hash {
   288				if debug_mode {
   289					fmt.Println("retry")
   290					fmt.Println("list block before")
   291					bc.DumpChain()
   292				}
   293	
   294				// orphan_blocksから外す
   295				bc.orphan_blocks = append(bc.orphan_blocks[:i], bc.orphan_blocks[i+1:]...)
   296	
   297				// ブロックをチェーンにつなぐ
   298				bc.blockAppendSimple(b)
   299				if debug_mode {
   300					fmt.Println(b)
   301					fmt.Println("list block after")
   302					bc.DumpChain()
   303				}
   304			}
   305		}
   306	
   307		// アンロック
   308		bc.mu.Unlock()
   309	
   310		return nil
   311	}
   312	
   313	// ブロックを要求
   314	func (bc *BlockChain) RequestBlock(id int) error {
   315		fmt.Println("RequestBlock:", id)
   316		bid := make([]byte, 4)
   317		binary.LittleEndian.PutUint32(bid, uint32(id))
   318		node := []byte(bc.p2p.Self())
   319		s_msg := append(bid, node...)
   320		fmt.Println(s_msg)
   321		bc.p2p.SendOne(P2P.CMD_SENDBLOCK, s_msg)
   322		return nil
   323	}
   324	
   325	// ハッシュ指定でブロックを取得
   326	func (bc *BlockChain) GetBlock(hash string) *Block {
   327		fmt.Println("GetBlock:", hash)
   328		bc.mu.Lock()
   329		for _, b := range bc.blocks {
   330			fmt.Println(b)
   331			if b.Hash == hash {
   332				bc.mu.Unlock()
   333				fmt.Println("GetBlock: Found", b)
   334				return b
   335			}
   336		}
   337		bc.mu.Unlock()
   338		return nil
   339	}
   340	
   341	// インデックス指定でブロックを取得
   342	func (bc *BlockChain) GetBlockByIndex(index int) *Block {
   343		fmt.Println("GetBlockByIndex:", index)
   344		bc.mu.Lock()
   345		if len(bc.blocks) > index {
   346			b := bc.blocks[index]
   347			bc.mu.Unlock()
   348			fmt.Println("GetBlockByIndex: Found", b)
   349			return b
   350		}
   351		bc.mu.Unlock()
   352		return nil
   353	}
   354	
   355	// データ指定でブロックを取得
   356	func (bc *BlockChain) GetBlockByData(data []byte) *Block {
   357		bc.mu.Lock()
   358		for _, b := range bc.blocks {
   359			if b.Data == string(data) {
   360				bc.mu.Unlock()
   361				fmt.Println("GetBlockByData: Found", b)
   362				return b
   363			}
   364		}
   365		bc.mu.Unlock()
   366		return nil
   367	}
   368	
   369	// ブロック一覧を取得
   370	func (bc *BlockChain) ListBlock() []*Block {
   371		fmt.Println("ListBlock:")
   372		fmt.Println("  blocks->")
   373		bc.mu.Lock()
   374		for _, b := range bc.blocks {
   375			fmt.Println("    ", b)
   376		}
   377		fmt.Println("  orphan_blocks->")
   378		for _, b := range bc.orphan_blocks {
   379			fmt.Println("    ", b)
   380		}
   381		fmt.Println("----------")
   382		bc.mu.Unlock()
   383		return bc.blocks
   384	}
   385	
   386	/***** デバッグ用 *******/
   387	func (bc *BlockChain) DumpChain() {
   388		fmt.Println("----------------")
   389		fmt.Println("Info => ", bc.Info)
   390	
   391		fmt.Println("ListBlock:")
   392		fmt.Println("  blocks->")
   393		for _, b := range bc.blocks {
   394			//fmt.Println("    ", b)
   395			fmt.Println("    ", b.Data)
   396		}
   397		fmt.Println("  orphan_blocks->")
   398		for _, b := range bc.orphan_blocks {
   399			//fmt.Println("    ", b)
   400			fmt.Println("    ", b.Data)
   401		}
   402		fmt.Println("----------------")
   403		return
   404	}
   405	
   406	/************************/
   407	
   408	// 新しいブロックの承認＆追加アクション
   409	func (bc *BlockChain) NewBlock(msg []byte) error {
   410		fmt.Println("new block action")
   411		//     fmt.Println(msg)
   412		//     fmt.Println(string(msg))
   413	
   414		// ブロックを取り出す
   415		block := new(Block)
   416		err := json.Unmarshal(msg, block)
   417		if err != nil {
   418			fmt.Println("Invalid Block.", err)
   419			return errors.New("Invalid Block.")
   420		}
   421		if debug_mode {fmt.Println("block = ", block)}
   422	
   423		// Check
   424		if block.isValid() == false {
   425			/* 不正なブロックなのでつながない */
   426			return errors.New("Invalid Block: ID=" + strconv.FormatInt(int64(block.Hight), 10))
   427		}
   428	
   429		// チェーンにつなぐ
   430		bc.AddBlock(block)
   431	
   432		return nil
   433	}
   434	
   435	// ブロック送信のアクション
   436	func (bc *BlockChain) SendBlock(msg []byte) error {
   437		fmt.Println("send block action")
   438	
   439		if debug_mode {
   440			fmt.Println(msg)
   441		}
   442	
   443		// メッセージ解析
   444		var block_id uint32
   445		buf := bytes.NewReader(msg)
   446		err := binary.Read(buf, binary.LittleEndian, &block_id)
   447		fmt.Println(err)
   448		target := string(msg[4:])
   449		fmt.Println(block_id, target)
   450	
   451		// ブロック取得
   452		block := bc.GetBlockByIndex(int(block_id))
   453		if block == nil {
   454			fmt.Println("Invalid Block ID")
   455			return errors.New("Invalid Block ID:" + strconv.FormatInt(int64(block_id), 10))
   456		}
   457	
   458		// 送信先を特定
   459		srv := strings.Split(target, ":")
   460		port, _ := strconv.Atoi(srv[1])
   461		node := bc.p2p.Search(srv[0], uint16(port))
   462		if node == nil {
   463			fmt.Println("Node NOT Found:" + target)
   464			return errors.New("Node NOT Found:" + target)
   465		}
   466	
   467		// ブロック送信
   468		b, _ := json.Marshal(block)
   469	
   470		if debug_mode {
   471			fmt.Println("block = ", block)
   472			fmt.Println("b = ", b)
   473		}
   474	
   475		// 新しいブロックを要求元サーバに送る
   476		s_msg := append([]byte{byte(P2P.CMD_NEWBLOCK)}, b...)
   477		node.Send(s_msg)
   478	
   479		return nil
   480	}
   481	
   482	// マイニング処理
   483	func (bc *BlockChain) miningBlock(data []byte, primary bool) error {
   484		if debug_mode {
   485			fmt.Println("MiningBlock:", data)
   486		}
   487	
   488		bc.mu.Lock()
   489		if bc.initialized == false {
   490			bc.mu.Unlock()
   491			fmt.Println("Could not start mining.")
   492			return errors.New("Could not start mining.")
   493		}
   494		if bc.mining {
   495			bc.mu.Unlock()
   496			fmt.Println("Someone Mining.")
   497			return errors.New("Someone Mining.")
   498		}
   499		bc.mining = true
   500		bc.mu.Unlock()
   501	
   502		// ブロックに記録するデータ取り出し
   503		d := data
   504	
   505		// マイニング
   506		block, err := bc.Create(string(d), true, primary)
   507		if err == nil {
   508			b, _ := json.Marshal(block)
   509			if debug_mode {
   510				fmt.Println(b)
   511			}
   512			// 全ノードに保存要求を送る
   513			bc.p2p.Broadcast(P2P.CMD_NEWBLOCK, b, true)
   514		}
   515	
   516		bc.mu.Lock()
   517		bc.mining = false
   518		bc.mu.Unlock()
   519		return err
   520	}
   521	
   522	// マイニングアクション
   523	func (bc *BlockChain) MiningBlock(data []byte) error {
   524		return bc.miningBlock(data, false)
   525	}
   526	
   527	// データ保存リクエスト
   528	func (bc *BlockChain) SaveData(data []byte) error {
   529	
   530		fmt.Println("SaveData:", data)
   531	
   532		// 全ノードにマイニング要求を送る
   533		bc.p2p.Broadcast(P2P.CMD_MININGBLOCK, data, false)
   534	
   535		// 自身のマイニング
   536		go bc.miningBlock(data, true)
   537	
   538		return nil
   539	}
   540	
   541	// データ書き換えアクション
   542	func (bc *BlockChain) ModifyData(msg []byte) error {
   543	
   544		fmt.Println("ModifyData:", msg)
   545	
   546		// get hight
   547		var hight uint32
   548		buf := bytes.NewReader(msg)
   549		err := binary.Read(buf, binary.LittleEndian, &hight)
   550		if err != nil {
   551			return errors.New("Invalid request.")
   552		}
   553	
   554		// get data
   555		data := string(msg[4:])
   556		if debug_mode {
   557			fmt.Println(data)
   558		}
   559	
   560		block := new(Block)
   561		target := bc.GetBlockByIndex(int(hight))
   562		if target == nil {
   563			return errors.New("No target Block: ID=" + strconv.FormatInt(int64(hight), 10))
   564		}
   565	
   566		// ブロックの内容をコピー
   567		*block = *target
   568	
   569		// 無理やりデータを変更&チェック
   570		block.Data = data
   571		fmt.Println(block)
   572		if block.isValid() == false {
   573		   // 不正なブロックなので、書き換えをやめる
   574			fmt.Println("Invalid Block!:", block)
   575			return errors.New("Invalid Block: ID=" + strconv.FormatInt(int64(block.Hight), 10))
   576		} else {
   577			// データを書き換え
   578			*target = *block
   579			// 一応全体チェックをかける
   580			d := make([]byte, 4)
   581			bc.Check(d)
   582		}
   583	
   584		return nil
   585	}
   586	
   587	// データ書き換えリクエスト
   588	func (bc *BlockChain) Modify(hight int, data string) error {
   589	
   590		fmt.Println("Modify:", hight, data)
   591	
   592		// メッセージ組み立て
   593		idx := make([]byte, 4)
   594		binary.LittleEndian.PutUint32(idx, uint32(hight))
   595		s_msg := append(idx, data...)
   596		fmt.Println("s_msg = ", s_msg)
   597	
   598		// 全ノードにデータ書き換え要求を送る
   599		bc.p2p.Broadcast(P2P.CMD_MODIFYDATA, s_msg, true)
   600	
   601		return nil
   602	}
