// Create a new Acknowledgement. Must be called by a leader. This // call assumes all the pieces are in place to create a new acknowledgement func (s *State) NewAck(msg interfaces.IMsg) interfaces.IMsg { vmIndex := msg.GetVMIndex() msg.SetLeaderChainID(s.IdentityChainID) ack := new(messages.Ack) ack.DBHeight = s.LLeaderHeight ack.VMIndex = vmIndex ack.Minute = byte(s.ProcessLists.Get(s.LLeaderHeight).VMs[vmIndex].LeaderMinute) ack.Timestamp = s.GetTimestamp() ack.SaltNumber = s.GetSalt(ack.Timestamp) copy(ack.Salt[:8], s.Salt.Bytes()[:8]) ack.MessageHash = msg.GetMsgHash() ack.LeaderChainID = s.IdentityChainID listlen := len(s.LeaderPL.VMs[vmIndex].List) if listlen == 0 { ack.Height = 0 ack.SerialHash = ack.MessageHash } else { last := s.LeaderPL.GetAckAt(vmIndex, listlen-1) ack.Height = last.Height + 1 ack.SerialHash, _ = primitives.CreateHash(last.MessageHash, ack.MessageHash) } ack.Sign(s) return ack }
func TestAuthoritySignature(t *testing.T) { s := testHelper.CreateAndPopulateTestState() idindex := s.CreateBlankFactomIdentity(primitives.NewZeroHash()) s.Identities[idindex].ManagementChainID = primitives.NewZeroHash() index := s.AddAuthorityFromChainID(primitives.NewZeroHash()) s.Authorities[index].SigningKey = *(s.GetServerPublicKey()) s.Authorities[index].Status = 1 ack := new(messages.Ack) ack.DBHeight = s.LLeaderHeight ack.VMIndex = 1 ack.Minute = byte(5) ack.Timestamp = s.GetTimestamp() ack.MessageHash = primitives.NewZeroHash() ack.LeaderChainID = s.IdentityChainID ack.SerialHash = primitives.NewZeroHash() err := ack.Sign(s) if err != nil { t.Error("Authority Test Failed when signing message") } msg, err := ack.MarshalForSignature() if err != nil { t.Error("Authority Test Failed when marshalling for sig") } sig := ack.GetSignature() server, err := s.Authorities[0].VerifySignature(msg, sig.GetSignature()) if !server || err != nil { t.Error("Authority Test Failed when checking sigs") } }
func (p *ProcessList) AddToProcessList(ack *messages.Ack, m interfaces.IMsg) { if p == nil { return } // We don't check the SaltNumber if this isn't an actual message, i.e. a response from // the past. if !ack.Response && ack.LeaderChainID.IsSameAs(p.State.IdentityChainID) { num := p.State.GetSalt(ack.Timestamp) if num != ack.SaltNumber { os.Stderr.WriteString(fmt.Sprintf("This ChainID %x\n", p.State.IdentityChainID.Bytes())) os.Stderr.WriteString(fmt.Sprintf("This Salt %x\n", p.State.Salt.Bytes()[:8])) os.Stderr.WriteString(fmt.Sprintf("This SaltNumber %x\n for this ack", num)) os.Stderr.WriteString(fmt.Sprintf("Ack ChainID %x\n", ack.LeaderChainID.Bytes())) os.Stderr.WriteString(fmt.Sprintf("Ack Salt %x\n", ack.Salt)) os.Stderr.WriteString(fmt.Sprintf("Ack SaltNumber %x\n for this ack", ack.SaltNumber)) panic("There are two leaders configured with the same Identity in this network! This is a configuration problem!") } } if _, ok := m.(*messages.MissingMsg); ok { panic("This shouldn't happen") } toss := func(hint string) { fmt.Println("dddd TOSS in Process List", p.State.FactomNodeName, hint) fmt.Println("dddd TOSS in Process List", p.State.FactomNodeName, ack.String()) fmt.Println("dddd TOSS in Process List", p.State.FactomNodeName, m.String()) delete(p.State.Holding, ack.GetHash().Fixed()) delete(p.State.Acks, ack.GetHash().Fixed()) } now := p.State.GetTimestamp() vm := p.VMs[ack.VMIndex] if len(vm.List) > int(ack.Height) && vm.List[ack.Height] != nil { _, isNew2 := p.State.Replay.Valid(constants.INTERNAL_REPLAY, m.GetRepeatHash().Fixed(), m.GetTimestamp(), now) if !isNew2 { toss("seen before, or too old") return } } if ack.DBHeight != p.DBHeight { panic(fmt.Sprintf("Ack is wrong height. Expected: %d Ack: %s", p.DBHeight, ack.String())) return } if len(vm.List) > int(ack.Height) && vm.List[ack.Height] != nil { if vm.List[ack.Height].GetMsgHash().IsSameAs(m.GetMsgHash()) { fmt.Printf("dddd %-30s %10s %s\n", "xxxxxxxxx PL Duplicate ", p.State.GetFactomNodeName(), m.String()) fmt.Printf("dddd %-30s %10s %s\n", "xxxxxxxxx PL Duplicate ", p.State.GetFactomNodeName(), ack.String()) fmt.Printf("dddd %-30s %10s %s\n", "xxxxxxxxx PL Duplicate vm", p.State.GetFactomNodeName(), vm.List[ack.Height].String()) fmt.Printf("dddd %-30s %10s %s\n", "xxxxxxxxx PL Duplicate vm", p.State.GetFactomNodeName(), vm.ListAck[ack.Height].String()) toss("2") return } vm.List[ack.Height] = nil return } // From this point on, we consider the transaction recorded. If we detect it has already been // recorded, then we still treat it as if we recorded it. vm.heartBeat = 0 // We have heard from this VM // We have already tested and found m to be a new message. We now record its hashes so later, we // can detect that it has been recorded. We don't care about the results of IsTSValid_ at this point. p.State.Replay.IsTSValid_(constants.INTERNAL_REPLAY, m.GetRepeatHash().Fixed(), m.GetTimestamp(), now) p.State.Replay.IsTSValid_(constants.INTERNAL_REPLAY, m.GetMsgHash().Fixed(), m.GetTimestamp(), now) delete(p.State.Acks, ack.GetHash().Fixed()) delete(p.State.Holding, m.GetMsgHash().Fixed()) // Both the ack and the message hash to the same GetHash() m.SetLocal(false) ack.SetLocal(false) ack.SetPeer2Peer(false) m.SetPeer2Peer(false) ack.SendOut(p.State, ack) m.SendOut(p.State, m) for len(vm.List) <= int(ack.Height) { vm.List = append(vm.List, nil) vm.ListAck = append(vm.ListAck, nil) } p.VMs[ack.VMIndex].List[ack.Height] = m p.VMs[ack.VMIndex].ListAck[ack.Height] = ack p.AddOldMsgs(m) p.OldAcks[m.GetMsgHash().Fixed()] = ack }