library(dplyr)
library(readr)
library(ggplot2)

Results from evaluating new domains using cacic web service

CACIC service uses the default architecture from bitbucket repo

Dataset

The dataset contains 3465 domains names. These domains were obtained from 3 datasets sent by Vaclav:

  1. 1500 domains names labeled as DGA by the original NN
  2. 1295 domains labeled as DGA and Normal by the original NN
  3. 1113 domains names labeled by the original NN as DGa and incorrectly classified as normal by Vaclav NN implementation

We merge the datasets and removed duplicated. Final dataset can be found here.

Confusion matrix

caret::confusionMatrix(as.factor(vaclav_results$class),as.factor(vaclav_results$label))
Confusion Matrix and Statistics

          Reference
Prediction  dga normal
    dga    2654     15
    normal  470    326
                                         
               Accuracy : 0.86           
                 95% CI : (0.848, 0.8714)
    No Information Rate : 0.9016         
    P-Value [Acc > NIR] : 1              
                                         
                  Kappa : 0.5053         
 Mcnemar's Test P-Value : <2e-16         
                                         
            Sensitivity : 0.8496         
            Specificity : 0.9560         
         Pos Pred Value : 0.9944         
         Neg Pred Value : 0.4095         
             Prevalence : 0.9016         
         Detection Rate : 0.7659         
   Detection Prevalence : 0.7703         
      Balanced Accuracy : 0.9028         
                                         
       'Positive' Class : dga            
                                         

FALSE NEGATIVES Only 470 domains labeled as DGA by the original NN service where not detected by the cacic web service

Interactive 3D representation of the TRUE POSITIVE (Blue) and FALSE (Orange) NEGATIVE DOMAINS

plotly::plot_ly(pca_data  , type="scatter3d", 
                x = ~PC1, y = ~PC2, z = ~PC3, color = ~label,
                colors = c('#BF382A', '#0C4B8E'), 
                opacity=0.5, marker = list(size = 2),text = ~paste(preds," ",domain))  
No scatter3d mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
No scatter3d mode specifed:
  Setting the mode to markers
  Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode

We can observe three clusters corresponding to the .hosting , .org and .feedback TLDs. TP and FN are observed in the three clusters. The table below shows the percent of FN for each cluster. The org TLD is the the cluster with the higher FN with a 23% followed by the hosting with 18% and feedback with 3%

char_dist<- function(tld_name){
  library(scales)
  
  charlist_FN=fn_domains %>% filter(grepl(tld_name,domain))  %>% do(charlist= unlist(sapply(.$domain, function(x) c(str_split(x,"")[1]))))
  charlist_TP=tp_domains %>% filter(grepl(tld_name,domain)) %>% do(charlist= unlist(sapply(.$domain, function(x) c(str_split(x,"")[1]))))
  
  charlist_FN=as.vector(unlist(charlist_FN %>% select(charlist)))
  charlist_TP=as.vector(unlist(charlist_TP %>% select(charlist)))
  
  tpplot<-ggplot(data.frame(charlist=charlist_TP),aes(x=charlist))+
    geom_bar(col="black",fill='white',aes(y = (..count..)/sum(..count..)))+
    scale_y_continuous(labels=percent)+ylab("Percent")+xlab("")+
    theme_bw()
  
  
  fnplot<-ggplot(data.frame(charlist=charlist_FN),aes(x=charlist))+
    geom_bar(col="black",fill='black',aes(y = (..count..)/sum(..count..)))+
    scale_y_continuous(labels=percent)+ylab("Percent")+xlab("")+
    theme_bw()
  
  gridExtra::grid.arrange(fnplot,tpplot,ncol=1)
  return(list(fnplot=fnplot,tpplot=tpplot))
}

Question: What is the difference between TP and FN in the org TLD?

The Character Frequency Histogram for TP (white) and FN (black)

Question: What is the difference between TP and FN in the hosting TLD?

The Character Frequency Histogram for TP (white) and FN (black)

org_plot<-char_dist("hosting")

Question: What is the difference between TP and FN in the feedback TLD?

The Character Frequency Histogram for TP (white) and FN (black)

org_plot<-char_dist("feedback")

CONCLUSIONS

No significant differences are observable between the FP and TP histograms for the three considered domains. A possible solution could be to include a portion of the non detected DGA into the dataset and retrain de model.

