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 } } }
// 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 }
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 } } } }
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 }
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) } } }
// 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 }
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)) } }
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()) } } } }
// 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 }
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 }
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) }
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 } } }
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()) } }
// 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 }
func Spew(data interface{}) string { return spew.Sdump(data) }
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 }
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) } }
// 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) }
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) } } }
// 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 } } }
// 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 }
// 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)) }