예제 #1
0
func (a *Anchor) checkTxMalleation(transaction *btcutil.Tx, details *btcjson.BlockDetails) {
	anchorLog.Debug("in checkTxMalleation")
	dirBlockInfos := make([]interfaces.IDirBlockInfo, 0, len(a.dirBlockInfoSlice))
	for _, v := range a.dirBlockInfoSlice {
		// find those already anchored but no call back yet
		if v.GetBTCBlockHeight() == 0 && bytes.Compare(v.GetBTCTxHash().Bytes(), primitives.NewZeroHash().Bytes()) != 0 {
			dirBlockInfos = append(dirBlockInfos, v)
		}
	}
	sort.Sort(util.ByDirBlockInfoTimestamp(dirBlockInfos))
	anchorLog.Debugf("malleated tx candidate count=%d, dirBlockInfo list=%s\n", len(dirBlockInfos), spew.Sdump(dirBlockInfos))
	for _, dirBlockInfo := range dirBlockInfos {
		tx, err := a.wclient.GetRawTransaction(toShaHash(dirBlockInfo.GetBTCTxHash()))
		if err != nil {
			anchorLog.Debugf(err.Error())
			continue
		}
		anchorLog.Debugf("GetRawTransaction=%s, dirBlockInfo=%s\n", spew.Sdump(tx), spew.Sdump(dirBlockInfo))
		// compare OP_RETURN
		if reflect.DeepEqual(transaction.MsgTx().TxOut[0], tx.MsgTx().TxOut[0]) {
			anchorLog.Debugf("Tx Malleated: original.txid=%s, malleated.txid=%s\n", dirBlockInfo.GetBTCTxHash().(*primitives.Hash).BTCString(), transaction.Sha().String())
			a.doSaveDirBlockInfo(transaction, details, dirBlockInfo.(*dbInfo.DirBlockInfo), true)
			break
		}
	}
}
예제 #2
0
// build Genesis blocks
func buildGenesisBlocks() error {
	//Set the timestamp for the genesis block
	t, err := time.Parse(time.RFC3339, common.GENESIS_BLK_TIMESTAMP)
	if err != nil {
		panic("Not able to parse the genesis block time stamp")
	}
	dchain.NextBlock.Header.Timestamp = uint32(t.Unix() / 60)

	// Allocate the first two dbentries for ECBlock and Factoid block
	dchain.AddDBEntry(&common.DBEntry{}) // AdminBlock
	dchain.AddDBEntry(&common.DBEntry{}) // ECBlock
	dchain.AddDBEntry(&common.DBEntry{}) // Factoid block

	// Entry Credit Chain
	cBlock := newEntryCreditBlock(ecchain)
	procLog.Debugf("buildGenesisBlocks: cBlock=%s\n", spew.Sdump(cBlock))
	dchain.AddECBlockToDBEntry(cBlock)
	exportECChain(ecchain)

	// Admin chain
	aBlock := newAdminBlock(achain)
	procLog.Debugf("buildGenesisBlocks: aBlock=%s\n", spew.Sdump(aBlock))
	dchain.AddABlockToDBEntry(aBlock)
	exportAChain(achain)

	// factoid Genesis Address
	//fchain.NextBlock = block.GetGenesisFBlock(0, FactoshisPerCredit, 10, 200000000000)
	fchain.NextBlock = block.GetGenesisFBlock()
	FBlock := newFactoidBlock(fchain)
	dchain.AddFBlockToDBEntry(FBlock)
	exportFctChain(fchain)

	// Directory Block chain
	procLog.Debug("in buildGenesisBlocks")
	dbBlock := newDirectoryBlock(dchain)

	// Check block hash if genesis block
	if dbBlock.DBHash.String() != common.GENESIS_DIR_BLOCK_HASH {
		//Panic for Milestone 1
		panic("\nGenesis block hash expected: " + common.GENESIS_DIR_BLOCK_HASH +
			"\nGenesis block hash found:    " + dbBlock.DBHash.String() + "\n")
	}

	exportDChain(dchain)

	// place an anchor into btc
	placeAnchor(dbBlock)

	return nil
}
예제 #3
0
func processAnchorChain() {
	fmt.Println("processAnchorChain")
	//eblocks, _ := db.FetchAllEBlocksByChain(anchorChainID)
	//fmt.Println("anchorChain length: ", len(*eblocks))
	for _, eblock := range *eblocks {
		//fmt.Printf("anchor chain block=%s\n", spew.Sdump(eblock))
		if eblock.Header.EBSequence == 0 {
			continue
		}
		for _, ebEntry := range eblock.Body.EBEntries {
			entry, _ := db.FetchEntryByHash(ebEntry)
			if entry != nil {
				//fmt.Printf("entry=%s\n", spew.Sdump(entry))
				aRecord, err := entryToAnchorRecord(entry)
				if err != nil {
					fmt.Println(err)
				}
				dirBlockInfo, _ := anchorChainToDirBlockInfo(aRecord)
				err = db.InsertDirBlockInfo(dirBlockInfo)
				if err != nil {
					fmt.Printf("InsertDirBlockInfo error: %s, DirBlockInfo=%s\n", err, spew.Sdump(dirBlockInfo))
				}
				dirBlockInfoMap[dirBlockInfo.DBHeight] = dirBlockInfo
			}
		}
	}
}
예제 #4
0
func validateDBSignature(aBlock *common.AdminBlock, dchain *common.DChain) bool {

	dbSigEntry := aBlock.GetDBSignature()
	if dbSigEntry == nil {
		if aBlock.Header.DBHeight == 0 {
			return true
		} else {
			return false
		}
	} else {
		dbSig := dbSigEntry.(*common.DBSignatureEntry)
		if serverPubKey.String() != dbSig.PubKey.String() {
			return false
		} else {
			// obtain the previous directory block
			dblk := dchain.Blocks[aBlock.Header.DBHeight-1]
			if dblk == nil {
				return false
			} else {
				// validatet the signature
				bHeader, _ := dblk.Header.MarshalBinary()
				if !serverPubKey.Verify(bHeader, (*[64]byte)(dbSig.PrevDBSig)) {
					procLog.Infof("No valid signature found in Admin Block = %s\n", spew.Sdump(aBlock))
					return false
				}
			}
		}
	}

	return true
}
예제 #5
0
func (a *Anchor) checkMissingDirBlockInfo() {
	anchorLog.Debug("checkMissingDirBlockInfo for those unsaved DirBlocks in database")
	dblocks, _ := a.db.FetchAllDBlocks()
	dirBlockInfos, _ := a.db.FetchAllDirBlockInfos() //FetchAllDirBlockInfos()
	for _, dblock := range dblocks {
		var found = false
		for i, dbinfo := range dirBlockInfos {
			if dbinfo.GetDatabaseHeight() == dblock.GetDatabaseHeight() {
				dirBlockInfos = append(dirBlockInfos[:i], dirBlockInfos[i+1:]...)
				found = true
				break
			}
		}
		if !found {
			if dblock.GetKeyMR() == nil || bytes.Compare(dblock.GetKeyMR().Bytes(), primitives.NewZeroHash().Bytes()) == 0 {
				dblock.BuildKeyMerkleRoot()
			}
			dirBlockInfo := dbInfo.NewDirBlockInfoFromDirBlock(dblock)
			dirBlockInfo.SetTimestamp(primitives.NewTimestampNow())
			anchorLog.Debug("add missing dirBlockInfo to map: ", spew.Sdump(dirBlockInfo))
			a.db.SaveDirBlockInfo(dirBlockInfo)
			a.dirBlockInfoSlice = append(a.dirBlockInfoSlice, dirBlockInfo)
		}
	}
}
예제 #6
0
// processAcknowledgement validates the ack and adds it to processlist
func processAcknowledgement(msg *wire.MsgAcknowledgement) error {
	// Error condiftion for Milestone 1
	if nodeMode == common.SERVER_NODE {
		return errors.New("Server received msg:" + msg.Command())
	}

	// Validate the signiture
	bytes, err := msg.GetBinaryForSignature()
	if err != nil {
		return err
	}
	if !serverPubKey.Verify(bytes, &msg.Signature) {
		return errors.New(fmt.Sprintf("Invalid signature in Ack = %s\n", spew.Sdump(msg)))
	}

	// Update the next block height in dchain
	if msg.Height > dchain.NextDBHeight {
		dchain.NextDBHeight = msg.Height
	}

	// Update the next block height in db
	if int64(msg.Height) > db.FetchNextBlockHeightCache() {
		db.UpdateNextBlockHeightCache(msg.Height)
	}

	return nil
}
예제 #7
0
func saveDirBlockInfo(transaction *btcutil.Tx, details *btcjson.BlockDetails) {
	anchorLog.Debug("in saveDirBlockInfo")
	var saved = false
	for _, dirBlockInfo := range dirBlockInfoMap {
		if bytes.Compare(dirBlockInfo.BTCTxHash.Bytes(), transaction.Sha().Bytes()) == 0 {
			dirBlockInfo.BTCTxOffset = int32(details.Index)
			dirBlockInfo.BTCBlockHeight = details.Height
			btcBlockHash, _ := wire.NewShaHashFromStr(details.Hash)
			dirBlockInfo.BTCBlockHash = toHash(btcBlockHash)
			dirBlockInfo.BTCConfirmed = true
			db.InsertDirBlockInfo(dirBlockInfo)
			delete(dirBlockInfoMap, dirBlockInfo.DBMerkleRoot.String())
			anchorLog.Infof("In saveDirBlockInfo, dirBlockInfo:%s saved to db\n", spew.Sdump(dirBlockInfo))
			saved = true

			anchorRec := new(AnchorRecord)
			anchorRec.AnchorRecordVer = 1
			anchorRec.DBHeight = dirBlockInfo.DBHeight
			anchorRec.KeyMR = dirBlockInfo.DBMerkleRoot.String()
			_, recordHeight, _ := db.FetchBlockHeightCache()
			anchorRec.RecordHeight = uint32(recordHeight)
			anchorRec.Bitcoin.Address = defaultAddress.String()
			anchorRec.Bitcoin.TXID = transaction.Sha().String()
			anchorRec.Bitcoin.BlockHeight = details.Height
			anchorRec.Bitcoin.BlockHash = details.Hash
			anchorRec.Bitcoin.Offset = int32(details.Index)
			anchorLog.Info("anchor.record saved: " + spew.Sdump(anchorRec))

			err := submitEntryToAnchorChain(anchorRec)
			if err != nil {
				anchorLog.Error("Error in writing anchor into anchor chain: ", err.Error())
			}
			break
		}
	}
	// This happends when there's a double spending (for dir block 122 and its btc tx)
	// (see https://www.blocktrail.com/BTC/tx/ac82f4173259494b22f4987f1e18608f38f1ff756fb4a3c637dfb5565aa5e6cf)
	// or tx mutation / malleated
	// In this case, it will end up being re-anchored.
	if !saved {
		anchorLog.Info("Not saved to db: btc.tx=%s\n blockDetails=%s\n", spew.Sdump(transaction), spew.Sdump(details))
	}
}
예제 #8
0
func (a *Anchor) checkForAnchor() {
	timeNow := time.Now().Unix()
	time0 := 60 * 60 * a.reAnchorAfter
	// anchor the latest dir block first
	sort.Sort(sort.Reverse(util.ByDirBlockInfoTimestamp(a.dirBlockInfoSlice)))
	for _, dirBlockInfo := range a.dirBlockInfoSlice {
		if bytes.Compare(dirBlockInfo.GetBTCTxHash().Bytes(), primitives.NewZeroHash().Bytes()) == 0 {
			anchorLog.Debug("first time anchor: ", spew.Sdump(dirBlockInfo))
			a.SendRawTransactionToBTC(dirBlockInfo.GetDBMerkleRoot(), dirBlockInfo.GetDBHeight())
		} else {
			// This is the re-anchor case for the missed callback of malleated tx
			lapse := timeNow - dirBlockInfo.GetTimestamp().GetTimeSeconds()
			if lapse > int64(time0) {
				anchorLog.Debugf("re-anchor: time lapse=%d, %s\n", lapse, spew.Sdump(dirBlockInfo))
				a.SendRawTransactionToBTC(dirBlockInfo.GetDBMerkleRoot(), dirBlockInfo.GetDBHeight())
			}
		}
	}
}
예제 #9
0
// Serve the "fast lane" incoming control msg from inCtlMsgQueue
func serveCtlMsgRequest(msg wire.FtmInternalMsg) error {

	switch msg.Command() {
	case wire.CmdCommitChain:

	default:
		return errors.New("1 Message type unsupported:" + spew.Sdump(msg))
	}
	return nil

}
예제 #10
0
func (a *Anchor) checkConfirmations(dirBlockInfo *dbInfo.DirBlockInfo, index int) error {
	anchorLog.Debug("check Confirmations for btc tx: ", toShaHash(dirBlockInfo.GetBTCTxHash()).String())
	txResult, err := a.wclient.GetTransaction(toShaHash(dirBlockInfo.GetBTCTxHash()))
	if err != nil {
		anchorLog.Debugf(err.Error())
		return err
	}
	anchorLog.Debugf("GetTransactionResult: %s\n", spew.Sdump(txResult))
	if txResult.Confirmations >= int64(a.confirmationsNeeded) {
		btcBlockHash, _ := wire.NewShaHashFromStr(txResult.BlockHash)
		var rewrite = false
		// Either the call back is not recorded in case of BTCBlockHash is zero hash,
		// or bad things like re-organization of btc main chain happened
		if bytes.Compare(dirBlockInfo.BTCBlockHash.Bytes(), btcBlockHash.Bytes()) != 0 {
			anchorLog.Debugf("BTCBlockHash changed: original BTCBlockHeight=%d, original BTCBlockHash=%s, original tx offset=%d\n", dirBlockInfo.BTCBlockHeight, toShaHash(dirBlockInfo.BTCBlockHash).String(), dirBlockInfo.BTCTxOffset)
			dirBlockInfo.BTCBlockHash = toHash(btcBlockHash)
			btcBlock, err := a.wclient.GetBlockVerbose(btcBlockHash, true)
			if err != nil {
				anchorLog.Debugf(err.Error())
			}
			if btcBlock.Height > 0 {
				dirBlockInfo.BTCBlockHeight = int32(btcBlock.Height)
			}
			anchorLog.Debugf("BTCBlockHash changed: new BTCBlockHeight=%d, new BTCBlockHash=%s, btcBlockVerbose.Height=%d\n", dirBlockInfo.BTCBlockHeight, btcBlockHash.String(), btcBlock.Height)
			rewrite = true
		}
		dirBlockInfo.BTCConfirmed = true // needs confirmationsNeeded (20) to be confirmed.
		dirBlockInfo.SetTimestamp(primitives.NewTimestampNow())
		a.db.SaveDirBlockInfo(dirBlockInfo)
		a.dirBlockInfoSlice = append(a.dirBlockInfoSlice[:index], a.dirBlockInfoSlice[index+1:]...) //delete it
		anchorLog.Debugf("Fully confirmed %d times. txid=%s, dirblockInfo=%s\n", txResult.Confirmations, txResult.TxID, spew.Sdump(dirBlockInfo))
		if rewrite {
			anchorLog.Debug("rewrite to anchor chain: ", spew.Sdump(dirBlockInfo))
			a.saveToAnchorChain(dirBlockInfo)
		}
	}
	return nil
}
예제 #11
0
func (a *Anchor) doSaveDirBlockInfo(transaction *btcutil.Tx, details *btcjson.BlockDetails, dirBlockInfo *dbInfo.DirBlockInfo, replace bool) {
	if replace {
		dirBlockInfo.BTCTxHash = toHash(transaction.Sha()) // in case of tx being malleated
	}
	dirBlockInfo.BTCTxOffset = int32(details.Index)
	dirBlockInfo.BTCBlockHeight = details.Height
	btcBlockHash, _ := wire.NewShaHashFromStr(details.Hash)
	dirBlockInfo.BTCBlockHash = toHash(btcBlockHash)
	dirBlockInfo.SetTimestamp(primitives.NewTimestampNow())
	a.db.SaveDirBlockInfo(dirBlockInfo)
	anchorLog.Infof("In doSaveDirBlockInfo, dirBlockInfo:%s saved to db\n", spew.Sdump(dirBlockInfo))

	// to make factom / explorer more user friendly, instead of waiting for
	// over 2 hours to know it's anchored, we can create the anchor chain instantly
	// then change it when the btc main chain re-org happens.
	a.saveToAnchorChain(dirBlockInfo)
}
예제 #12
0
func createMissingDirBlockInfo() {
	fmt.Println("create DirBlockInfo for those un-anchored DirBlocks")
	//dblocks, _ := db.FetchAllDBlocks()
	for _, dblock := range dblocks {
		if _, ok := dirBlockInfoMap[dblock.Header.DBHeight]; ok {
			continue
		} else {
			dblock.BuildKeyMerkleRoot()
			//fmt.Printf("creating missing dirBlockInfo for dir block=%s\n", spew.Sdump(dblock))
			dirBlockInfo := common.NewDirBlockInfoFromDBlock(&dblock)
			//fmt.Printf("creating missing dirBlockInfo. DirBlockInfo=%s\n", spew.Sdump(dirBlockInfo))
			err := db.InsertDirBlockInfo(dirBlockInfo)
			if err != nil {
				fmt.Printf("InsertDirBlockInfo error: %s, DirBlockInfo=%s\n", err, spew.Sdump(dirBlockInfo))
			}
			dirBlockInfoMap[dirBlockInfo.DBHeight] = dirBlockInfo
		}
	}
}
예제 #13
0
func (a *Anchor) saveToAnchorChain(dirBlockInfo *dbInfo.DirBlockInfo) {
	anchorLog.Debug("in saveToAnchorChain")
	anchorRec := new(AnchorRecord)
	anchorRec.AnchorRecordVer = 1
	anchorRec.DBHeight = dirBlockInfo.GetDBHeight()
	anchorRec.KeyMR = dirBlockInfo.GetDBMerkleRoot().String()
	anchorRec.RecordHeight = a.state.GetHighestCompletedBlock() // need the next block height
	anchorRec.Bitcoin = new(BitcoinStruct)
	anchorRec.Bitcoin.Address = a.defaultAddress.String()
	anchorRec.Bitcoin.TXID = dirBlockInfo.GetBTCTxHash().(*primitives.Hash).BTCString()
	anchorRec.Bitcoin.BlockHeight = dirBlockInfo.BTCBlockHeight
	anchorRec.Bitcoin.BlockHash = dirBlockInfo.BTCBlockHash.(*primitives.Hash).BTCString()
	anchorRec.Bitcoin.Offset = dirBlockInfo.BTCTxOffset
	anchorLog.Info("before submitting Entry To AnchorChain. anchor.record: " + spew.Sdump(anchorRec))

	err := a.submitEntryToAnchorChain(anchorRec)
	if err != nil {
		anchorLog.Error("Error in writing anchor into anchor chain: ", err.Error())
	}
}
예제 #14
0
// UpdateDirBlockInfoMap allows factom processor to update DirBlockInfo
// when a new Directory Block is saved to db
func UpdateDirBlockInfoMap(dirBlockInfo *common.DirBlockInfo) {
	anchorLog.Debug("UpdateDirBlockInfoMap: ", spew.Sdump(dirBlockInfo))
	dirBlockInfoMap[dirBlockInfo.DBMerkleRoot.String()] = dirBlockInfo
}
예제 #15
0
func Spew(data interface{}) string {
	return spew.Sdump(data)
}
예제 #16
0
func validateMsgTx(msgtx *wire.MsgTx, inputs []btcjson.ListUnspentResult) error {
	flags := txscript.ScriptBip16 | txscript.ScriptStrictMultiSig //ScriptCanonicalSignatures
	bip16 := time.Now().After(txscript.Bip16Activation)
	if bip16 {
		flags |= txscript.ScriptBip16
	}

	for i := range msgtx.TxIn {
		scriptPubKey, err := hex.DecodeString(inputs[i].ScriptPubKey)
		if err != nil {
			return fmt.Errorf("cannot decode scriptPubKey: %s", err)
		}
		engine, err := txscript.NewEngine(scriptPubKey, msgtx, i, flags)
		if err != nil {
			anchorLog.Errorf("cannot create script engine: %s\n", err)
			return fmt.Errorf("cannot create script engine: %s", err)
		}
		if err = engine.Execute(); err != nil {
			anchorLog.Errorf("cannot execute script engine: %s\n  === UnspentResult: %s", err, spew.Sdump(inputs[i]))
			return fmt.Errorf("cannot execute script engine: %s", err)
		}
	}
	return nil
}
예제 #17
0
func (a *Anchor) saveDirBlockInfo(transaction *btcutil.Tx, details *btcjson.BlockDetails) {
	anchorLog.Debug("in saveDirBlockInfo")
	var saved = false
	for _, dirBlockInfo := range a.dirBlockInfoSlice {
		if bytes.Compare(dirBlockInfo.GetBTCTxHash().Bytes(), transaction.Sha().Bytes()) == 0 {
			a.doSaveDirBlockInfo(transaction, details, dirBlockInfo.(*dbInfo.DirBlockInfo), false)
			saved = true
			break
		}
	}
	// This happends when there's a double spending or tx malleated(for dir block 122 and its btc tx)
	// Original: https://www.blocktrail.com/BTC/tx/ac82f4173259494b22f4987f1e18608f38f1ff756fb4a3c637dfb5565aa5e6cf
	// malleated: https://www.blocktrail.com/BTC/tx/a9b2d6b5d320c7f0f384a49b167524aca9c412af36ed7b15ca7ea392bccb2538
	// re-anchored: https://www.blocktrail.com/BTC/tx/ac82f4173259494b22f4987f1e18608f38f1ff756fb4a3c637dfb5565aa5e6cf
	// In this case, if tx malleation is detected, then use the malleated tx to replace the original tx;
	// Otherwise, it will end up being re-anchored.
	if !saved {
		anchorLog.Infof("Not saved to db, (maybe btc tx malleated): btc.tx=%s\n blockDetails=%s\n", spew.Sdump(transaction), spew.Sdump(details))
		a.checkTxMalleation(transaction, details)
	}
}
예제 #18
0
// Initialize Admin Block Chain from database
func initAChain() {

	//Initialize the Admin Chain ID
	achain = new(common.AdminChain)
	achain.ChainID = new(common.Hash)
	achain.ChainID.SetBytes(common.ADMIN_CHAINID)

	// get all aBlocks from db
	aBlocks, _ := db.FetchAllABlocks()
	sort.Sort(util.ByABlockIDAccending(aBlocks))

	// double check the block ids
	for i := 0; i < len(aBlocks); i = i + 1 {
		if uint32(i) != aBlocks[i].Header.DBHeight {
			panic(errors.New("BlockID does not equal index for chain:" + achain.ChainID.String() + " block:" + fmt.Sprintf("%v", aBlocks[i].Header.DBHeight)))
		}
		if !validateDBSignature(&aBlocks[i], dchain) {
			panic(errors.New("No valid signature found in Admin Block = " + fmt.Sprintf("%s\n", spew.Sdump(aBlocks[i]))))
		}
	}

	//Create an empty block and append to the chain
	if len(aBlocks) == 0 || dchain.NextDBHeight == 0 {
		achain.NextBlockHeight = 0
		achain.NextBlock, _ = common.CreateAdminBlock(achain, nil, 10)

	} else {
		// Entry Credit Chain should have the same height as the dir chain
		achain.NextBlockHeight = dchain.NextDBHeight
		achain.NextBlock, _ = common.CreateAdminBlock(achain, &aBlocks[achain.NextBlockHeight-1], 10)
	}

	exportAChain(achain)

}
예제 #19
0
func TestECBlockMarshal(t *testing.T) {
	ecb1 := common.NewECBlock()

	// build a CommitChain for testing
	cc := common.NewCommitChain()
	cc.Version = 0
	cc.MilliTime = &[6]byte{1, 1, 1, 1, 1, 1}
	cc.ChainIDHash.SetBytes(byteof(0xaa))
	cc.Weld.SetBytes(byteof(0xbb))
	cc.EntryHash.SetBytes(byteof(0xcc))
	cc.Credits = 11

	// make a key and sign the msg
	if pub, privkey, err := ed.GenerateKey(rand.Reader); err != nil {
		t.Error(err)
	} else {
		cc.ECPubKey = pub
		cc.Sig = ed.Sign(privkey, cc.CommitMsg())
	}

	// create a ECBlock for testing
	ecb1.Header.ECChainID.SetBytes(byteof(0x11))
	ecb1.Header.BodyHash.SetBytes(byteof(0x22))
	ecb1.Header.PrevHeaderHash.SetBytes(byteof(0x33))
	ecb1.Header.PrevLedgerKeyMR.SetBytes(byteof(0x44))
	ecb1.Header.EBHeight = 10
	ecb1.Header.HeaderExpansionArea = byteof(0x55)
	ecb1.Header.ObjectCount = 0

	// add the CommitChain to the ECBlock
	ecb1.AddEntry(cc)

	m1 := common.NewMinuteNumber()
	m1.Number = 0x01
	ecb1.AddEntry(m1)

	// add a ServerIndexNumber
	si1 := common.NewServerIndexNumber()
	si1.Number = 3
	ecb1.AddEntry(si1)

	// create an IncreaseBalance for testing
	ib := common.NewIncreaseBalance()
	pub := new([32]byte)
	copy(pub[:], byteof(0xaa))
	ib.ECPubKey = pub
	ib.TXID.SetBytes(byteof(0xbb))
	ib.NumEC = uint64(13)
	// add the IncreaseBalance
	ecb1.AddEntry(ib)

	m2 := common.NewMinuteNumber()
	m2.Number = 0x02
	ecb1.AddEntry(m2)

	ecb2 := common.NewECBlock()
	if p, err := ecb1.MarshalBinary(); err != nil {
		t.Error(err)
	} else {
		if err := ecb2.UnmarshalBinary(p); err != nil {
			t.Error(err)
		}
		t.Log(spew.Sdump(ecb1))
		t.Log(spew.Sdump(ecb2))
		if q, err := ecb2.MarshalBinary(); err != nil {
			t.Error(err)
		} else if string(p) != string(q) {
			t.Errorf("ecb1 = %x\n", p)
			t.Errorf("ecb2 = %x\n", q)
		}
	}
}
예제 #20
0
// TestSpew executes all of the tests described by spewTests.
func TestSpew(t *testing.T) {
	initSpewTests()

	t.Logf("Running %d tests", len(spewTests))
	for i, test := range spewTests {
		buf := new(bytes.Buffer)
		switch test.f {
		case fCSFdump:
			test.cs.Fdump(buf, test.in)

		case fCSFprint:
			test.cs.Fprint(buf, test.in)

		case fCSFprintf:
			test.cs.Fprintf(buf, test.format, test.in)

		case fCSFprintln:
			test.cs.Fprintln(buf, test.in)

		case fCSPrint:
			b, err := redirStdout(func() { test.cs.Print(test.in) })
			if err != nil {
				t.Errorf("%v #%d %v", test.f, i, err)
				continue
			}
			buf.Write(b)

		case fCSPrintln:
			b, err := redirStdout(func() { test.cs.Println(test.in) })
			if err != nil {
				t.Errorf("%v #%d %v", test.f, i, err)
				continue
			}
			buf.Write(b)

		case fCSSdump:
			str := test.cs.Sdump(test.in)
			buf.WriteString(str)

		case fCSSprint:
			str := test.cs.Sprint(test.in)
			buf.WriteString(str)

		case fCSSprintf:
			str := test.cs.Sprintf(test.format, test.in)
			buf.WriteString(str)

		case fCSSprintln:
			str := test.cs.Sprintln(test.in)
			buf.WriteString(str)

		case fCSErrorf:
			err := test.cs.Errorf(test.format, test.in)
			buf.WriteString(err.Error())

		case fCSNewFormatter:
			fmt.Fprintf(buf, test.format, test.cs.NewFormatter(test.in))

		case fErrorf:
			err := spew.Errorf(test.format, test.in)
			buf.WriteString(err.Error())

		case fFprint:
			spew.Fprint(buf, test.in)

		case fFprintln:
			spew.Fprintln(buf, test.in)

		case fPrint:
			b, err := redirStdout(func() { spew.Print(test.in) })
			if err != nil {
				t.Errorf("%v #%d %v", test.f, i, err)
				continue
			}
			buf.Write(b)

		case fPrintln:
			b, err := redirStdout(func() { spew.Println(test.in) })
			if err != nil {
				t.Errorf("%v #%d %v", test.f, i, err)
				continue
			}
			buf.Write(b)

		case fSdump:
			str := spew.Sdump(test.in)
			buf.WriteString(str)

		case fSprint:
			str := spew.Sprint(test.in)
			buf.WriteString(str)

		case fSprintf:
			str := spew.Sprintf(test.format, test.in)
			buf.WriteString(str)

		case fSprintln:
			str := spew.Sprintln(test.in)
			buf.WriteString(str)

		default:
			t.Errorf("%v #%d unrecognized function", test.f, i)
			continue
		}
		s := buf.String()
		if test.want != s {
			t.Errorf("ConfigState #%d\n got: %s want: %s", i, s, test.want)
			continue
		}
	}
}
예제 #21
0
// Serve incoming msg from inMsgQueue
func serveMsgRequest(msg wire.FtmInternalMsg) error {

	switch msg.Command() {
	case wire.CmdCommitChain:
		msgCommitChain, ok := msg.(*wire.MsgCommitChain)
		if ok && msgCommitChain.IsValid() {

			h := msgCommitChain.CommitChain.GetSigHash().Bytes()
			t := msgCommitChain.CommitChain.GetMilliTime() / 1000

			if !IsTSValid(h, t) {
				return fmt.Errorf("Timestamp invalid on Commit Chain")
			}

			err := processCommitChain(msgCommitChain)
			if err != nil {
				return err
			}
		} else {
			return errors.New("Error in processing msg:" + spew.Sdump(msg))
		}
		// Broadcast the msg to the network if no errors
		outMsgQueue <- msg

	case wire.CmdCommitEntry:
		msgCommitEntry, ok := msg.(*wire.MsgCommitEntry)
		if ok && msgCommitEntry.IsValid() {

			h := msgCommitEntry.CommitEntry.GetSigHash().Bytes()
			t := msgCommitEntry.CommitEntry.GetMilliTime() / 1000

			if !IsTSValid(h, t) {
				return fmt.Errorf("Timestamp invalid on Commit Entry")
			}

			err := processCommitEntry(msgCommitEntry)
			if err != nil {
				return err
			}
		} else {
			return errors.New("Error in processing msg:" + spew.Sdump(msg))
		}
		// Broadcast the msg to the network if no errors
		outMsgQueue <- msg

	case wire.CmdRevealEntry:
		msgRevealEntry, ok := msg.(*wire.MsgRevealEntry)
		if ok && msgRevealEntry.IsValid() {
			err := processRevealEntry(msgRevealEntry)
			if err != nil {
				return err
			}
		} else {
			return errors.New("Error in processing msg:" + spew.Sdump(msg))
		}
		// Broadcast the msg to the network if no errors
		outMsgQueue <- msg

	case wire.CmdInt_EOM:

		if nodeMode == common.SERVER_NODE {
			msgEom, ok := msg.(*wire.MsgInt_EOM)
			if !ok {
				return errors.New("Error in build blocks:" + spew.Sdump(msg))
			}
			procLog.Infof("PROCESSOR: End of minute msg - wire.CmdInt_EOM:%+v\n", msg)

			common.FactoidState.EndOfPeriod(int(msgEom.EOM_Type))

			if msgEom.EOM_Type == wire.END_MINUTE_10 {

				// Process from Orphan pool before the end of process list
				processFromOrphanPool()

				// Pass the Entry Credit Exchange Rate into the Factoid component
				msgEom.EC_Exchange_Rate = FactoshisPerCredit
				plMgr.AddMyProcessListItem(msgEom, nil, wire.END_MINUTE_10)
				// Set exchange rate in the Factoid State
				common.FactoidState.SetFactoshisPerEC(FactoshisPerCredit)

				err := buildBlocks()
				if err != nil {
					return err
				}

			} else if wire.END_MINUTE_1 <= msgEom.EOM_Type && msgEom.EOM_Type < wire.END_MINUTE_10 {
				ack, err := plMgr.AddMyProcessListItem(msgEom, nil, msgEom.EOM_Type)
				if err != nil {
					return err
				}
				if ack.ChainID == nil {
					ack.ChainID = dchain.ChainID
				}
				// Broadcast the ack to the network if no errors
				//outMsgQueue <- ack
			}

			cp.CP.AddUpdate(
				"MinMark",  // tag
				"status",   // Category
				"Progress", // Title
				fmt.Sprintf("End of Minute %v\n", msgEom.EOM_Type)+ // Message
					fmt.Sprintf("Directory Block Height %v", dchain.NextDBHeight),
				0)
		}

	case wire.CmdDirBlock:
		if nodeMode == common.SERVER_NODE {
			break
		}

		dirBlock, ok := msg.(*wire.MsgDirBlock)
		if ok {
			err := processDirBlock(dirBlock)
			if err != nil {
				return err
			}
		} else {
			return errors.New("Error in processing msg:" + fmt.Sprintf("%+v", msg))
		}

	case wire.CmdFBlock:

		if nodeMode == common.SERVER_NODE {
			break
		}

		fblock, ok := msg.(*wire.MsgFBlock)
		if ok {
			err := processFBlock(fblock)
			if err != nil {
				return err
			}
		} else {
			return errors.New("Error in processing msg:" + fmt.Sprintf("%+v", msg))
		}

	case wire.CmdFactoidTX:

		// First check that the message is good, and is valid.  If not,
		// continue processing commands.
		msgFactoidTX, ok := msg.(*wire.MsgFactoidTX)
		if !ok || !msgFactoidTX.IsValid() {
			break
		}
		// prevent replay attacks
		{
			h := msgFactoidTX.Transaction.GetSigHash().Bytes()
			t := int64(msgFactoidTX.Transaction.GetMilliTimestamp() / 1000)

			if !IsTSValid(h, t) {
				return fmt.Errorf("Timestamp invalid on Factoid Transaction")
			}
		}

		// Handle the server case
		if nodeMode == common.SERVER_NODE {
			t := msgFactoidTX.Transaction
			txnum := len(common.FactoidState.GetCurrentBlock().GetTransactions())
			if common.FactoidState.AddTransaction(txnum, t) == nil {
				if err := processBuyEntryCredit(msgFactoidTX); err != nil {
					return err
				}
			}
		} else {
			// Handle the client case
			outMsgQueue <- msg
		}

	case wire.CmdABlock:
		if nodeMode == common.SERVER_NODE {
			break
		}

		ablock, ok := msg.(*wire.MsgABlock)
		if ok {
			err := processABlock(ablock)
			if err != nil {
				return err
			}
		} else {
			return errors.New("Error in processing msg:" + fmt.Sprintf("%+v", msg))
		}

	case wire.CmdECBlock:
		if nodeMode == common.SERVER_NODE {
			break
		}

		cblock, ok := msg.(*wire.MsgECBlock)
		if ok {
			err := procesECBlock(cblock)
			if err != nil {
				return err
			}
		} else {
			return errors.New("Error in processing msg:" + fmt.Sprintf("%+v", msg))
		}

	case wire.CmdEBlock:
		if nodeMode == common.SERVER_NODE {
			break
		}

		eblock, ok := msg.(*wire.MsgEBlock)
		if ok {
			err := processEBlock(eblock)
			if err != nil {
				return err
			}
		} else {
			return errors.New("Error in processing msg:" + fmt.Sprintf("%+v", msg))
		}

	case wire.CmdEntry:
		if nodeMode == common.SERVER_NODE {
			break
		}

		entry, ok := msg.(*wire.MsgEntry)
		if ok {
			err := processEntry(entry)
			if err != nil {
				return err
			}
		} else {
			return errors.New("Error in processing msg:" + fmt.Sprintf("%+v", msg))
		}

	default:
		return errors.New("Message type unsupported:" + fmt.Sprintf("%+v", msg))
	}

	return nil
}
예제 #22
0
// UpdateDirBlockInfoMap allows factom processor to update DirBlockInfo
// when a new Directory Block is saved to db
func (a *Anchor) UpdateDirBlockInfoMap(dirBlockInfo interfaces.IDirBlockInfo) {
	anchorLog.Debug("UpdateDirBlockInfoMap: ", spew.Sdump(dirBlockInfo))
	a.dirBlockInfoSlice = append(a.dirBlockInfoSlice, dirBlockInfo.(*dbInfo.DirBlockInfo))
}