tensorboard("logs") 
LS0tCnRpdGxlOiAiREdBIE5OIE1vZGVsIENvbXBhcmlzb24iCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazogCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKLS0tCgpgYGB7cn0KCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoZ2dwbG90MikKYGBgCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9Cgp2YWNsYXZfcmVzdWx0czwtcmVhZF9jc3YoIi4vdGVzdF9yZXN1bHQuY3N2IikKY2FjaWNfcmVzdWx0czwtcmVhZF9jc3YoIi4vcmVzdWx0cy5jc3YiLGNvbF9uYW1lcyA9IEZBTFNFKQpvbGRfYmFja3BvcnRlZF9yZXN1bHRzPC1yZWFkX2NzdigiLi9wcmVkc19iYWNrcG9ydGVkLmNzdiIpCmNhY2ljX3B5dGhvbl9yZXN1bHRzIDwtcmVhZF9jc3YoIi4vcHJlZHNfY2FjaWNfcHl0aG9uLmNzdiIpCmNhY2ljX3B5dGhvbl9yZXN1bHRzMiA8LXJlYWRfY3N2KCIuL3ByZWRzX2NhY2ljX3B5dGhvbl92Mi5jc3YiKQoKYGBgCgpgYGB7ciBldmFsPUZBTFNFLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9NCwgaW5jbHVkZT1GQUxTRX0KcmVzdWx0czwtY2JpbmQodmFjbGF2X3Jlc3VsdHMsY2FjaWNfcmVzdWx0cyxvbGRfYmFja3BvcnRlZF9yZXN1bHRzJHByZWRzX29yaWdpbmFsX2JhY2twb3J0ZWQsY2FjaWNfcHl0aG9uX3Jlc3VsdHMkcHJlZHNfY2FjaWNfcHl0aG9uLCBjYWNpY19weXRob25fcmVzdWx0czIkcHJlZF9jYWNpY19tb2RlbCkKCm5hbWVzKHJlc3VsdHMpPC1jKCJkb21haW4iLCJvcmlnaW5hbCIsIm5ldyIsImNhY2ljIiwiYmFja3BvcnRlZCIsImNhY2ljX3B5dGhvbiIsImNhY2ljX3B5dGhvbjIiKQoKcmVzdWx0cyAlPiUgbXV0YXRlKG9yaWdpbmFsX2NsYXNzPWlmZWxzZShvcmlnaW5hbD4wLjksImRnYSIsIm5vcm1hbCIpLAogICAgICAgICAgICAgICAgICAgY2FjaWNfY2xhc3M9aWZlbHNlKGNhY2ljPjAuOSwiZGdhIiwibm9ybWFsIiksCiAgICAgICAgICAgICAgICAgICBuZXdfY2xhc3M9aWZlbHNlKG5ldz4wLjksImRnYSIsIm5vcm1hbCIpLAogICAgICAgICAgICAgICAgICAgYmFja3BvcnRlZF9jbGFzcz1pZmVsc2UoYmFja3BvcnRlZD4wLjksImRnYSIsIm5vcm1hbCIpLAogICAgICAgICAgICAgICAgICAgY2FjaWNfcHl0aG9uX2NsYXNzPWlmZWxzZShjYWNpY19weXRob24+MC45LCJkZ2EiLCJub3JtYWwiKQogICAgICAgICAgICAgICAgICAgKSAlPiUgc2VsZWN0KGRvbWFpbixvcmlnaW5hbCxjYWNpYyxuZXcsYmFja3BvcnRlZCxjYWNpY19weXRob24pICU+JSByZXNoYXBlMjo6bWVsdChpZC52YXJzPSdkb21haW4nKSAlPiUKICBnZ3Bsb3QoKSsKICBnZW9tX3RpbGUoYWVzKHk9ZG9tYWluLHg9dmFyaWFibGUsIGFscGhhPXZhbHVlLGZpbGw9dmFsdWUpLGNvbG9yPSdza3libHVlJykrCiAgIHRoZW1lKGF4aXMudGl0bGUueT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCkKICAgICAgICApKwogIHhsYWIoIm1vZGVsIikreWxhYigiIikrbGFicyhmaWxsPSJwcm9iYWJpbGl0eSIpKwogICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0PTEpKQoKCgpwbG90bHk6OmdncGxvdGx5KCkKYGBgCgpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KGRwbHlyKQpyZXN1bHRzX2NsYXNzPC1yZXN1bHRzICU+JSBtdXRhdGUob3JpZ2luYWxfY2xhc3M9aWZlbHNlKG9yaWdpbmFsPjAuOSwiZGdhIiwibm9ybWFsIiksCiAgICAgICAgICAgICAgICAgICBjYWNpY19jbGFzcz1pZmVsc2UoY2FjaWM+MC45LCJkZ2EiLCJub3JtYWwiKSwKICAgICAgICAgICAgICAgICAgIG5ld19jbGFzcz1pZmVsc2UobmV3PjAuOSwiZGdhIiwibm9ybWFsIiksCiAgICAgICAgICAgICAgICAgICBiYWNrcG9ydGVkX2NsYXNzPWlmZWxzZShiYWNrcG9ydGVkPjAuOSwiZGdhIiwibm9ybWFsIiksCiAgICAgICAgICAgICAgICAgICBjYWNpY19weXRob25fY2xhc3M9aWZlbHNlKGNhY2ljX3B5dGhvbj4wLjksImRnYSIsIm5vcm1hbCIpLAogICAgICAgICAgICAgICAgICAgY2FjaWNfcHl0aG9uX2NsYXNzMj1pZmVsc2UoY2FjaWNfcHl0aG9uMj4wLjksImRnYSIsIm5vcm1hbCIpCiAgICAgICAgICAgICAgICAgICApICU+JSBzZWxlY3QoZG9tYWluLG9yaWdpbmFsX2NsYXNzLGNhY2ljX3B5dGhvbl9jbGFzcyxjYWNpY19jbGFzcyxjYWNpY19weXRob25fY2xhc3MyKQoKcmVzdWx0cyAlPiUgc2VsZWN0KGRvbWFpbixvcmlnaW5hbCxjYWNpY19weXRob24yKSAlPiUgcmVhZHI6OndyaXRlX2Nzdigib3JpZ2luYWx2c2NhY2ljX3Jlc3VsdHMuY3N2IikKCmNhcmV0Ojpjb25mdXNpb25NYXRyaXgoYXMuZmFjdG9yKHJlc3VsdHNfY2xhc3Mkb3JpZ2luYWxfY2xhc3MpLGFzLmZhY3RvcihyZXN1bHRzX2NsYXNzJGNhY2ljX3B5dGhvbl9jbGFzczIpKQoKCmBgYApgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpkYXRhc2V0XzE1MDA8LXJlYWRfY3N2KCJyZXN1bHRzX2RhdGFzZXRfMTUwMC5jc3YiKQpkYXRhc2V0XzE1MDAgJT4lIG11dGF0ZShsYWJlbD1pZmVsc2Uob3JpZ2luYWw+MC45LCJkZ2EiLCJub3JtYWwiKSkgJT4lIHNlbGVjdChkb21haW4sbGFiZWwpICU+JSByZWFkcjo6d3JpdGVfY3N2KCIxMjk1X2RhdGEuY3N2IikKYGBgCgpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpkYXRhc2V0XzE1MDAKZGF0YXNldF8xNTAwWzE1MDAsXSRvcmlnaW5hbD0wCgpkYXRhc2V0XzE1MDBfY2xhc3M8LWRhdGFzZXRfMTUwMCAlPiUgbXV0YXRlKAogICAgICAgICAgICAgICAgICAgb3JpZ2luYWxfY2xhc3MgPSBpZmVsc2Uob3JpZ2luYWw+MC45LCJkZ2EiLCJub3JtYWwiKSwKICAgICAgICAgICAgICAgICAgIGNhY2ljX2NsYXNzID0gaWZlbHNlKGNhY2ljX3NlcnZpY2lvPjAuOSwiZGdhIiwibm9ybWFsIiksCiAgICAgICAgICAgICAgICAgICBjYWNpY19weXRob25fdmFjbGF2X2NsYXNzID0gaWZlbHNlKGNhY2ljX3B5dGhvbl92YWNsYXY+MC45LCJkZ2EiLCJub3JtYWwiKSwKICAgICAgICAgICAgICAgICAgIGNhY2ljX3B5dGhvbl9jbGFzcyA9IGlmZWxzZShjYWNpY19weXRob24+MC45LCJkZ2EiLCJub3JtYWwiKQogICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICApIyAlPiUgc2VsZWN0KGRvbWFpbixvcmlnaW5hbF9jbGFzcyxjYWNpY19weXRob25fdmFjbGF2X2NsYXNzLGNhY2ljX2NsYXNzLGNhY2ljX3B5dGhvbl9jbGFzcykKCgpjYXJldDo6Y29uZnVzaW9uTWF0cml4KGFzLmZhY3RvcihkYXRhc2V0XzE1MDBfY2xhc3MkY2FjaWNfY2xhc3MpLCBhcy5mYWN0b3IoZGF0YXNldF8xNTAwX2NsYXNzJG9yaWdpbmFsX2NsYXNzKSApCgpgYGAKCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoYWJpbmQpCmZuX2RvbWFpbnM8LWRhdGFzZXRfMTUwMF9jbGFzcyAlPiUgZmlsdGVyKG9yaWdpbmFsX2NsYXNzPT0nZGdhJyAmIGNhY2ljX3B5dGhvbl9jbGFzcz09J25vcm1hbCcpICU+JSBzZWxlY3QoZG9tYWluLGNhY2ljX3B5dGhvbixjYWNpY19weXRob25fY2xhc3MpIAp0cF9kb21haW5zPC1kYXRhc2V0XzE1MDBfY2xhc3MgJT4lIGZpbHRlcihvcmlnaW5hbF9jbGFzcz09J2RnYScgJiBjYWNpY19weXRob25fY2xhc3M9PSdkZ2EnKSAlPiUgc2VsZWN0KGRvbWFpbixjYWNpY19weXRob24pIAoKZm5fZG9tYWlucyRsYWJlbDwtcmVwKCJGYWxzZSBOZWdhdGl2ZSIsIGxlbmd0aChmbl9kb21haW5zJGRvbWFpbikpCnRwX2RvbWFpbnMkbGFiZWw8LXJlcCgiVHJ1ZSBQb3NpdGl2ZSIsIGxlbmd0aCh0cF9kb21haW5zJGRvbWFpbikpCgoKRk5fdG9rZW5pemVkPXRva2VuaXplKGFzLm1hdHJpeChmbl9kb21haW5zJGRvbWFpbiksZm5fZG9tYWlucyRsYWJlbCkKVFBfdG9rZW5pemVkPXRva2VuaXplKGFzLm1hdHJpeCh0cF9kb21haW5zJGRvbWFpbiksdHBfZG9tYWlucyRsYWJlbCkKCm1hbHdhcmVfcmVzdWx0cz1saXN0KCkKbWFsd2FyZV9yZXN1bHRzJGVuY29kZTwtYWJpbmQoRk5fdG9rZW5pemVkJGVuY29kZSxUUF90b2tlbml6ZWQkZW5jb2RlLGFsb25nPTEpCm1hbHdhcmVfcmVzdWx0cyRkb21haW48LWMoRk5fdG9rZW5pemVkJGRvbWFpbixUUF90b2tlbml6ZWQkZG9tYWluKQptYWx3YXJlX3Jlc3VsdHMkbGFiZWw8LWMoYXMuY2hhcmFjdGVyKEZOX3Rva2VuaXplZCRsYWJlbCksYXMuY2hhcmFjdGVyKFRQX3Rva2VuaXplZCRsYWJlbCkpCm1hbHdhcmVfcmVzdWx0cyRwcmVkczwtYyhmbl9kb21haW5zJGNhY2ljX3B5dGhvbix0cF9kb21haW5zJGNhY2ljX3B5dGhvbikKcGNhPXByY29tcChtYWx3YXJlX3Jlc3VsdHMkZW5jb2RlWywxOjIwXSxjZW50ZXI9VFJVRSxzY2FsZS49VFJVRSkKICBwY2FfZGF0YTwtZGF0YS5mcmFtZShwY2EkeCxsYWJlbD1tYWx3YXJlX3Jlc3VsdHMkbGFiZWwsZG9tYWluPW1hbHdhcmVfcmVzdWx0cyRkb21haW4scHJlZHM9bWFsd2FyZV9yZXN1bHRzJHByZWRzKQogIHBjYV9wbG90PC1nZ3Bsb3QocGNhX2RhdGEgJT4lIHNhbXBsZV9uKDUwMCksYWVzKHg9UEMxLHk9UEMzKSkrCiAgICBnZW9tX3BvaW50KGFlcyhjb2xvcj1sYWJlbCx0ZXh0PWRvbWFpbixzaGFwZT1hcy5mYWN0b3IobGFiZWwpKSxhbHBoYT0wLjUpKwogICAgdGhlbWVfYncoKQoKcGxvdGx5OjpwbG90X2x5KHBjYV9kYXRhICwgdHlwZT0ic2NhdHRlcjNkIiwgCiAgICAgICAgICAgICAgICB4ID0gflBDMSwgeSA9IH5QQzIsIHogPSB+UEMzLCBjb2xvciA9IH5sYWJlbCwKICAgICAgICAgICAgICAgIGNvbG9ycyA9IGMoJyNCRjM4MkEnLCAnIzBDNEI4RScpLCAKICAgICAgICAgICAgICAgIG9wYWNpdHk9MC41LCBtYXJrZXIgPSBsaXN0KHNpemUgPSAzKSx0ZXh0ID0gfnBhc3RlKHByZWRzLCIgIixkb21haW4pKSAgCmBgYAoKCgojIFJlc3VsdHMgZnJvbSBldmFsdWF0aW5nIG5ldyBkb21haW5zIHVzaW5nIGNhY2ljIHdlYiBzZXJ2aWNlCkNBQ0lDIHNlcnZpY2UgdXNlcyB0aGUgZGVmYXVsdCBhcmNoaXRlY3R1cmUgZnJvbSBiaXRidWNrZXQgcmVwbwoKKiBTZXJ2aWNlIGxvY2F0ZWQgYXQgaHR0cDovL2NhdGFudXNvLmR1Y2tkbnMub3JnOjgwMDAvcHJlZGljdD9kb21haW49d3d3Lmdvb2dsZS5jb20KCgojIyBEYXRhc2V0ClRoZSBkYXRhc2V0IGNvbnRhaW5zIDM0NjUgZG9tYWlucyBuYW1lcy4gVGhlc2UgZG9tYWlucyB3ZXJlIG9idGFpbmVkIGZyb20gMyBkYXRhc2V0cyBzZW50IGJ5IFZhY2xhdjoKCjEuIDE1MDAgZG9tYWlucyBuYW1lcyBsYWJlbGVkIGFzIERHQSBieSB0aGUgb3JpZ2luYWwgTk4KMi4gMTI5NSBkb21haW5zIGxhYmVsZWQgYXMgREdBIGFuZCBOb3JtYWwgYnkgdGhlIG9yaWdpbmFsIE5OCjMuIDExMTMgZG9tYWlucyBuYW1lcyBsYWJlbGVkIGJ5IHRoZSBvcmlnaW5hbCBOTiBhcyBER2EgYW5kIGluY29ycmVjdGx5IGNsYXNzaWZpZWQgYXMgbm9ybWFsIGJ5IFZhY2xhdiBOTiBpbXBsZW1lbnRhdGlvbgoKV2UgbWVyZ2UgdGhlIGRhdGFzZXRzIGFuZCByZW1vdmVkIGR1cGxpY2F0ZWQuIEZpbmFsIGRhdGFzZXQgY2FuIGJlIGZvdW5kIFtoZXJlXShodHRwczovL3d3dy5kcm9wYm94LmNvbS9zLzVqeWYweml4Njdld294bS92YWNsYXZfcmVzdWx0c19sYWJlbGVkLmNzdj9kbD0xKS4KCmBgYHtyfQoKdmFjbGF2X2RhdGFzZXQ8LXJlYWRfY3N2KCJ2YWNsYXYuY3N2IikgIyByZXN1bHRzIGZyb20gb3JpZ2luYWwgTk4gc2VydmljZSBydW5uaW5nIGF0IHdoYWxlYm9uZQp2YWNsYXZfcmVzdWx0czwtcmVhZF9jc3YoInZhY2xhdl9yZXN1bHRzLmNzdiIpICMgcmVzdWx0cyBmcm9tIHF1ZXJ5aW5nIGNhY2ljIHdlYiBzZXJ2aWNlCnZhY2xhdl9yZXN1bHRzPC1jYmluZCh2YWNsYXZfcmVzdWx0cyxsYWJlbD12YWNsYXZfZGF0YXNldCRsYWJlbCkgJT4lIHNlbGVjdChkb21haW4scHJvYmFiaWxpdHksY2xhc3MsbGFiZWwpCnJlYWRyOjp3cml0ZV9jc3YodmFjbGF2X3Jlc3VsdHMsInZhY2xhdl9yZXN1bHRzX2xhYmVsZWQuY3N2IikKdmFjbGF2X3Jlc3VsdHMgJT4lIGdyb3VwX2J5KGNsYXNzKSAlPiUgc3VtbWFyaXNlKG49bigpKQpgYGAKIyMgQ29uZnVzaW9uIG1hdHJpeApgYGB7cn0KY2FyZXQ6OmNvbmZ1c2lvbk1hdHJpeChhcy5mYWN0b3IodmFjbGF2X3Jlc3VsdHMkY2xhc3MpLGFzLmZhY3Rvcih2YWNsYXZfcmVzdWx0cyRsYWJlbCkpCmBgYAoKKipGQUxTRSBORUdBVElWRVMgKiogT25seSA0NzAgZG9tYWlucyBsYWJlbGVkIGFzIERHQSBieSB0aGUgb3JpZ2luYWwgTk4gc2VydmljZSB3aGVyZSBub3QgZGV0ZWN0ZWQgYnkgdGhlIGNhY2ljIHdlYiBzZXJ2aWNlCgojIyMgSW50ZXJhY3RpdmUgM0QgcmVwcmVzZW50YXRpb24gb2YgdGhlIFRSVUUgUE9TSVRJVkUgKEJsdWUpIGFuZCBGQUxTRSAoT3JhbmdlKSBORUdBVElWRSBET01BSU5TCgpgYGB7ciBmaWcud2lkdGg9OH0KbGlicmFyeShhYmluZCkKZm5fZG9tYWluczwtdmFjbGF2X3Jlc3VsdHMgJT4lIGZpbHRlcihjbGFzcz09J25vcm1hbCcgJiBsYWJlbD09J2RnYScpIAp0cF9kb21haW5zPC12YWNsYXZfcmVzdWx0cyAlPiUgZmlsdGVyKGNsYXNzPT0nZGdhJyAmIGxhYmVsPT0nZGdhJykgIAoKZm5fZG9tYWlucyRsYWJlbDwtcmVwKCJGYWxzZSBOZWdhdGl2ZSIsIGxlbmd0aChmbl9kb21haW5zJGRvbWFpbikpCnRwX2RvbWFpbnMkbGFiZWw8LXJlcCgiVHJ1ZSBQb3NpdGl2ZSIsIGxlbmd0aCh0cF9kb21haW5zJGRvbWFpbikpCgoKRk5fdG9rZW5pemVkPXRva2VuaXplKGFzLm1hdHJpeChmbl9kb21haW5zJGRvbWFpbiksZm5fZG9tYWlucyRsYWJlbCkKVFBfdG9rZW5pemVkPXRva2VuaXplKGFzLm1hdHJpeCh0cF9kb21haW5zJGRvbWFpbiksdHBfZG9tYWlucyRsYWJlbCkKCm1hbHdhcmVfcmVzdWx0cz1saXN0KCkKbWFsd2FyZV9yZXN1bHRzJGVuY29kZTwtYWJpbmQoRk5fdG9rZW5pemVkJGVuY29kZSxUUF90b2tlbml6ZWQkZW5jb2RlLGFsb25nPTEpCm1hbHdhcmVfcmVzdWx0cyRkb21haW48LWMoRk5fdG9rZW5pemVkJGRvbWFpbixUUF90b2tlbml6ZWQkZG9tYWluKQptYWx3YXJlX3Jlc3VsdHMkbGFiZWw8LWMoYXMuY2hhcmFjdGVyKEZOX3Rva2VuaXplZCRsYWJlbCksYXMuY2hhcmFjdGVyKFRQX3Rva2VuaXplZCRsYWJlbCkpCm1hbHdhcmVfcmVzdWx0cyRwcmVkczwtYyhmbl9kb21haW5zJHByb2JhYmlsaXR5LHRwX2RvbWFpbnMkcHJvYmFiaWxpdHkpCnBjYT1wcmNvbXAobWFsd2FyZV9yZXN1bHRzJGVuY29kZVssMToyMF0sY2VudGVyPVRSVUUsc2NhbGUuPVRSVUUpCiAgcGNhX2RhdGE8LWRhdGEuZnJhbWUocGNhJHgsbGFiZWw9bWFsd2FyZV9yZXN1bHRzJGxhYmVsLGRvbWFpbj1tYWx3YXJlX3Jlc3VsdHMkZG9tYWluLHByZWRzPW1hbHdhcmVfcmVzdWx0cyRwcmVkcykKICBwY2FfcGxvdDwtZ2dwbG90KHBjYV9kYXRhICU+JSBzYW1wbGVfbig1MDApLGFlcyh4PVBDMSx5PVBDMykpKwogICAgZ2VvbV9wb2ludChhZXMoY29sb3I9bGFiZWwsdGV4dD1kb21haW4sc2hhcGU9YXMuZmFjdG9yKGxhYmVsKSksYWxwaGE9MC41KSsKICAgIHRoZW1lX2J3KCkKCnBsb3RseTo6cGxvdF9seShwY2FfZGF0YSAgLCB0eXBlPSJzY2F0dGVyM2QiLCAKICAgICAgICAgICAgICAgIHggPSB+UEMxLCB5ID0gflBDMiwgeiA9IH5QQzMsIGNvbG9yID0gfmxhYmVsLAogICAgICAgICAgICAgICAgY29sb3JzID0gYygnI0JGMzgyQScsICcjMEM0QjhFJyksIAogICAgICAgICAgICAgICAgb3BhY2l0eT0wLjUsIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IDIpLHRleHQgPSB+cGFzdGUocHJlZHMsIiAiLGRvbWFpbikpICAKYGBgCgpXZSBjYW4gb2JzZXJ2ZSB0aHJlZSBjbHVzdGVycyBjb3JyZXNwb25kaW5nIHRvIHRoZSAqKi5ob3N0aW5nKiogLCAqKi5vcmcqKiBhbmQgKiouZmVlZGJhY2sqKiAgVExEcy4KVFAgYW5kIEZOIGFyZSBvYnNlcnZlZCBpbiB0aGUgdGhyZWUgY2x1c3RlcnMuIFRoZSB0YWJsZSBiZWxvdyBzaG93cyB0aGUgcGVyY2VudCBvZiBGTiBmb3IgZWFjaCBjbHVzdGVyLgpUaGUgKipvcmcqKiBUTEQgaXMgdGhlIHRoZSBjbHVzdGVyIHdpdGggdGhlIGhpZ2hlciBGTiB3aXRoIGEgMjMlIGZvbGxvd2VkIGJ5IHRoZSAqKmhvc3RpbmcqKiB3aXRoIDE4JSBhbmQgKipmZWVkYmFjayoqIHdpdGggMyUKCmBgYHtyfQpkYXRhLmZyYW1lKGRvbWFpbj1tYWx3YXJlX3Jlc3VsdHMkZG9tYWluLGxhYmVsPW1hbHdhcmVfcmVzdWx0cyRsYWJlbCkgJT4lIG11dGF0ZSh0bGQ9aWZlbHNlKCBncmVwbCgib3JnIixkb21haW4gKSwib3JnIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKCBncmVwbCgiZmVlZGJhY2siLGRvbWFpbikgLCJmZWVkYmFjayIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoIGdyZXBsKCJob3N0aW5nIixkb21haW4pICwgImhvc3RpbmciLCAib3RoZXIiKSkpKSAgJT4lCiBncm91cF9ieSh0bGQsbGFiZWwpICU+JSBzdW1tYXJpc2UodG90YWw9bigpKSAlPiUgbXV0YXRlKHBlcmNlbnQ9dG90YWwvc3VtKHRvdGFsKSkgJT4lIGZpbHRlcihsYWJlbD09IkZhbHNlIE5lZ2F0aXZlIiklPiUgc2VsZWN0KHRsZCxwZXJjZW50KQpgYGAKCgoKCmBgYHtyfQpjaGFyX2Rpc3Q8LSBmdW5jdGlvbih0bGRfbmFtZSl7CiAgbGlicmFyeShzY2FsZXMpCiAgCiAgY2hhcmxpc3RfRk49Zm5fZG9tYWlucyAlPiUgZmlsdGVyKGdyZXBsKHRsZF9uYW1lLGRvbWFpbikpICAlPiUgZG8oY2hhcmxpc3Q9IHVubGlzdChzYXBwbHkoLiRkb21haW4sIGZ1bmN0aW9uKHgpIGMoc3RyX3NwbGl0KHgsIiIpWzFdKSkpKQogIGNoYXJsaXN0X1RQPXRwX2RvbWFpbnMgJT4lIGZpbHRlcihncmVwbCh0bGRfbmFtZSxkb21haW4pKSAlPiUgZG8oY2hhcmxpc3Q9IHVubGlzdChzYXBwbHkoLiRkb21haW4sIGZ1bmN0aW9uKHgpIGMoc3RyX3NwbGl0KHgsIiIpWzFdKSkpKQogIAogIGNoYXJsaXN0X0ZOPWFzLnZlY3Rvcih1bmxpc3QoY2hhcmxpc3RfRk4gJT4lIHNlbGVjdChjaGFybGlzdCkpKQogIGNoYXJsaXN0X1RQPWFzLnZlY3Rvcih1bmxpc3QoY2hhcmxpc3RfVFAgJT4lIHNlbGVjdChjaGFybGlzdCkpKQogIAogIHRwcGxvdDwtZ2dwbG90KGRhdGEuZnJhbWUoY2hhcmxpc3Q9Y2hhcmxpc3RfVFApLGFlcyh4PWNoYXJsaXN0KSkrCiAgICBnZW9tX2Jhcihjb2w9ImJsYWNrIixmaWxsPSd3aGl0ZScsYWVzKHkgPSAoLi5jb3VudC4uKS9zdW0oLi5jb3VudC4uKSkpKwogICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1wZXJjZW50KSt5bGFiKCJQZXJjZW50IikreGxhYigiIikrCiAgICB0aGVtZV9idygpCiAgCiAgCiAgZm5wbG90PC1nZ3Bsb3QoZGF0YS5mcmFtZShjaGFybGlzdD1jaGFybGlzdF9GTiksYWVzKHg9Y2hhcmxpc3QpKSsKICAgIGdlb21fYmFyKGNvbD0iYmxhY2siLGZpbGw9J2JsYWNrJyxhZXMoeSA9ICguLmNvdW50Li4pL3N1bSguLmNvdW50Li4pKSkrCiAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXBlcmNlbnQpK3lsYWIoIlBlcmNlbnQiKSt4bGFiKCIiKSsKICAgIHRoZW1lX2J3KCkKICAKICBncmlkRXh0cmE6OmdyaWQuYXJyYW5nZShmbnBsb3QsdHBwbG90LG5jb2w9MSkKICByZXR1cm4obGlzdChmbnBsb3Q9Zm5wbG90LHRwcGxvdD10cHBsb3QpKQp9CgpgYGAKIyNRdWVzdGlvbjogV2hhdCBpcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIFRQIGFuZCBGTiBpbiB0aGUgKipvcmcqKiBUTEQ/ClRoZSBDaGFyYWN0ZXIgRnJlcXVlbmN5IEhpc3RvZ3JhbSBmb3IgVFAgKHdoaXRlKSBhbmQgRk4gKGJsYWNrKQpgYGB7cn0Kb3JnX3Bsb3Q8LWNoYXJfZGlzdCgib3JnIikKYGBgCgojIyBRdWVzdGlvbjogV2hhdCBpcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIFRQIGFuZCBGTiBpbiB0aGUgKipob3N0aW5nKiogVExEPwpUaGUgQ2hhcmFjdGVyIEZyZXF1ZW5jeSBIaXN0b2dyYW0gZm9yIFRQICh3aGl0ZSkgYW5kIEZOIChibGFjaykKYGBge3J9Cm9yZ19wbG90PC1jaGFyX2Rpc3QoImhvc3RpbmciKQpgYGAKCgojIyBRdWVzdGlvbjogV2hhdCBpcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIFRQIGFuZCBGTiBpbiB0aGUgKipmZWVkYmFjayoqIFRMRD8KVGhlIENoYXJhY3RlciBGcmVxdWVuY3kgSGlzdG9ncmFtIGZvciBUUCAod2hpdGUpIGFuZCBGTiAoYmxhY2spCgpgYGB7cn0Kb3JnX3Bsb3Q8LWNoYXJfZGlzdCgiZmVlZGJhY2siKQpgYGAKCiMgQ09OQ0xVU0lPTlMKCk5vIHNpZ25pZmljYW50IGRpZmZlcmVuY2VzIGFyZSBvYnNlcnZhYmxlIGJldHdlZW4gdGhlIEZQIGFuZCBUUCBoaXN0b2dyYW1zIGZvciB0aGUgdGhyZWUgY29uc2lkZXJlZCBkb21haW5zLgpBIHBvc3NpYmxlIHNvbHV0aW9uIGNvdWxkIGJlIHRvIGluY2x1ZGUgYSBwb3J0aW9uIG9mIHRoZSBub24gZGV0ZWN0ZWQgREdBIGludG8gdGhlIGRhdGFzZXQgYW5kIHJldHJhaW4gZGUgbW9kZWwuCgoKCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoc3RyaW5ncikKCmZuX251bWZyZXE8LWRhdGEuZnJhbWUoZG9tYWluPWZuX2RvbWFpbnMkZG9tYWluLG51bWZyZXE9c3RyX3NwbGl0KGZuX2RvbWFpbnMkZG9tYWluLCJcXC4iLHNpbXBsaWZ5ID0gVClbLDFdICU+JSAgc3RyX2NvdW50KCJbMC05XSIpIC8gIHN0cl9sZW5ndGgoc3RyX3NwbGl0KGZuX2RvbWFpbnMkZG9tYWluLCJcXC4iLHNpbXBsaWZ5ID0gVClbLDFdKSx0eXBlPXJlcCgiZm4iKSxwcmVkcz1mbl9kb21haW5zJHByb2JhYmlsaXR5KQp0cF9udW1mcmVxPC1kYXRhLmZyYW1lKGRvbWFpbj10cF9kb21haW5zJGRvbWFpbixudW1mcmVxPXN0cl9zcGxpdCh0cF9kb21haW5zJGRvbWFpbiwiXFwuIixzaW1wbGlmeSA9IFQpWywxXSAlPiUgIHN0cl9jb3VudCgiWzAtOV0iKSAvICBzdHJfbGVuZ3RoKHN0cl9zcGxpdCh0cF9kb21haW5zJGRvbWFpbiwiXFwuIixzaW1wbGlmeSA9IFQpWywxXSksdHlwZT1yZXAoInRwIikscHJlZHM9dHBfZG9tYWlucyRwcm9iYWJpbGl0eSkKCnJiaW5kKGZuX251bWZyZXEsdHBfbnVtZnJlcSkgJT4lIGZpbHRlciAoZ3JlcGwoIm9yZyIsZG9tYWluKSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgIAogIGdncGxvdCgpKwogIGdlb21faGlzdG9ncmFtKGFlcyh4PW51bWZyZXEpLGFscGhhPTAuNSxmaWxsPSdza3libHVlJyxjb2xvcj0nYmx1ZScpKwogIGZhY2V0X3dyYXAofnR5cGUpKwogIHRoZW1lX2J3KCkKICAKCmZuX251bWZyZXEgJT4lIGFycmFuZ2UobnVtZnJlcSkKCmBgYAoKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KRk5fdG9rZW5pemVkJGVuY29kZQpgYGAKCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoa2VyYXMpCm1hbHdhcmVfcmVzdWx0cyRlbmNvZGUgJT4lIG5yb3coKQoKaW5wdXRfc2hhcGUgPC0gZGltKG1hbHdhcmVfcmVzdWx0cyRlbmNvZGUpWzJdCmlucHV0czwtbGF5ZXJfaW5wdXQoc2hhcGUgPSBpbnB1dF9zaGFwZSkKZW1iZWRpbmc8LSBpbnB1dHMgJT4lIGxheWVyX2VtYmVkZGluZyg0MCwgMTAwICwgaW5wdXRfbGVuZ3RoID0gaW5wdXRfc2hhcGUpICU+JQpsYXllcl9mbGF0dGVuKCkgJT4lIGxheWVyX2RlbnNlKHVuaXRzID0gMSwgYWN0aXZhdGlvbiA9ICJzaWdtb2lkIikKCm1vZGVsIDwtIGtlcmFzX21vZGVsKGlucHV0cyA9IGlucHV0cywgb3V0cHV0cyA9IGVtYmVkaW5nKQptb2RlbCAlPiUgY29tcGlsZSgKICBvcHRpbWl6ZXIgPSAicm1zcHJvcCIsCiAgbG9zcyA9ICJiaW5hcnlfY3Jvc3NlbnRyb3B5IiwKICBtZXRyaWNzID0gYygiYWNjIikKKQoKbW9kZWwgJT4lIGZpdCh4PW1hbHdhcmVfcmVzdWx0cyRlbmNvZGUsCiAgICAgICAgICAgICAgeT1pZmVsc2UoZ3JlcGwoIkZhbHNlIE5lZ2F0aXZlIiwKICAgICAgICAgICAgICBtYWx3YXJlX3Jlc3VsdHMkbGFiZWwpLDEsMCksCiAgICAgICAgICAgICAgYmF0Y2hfc2l6ZSA9IDMyLAogICAgICAgICAgICAgIHZlcmJvc2UgPSAyLAogICAgICAgICAgICAgIGVwPTEwLAogICAgICAgICAgICAgIGNhbGxiYWNrcyA9IGNhbGxiYWNrX3RlbnNvcmJvYXJkKCJsb2dzL3J1bl9hIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaXN0b2dyYW1fZnJlcSA9IDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW1iZWRkaW5nc19mcmVxID0gMQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgICApIApgYGAKYGBge3J9CnRlbnNvcmJvYXJkKCJsb2dzIikgCmBgYAoK