diff --git a/bankofanthos_prototype/bankofanthos/accountsdb.sql b/bankofanthos_prototype/bankofanthos/accountsdb.sql index b980687..4ab94d4 100755 --- a/bankofanthos_prototype/bankofanthos/accountsdb.sql +++ b/bankofanthos_prototype/bankofanthos/accountsdb.sql @@ -17,8 +17,8 @@ -- users stores information about Bank of Anthos customers, including their -- username, password, name, etc. CREATE TABLE IF NOT EXISTS users ( - accountid CHAR(12) PRIMARY KEY, - username VARCHAR(64) UNIQUE NOT NULL, + accountid CHAR(12) UNIQUE NOT NULL, + username VARCHAR(64) PRIMARY KEY, passhash BYTEA NOT NULL, firstname VARCHAR(64) NOT NULL, lastname VARCHAR(64) NOT NULL, diff --git a/bankofanthos_prototype/bankofanthos/bankofanthos_demo b/bankofanthos_prototype/bankofanthos/bankofanthos_demo new file mode 100755 index 0000000..292ec82 Binary files /dev/null and b/bankofanthos_prototype/bankofanthos/bankofanthos_demo differ diff --git a/bankofanthos_prototype/bankofanthos/bankofanthos_demo_bug1 b/bankofanthos_prototype/bankofanthos/bankofanthos_demo_bug1 new file mode 100755 index 0000000..538cc06 Binary files /dev/null and b/bankofanthos_prototype/bankofanthos/bankofanthos_demo_bug1 differ diff --git a/bankofanthos_prototype/bankofanthos/frontend/handlers.go b/bankofanthos_prototype/bankofanthos/frontend/handlers.go index ebb188f..8c9706e 100644 --- a/bankofanthos_prototype/bankofanthos/frontend/handlers.go +++ b/bankofanthos_prototype/bankofanthos/frontend/handlers.go @@ -239,13 +239,17 @@ func (s *server) paymentHandler(w http.ResponseWriter, r *http.Request) { http.Error(w, "Invalid amount", http.StatusBadRequest) return } + + // [BUG0] + // paymentAmount *= 10000 paymentAmount *= 100 + logger.Debug("Debug: starting transactions") txn := model.Transaction{ FromAccountNum: authenticatedAccountID, FromRoutingNum: s.config.localRoutingNum, ToAccountNum: recipient, - ToRoutingNum: s.config.localRoutingNum, + ToRoutingNum: "000000000", Amount: int64(paymentAmount), Timestamp: time.Now(), } @@ -331,6 +335,9 @@ func (s *server) depositHandler(w http.ResponseWriter, r *http.Request) { http.Error(w, "Invalid amount", http.StatusBadRequest) return } + + // [BUG0] + // paymentAmount *= 10000 paymentAmount *= 100 txn := model.Transaction{ diff --git a/bankofanthos_prototype/bankofanthos/ledgerwriter/ledgerwriter.go b/bankofanthos_prototype/bankofanthos/ledgerwriter/ledgerwriter.go index f620b2d..242e3b2 100644 --- a/bankofanthos_prototype/bankofanthos/ledgerwriter/ledgerwriter.go +++ b/bankofanthos_prototype/bankofanthos/ledgerwriter/ledgerwriter.go @@ -150,8 +150,12 @@ func validateTransaction(localRoutingNum, authedAcct string, t *model.Transactio } // end of [BUG] - if !acctRegex.MatchString(t.FromAccountNum) || !acctRegex.MatchString(t.ToAccountNum) { - return fmt.Errorf("invalid transaction: Invalid account details: %s %s", t.FromAccountNum, t.ToAccountNum) + if !acctRegex.MatchString(t.FromAccountNum) { + return fmt.Errorf("invalid transaction: Invalid account %s: account length expected %d actual %d", t.FromAccountNum, accountIdLength, len(t.FromAccountNum)) + } + + if !acctRegex.MatchString(t.ToAccountNum) { + return fmt.Errorf("invalid transaction: Invalid account %s: account length expected %d actual %d", t.ToAccountNum, accountIdLength, len(t.ToAccountNum)) } if !routeRegex.MatchString(t.FromRoutingNum) || !routeRegex.MatchString(t.ToRoutingNum) { diff --git a/bankofanthos_prototype/bankofanthos/userservice/user_db.go b/bankofanthos_prototype/bankofanthos/userservice/user_db.go index b5dbf99..8b51085 100644 --- a/bankofanthos_prototype/bankofanthos/userservice/user_db.go +++ b/bankofanthos_prototype/bankofanthos/userservice/user_db.go @@ -15,8 +15,11 @@ package userservice import ( + "crypto/md5" + "encoding/binary" "errors" "fmt" + "io" "math/rand" "github.com/ServiceWeaver/weaver" @@ -57,14 +60,19 @@ func (udb *userDB) addUser(user User) error { } // Generates a globally unique alphanumerical accountid. -func (udb *userDB) generateAccountID(accountIdLength int) string { +func (udb *userDB) generateAccountID(accountIdLength int, username string) string { var accountID string for { // [BUG] // baseline code + h := md5.New() + io.WriteString(h, username) + seed := int64(binary.BigEndian.Uint64(h.Sum(nil))) + rand := rand.New(rand.NewSource(seed)) if accountIdLength == 10 { accountID = fmt.Sprint(rand.Int63n(1e10-1e9) + 1e9) } else { + // accountID = fmt.Sprintf("00%d", rand.Int63n(1e10-1e9)+1e9) accountID = fmt.Sprint(rand.Int63n(1e12-1e11) + 1e11) } // end of [BUG] diff --git a/bankofanthos_prototype/bankofanthos/userservice/userservice.go b/bankofanthos_prototype/bankofanthos/userservice/userservice.go index 9b61f5e..1972ef5 100644 --- a/bankofanthos_prototype/bankofanthos/userservice/userservice.go +++ b/bankofanthos_prototype/bankofanthos/userservice/userservice.go @@ -26,7 +26,6 @@ import ( "github.com/ServiceWeaver/weaver" "github.com/golang-jwt/jwt" - "golang.org/x/crypto/bcrypt" ) // CreateUserRequest contains data used for creating a new user. @@ -118,16 +117,16 @@ func (i *impl) CreateUser(ctx context.Context, r CreateUserRequest) error { return err } i.Logger(ctx).Info("Creating password hash.") - passwordHash, err := bcrypt.GenerateFromPassword([]byte(r.Password), bcrypt.MinCost) - if err != nil { - return err - } - accountID := i.db.generateAccountID(i.Config().AccountIdLength) + // passwordHash, err := bcrypt.GenerateFromPassword([]byte(r.Password), bcrypt.MinCost) + // if err != nil { + // return err + // } + accountID := i.db.generateAccountID(i.Config().AccountIdLength, r.Username) userData := User{ AccountID: accountID, Username: r.Username, - Passhash: passwordHash, + Passhash: []byte(r.Password), Firstname: r.FirstName, Lastname: r.LastName, Birthday: r.Birthday, @@ -152,7 +151,10 @@ func (i *impl) Login(ctx context.Context, r LoginRequest) (string, error) { return "", err } i.Logger(ctx).Debug("Validating the password.") - if err := bcrypt.CompareHashAndPassword(user.Passhash, []byte(r.Password)); err != nil { + // if err := bcrypt.CompareHashAndPassword(user.Passhash, []byte(r.Password)); err != nil { + // return "", err + // } + if string(user.Passhash) != r.Password { return "", err } diff --git a/bankofanthos_prototype/bankofanthos/weaver.toml b/bankofanthos_prototype/bankofanthos/weaver.toml index 952c725..8454582 100644 --- a/bankofanthos_prototype/bankofanthos/weaver.toml +++ b/bankofanthos_prototype/bankofanthos/weaver.toml @@ -1,5 +1,5 @@ [serviceweaver] -binary = "./bankofanthos" +binary = "./bankofanthos_demo" [single] listeners.bank = {address = "localhost:9000"} diff --git a/bankofanthos_prototype/bankofanthos/weaver_canary.toml b/bankofanthos_prototype/bankofanthos/weaver_canary.toml index a9d571b..fc6b20e 100644 --- a/bankofanthos_prototype/bankofanthos/weaver_canary.toml +++ b/bankofanthos_prototype/bankofanthos/weaver_canary.toml @@ -1,5 +1,5 @@ [serviceweaver] -binary = "./bankofanthos_experimental" +binary = "./bankofanthos_demo" [single] listeners.bank = {address = "localhost:9000"} diff --git a/bankofanthos_prototype/eval_driver/config1.toml b/bankofanthos_prototype/eval_driver/config1.toml new file mode 100644 index 0000000..2f2ee36 --- /dev/null +++ b/bankofanthos_prototype/eval_driver/config1.toml @@ -0,0 +1,21 @@ +[generatedPath] +dirPath = "generated" +configPath = "generated/configs/" +logPath = "generated/logs/" +outPath = "generated/out/" + + +[info] +prodPort = "9000" +databases = {"accountsdb"="postgresql://admin:admin@localhost:5432/accountsdb?sslmode=disable","postgresdb"="postgresql://admin:admin@localhost:5432/postgresdb?sslmode=disable"} +requestPath = "../tester/reqlog_demo.json" + +[stable] +port = "9003" +bin = "./../bankofanthos/bankofanthos_demo" +config = "../bankofanthos/weaver.toml" + +[canary] +port = "9004" +bin = "./../bankofanthos/bankofanthos_demo_bug1" +config = "../bankofanthos/weaver.toml" diff --git a/bankofanthos_prototype/eval_driver/config.toml b/bankofanthos_prototype/eval_driver/config2.toml similarity index 73% rename from bankofanthos_prototype/eval_driver/config.toml rename to bankofanthos_prototype/eval_driver/config2.toml index 51e08b1..0d8ccbf 100644 --- a/bankofanthos_prototype/eval_driver/config.toml +++ b/bankofanthos_prototype/eval_driver/config2.toml @@ -8,14 +8,14 @@ outPath = "generated/out/" [info] prodPort = "9000" databases = {"accountsdb"="postgresql://admin:admin@localhost:5432/accountsdb?sslmode=disable","postgresdb"="postgresql://admin:admin@localhost:5432/postgresdb?sslmode=disable"} -requestPath = "../tester/reqlog.json" +requestPath = "../tester/reqlog_demo.json" [stable] -port = "9001" -bin = "./../bankofanthos/bankofanthos" +port = "9003" +bin = "./../bankofanthos/bankofanthos_demo" config = "../bankofanthos/weaver.toml" [canary] -port = "9002" -bin = "./../bankofanthos/bankofanthos" +port = "9004" +bin = "./../bankofanthos/bankofanthos_demo" config = "../bankofanthos/weaver_canary.toml" diff --git a/bankofanthos_prototype/eval_driver/diff/diff.go b/bankofanthos_prototype/eval_driver/diff/diff.go index 79b368f..f609e95 100644 --- a/bankofanthos_prototype/eval_driver/diff/diff.go +++ b/bankofanthos_prototype/eval_driver/diff/diff.go @@ -13,6 +13,23 @@ var ( toFile = "experimental" ) +func printDiff(diff string) string { + var b strings.Builder + diffLines := strings.Split(diff, "\n") + for _, line := range diffLines { + if strings.HasPrefix(line, "@@") || strings.HasPrefix(line, "---") || strings.HasPrefix(line, "+++") { + b.WriteString(line) + b.WriteString("\n") + continue + } + b.WriteString(string(Bold)) + b.WriteString(line) + b.WriteString("\n") + b.WriteString(string("\x1b[0m")) + } + return b.String() +} + // outputEq compares two files content, print out the diff and return // a equal bool. func OutputEq(path1 string, path2 string) (bool, error) { @@ -26,9 +43,13 @@ func OutputEq(path1 string, path2 string) (bool, error) { return false, err } + // hack the response + output1Str := strings.ReplaceAll(string(output1), "400 Bad Request", "") + output2Str := strings.ReplaceAll(string(output2), "400 Bad Request", "") + diff := difflib.UnifiedDiff{ - A: difflib.SplitLines(string(output1)), - B: difflib.SplitLines(string(output2)), + A: difflib.SplitLines(output1Str), + B: difflib.SplitLines(output2Str), FromFile: fromFile, ToFile: toFile, Context: 0, @@ -42,6 +63,9 @@ func OutputEq(path1 string, path2 string) (bool, error) { return true, nil } - fmt.Println(strings.Replace(result, "\t", " ", -1)) + result = strings.ReplaceAll(result, "-", "<") + result = strings.ReplaceAll(result, "+", ">") + + fmt.Println(printDiff(result)) return false, nil } diff --git a/bankofanthos_prototype/eval_driver/diff/formatter.go b/bankofanthos_prototype/eval_driver/diff/formatter.go index fce458b..8f6e0db 100644 --- a/bankofanthos_prototype/eval_driver/diff/formatter.go +++ b/bankofanthos_prototype/eval_driver/diff/formatter.go @@ -4,6 +4,7 @@ import ( "bankofanthos_prototype/eval_driver/dbbranch" "fmt" "strings" + "time" ) type Code string @@ -71,7 +72,22 @@ func stringifyRow(row *dbbranch.Row) ([]string, error) { var rowSlice []string for _, col := range *row { - rowSlice = append(rowSlice, fmt.Sprintf("%v", col)) + value := fmt.Sprintf("%v", col) + if b, ok := col.([]byte); ok { + value = string(b) + } + if t, ok := col.(time.Time); ok { + + year, month, day := t.Date() + hour, minute, sec := t.Clock() + if hour == 0 && minute == 0 && sec == 0 { + value = fmt.Sprintf("%04d-%02d-%02d", year, int(month), day) + } else { + value = fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d", year, int(month), day, hour, minute, sec) + } + + } + rowSlice = append(rowSlice, fmt.Sprintf("%v", value)) } return rowSlice, nil @@ -108,6 +124,10 @@ func stringifyRows(left []*dbbranch.Row, middle []*dbbranch.Row, right []*dbbran func DisplayDiff(branchDiffs map[string]*dbbranch.Diff, displayInlineDiff bool) (string, error) { var b strings.Builder for tableName, tableDiff := range branchDiffs { + // skip empty tables + if len(tableDiff.Baseline) == 0 { + continue + } if displayInlineDiff { formatter := newInlineFormatter(&b, tableDiff, tableName) err := formatter.flush() diff --git a/bankofanthos_prototype/eval_driver/main.go b/bankofanthos_prototype/eval_driver/main.go index b4238f6..05f4abc 100644 --- a/bankofanthos_prototype/eval_driver/main.go +++ b/bankofanthos_prototype/eval_driver/main.go @@ -88,7 +88,9 @@ func main() { // parse flags var configFile string var deleteBranches, inlineDiff bool - flag.StringVar(&configFile, "configFile", "config.toml", "Config file for eval") + var expCnt int + flag.StringVar(&configFile, "configFile", "config1.toml", "Config file for eval") + flag.IntVar(&expCnt, "expCnt", 3, "experimental run cnt") flag.BoolVar(&deleteBranches, "deleteBranches", true, "Delete branches at the end of eval run, only set false for investigation purpose") flag.BoolVar(&inlineDiff, "inlineDiff", false, "Whether to use inline diff or not") flag.Parse() @@ -125,7 +127,7 @@ func main() { } var controlService *service.Service - for _, trail := range trails { + for i, trail := range trails { service, err := runTrail(ctx, trail, branchers, v1ProdService, v2ProdService, request, configLoader) if err != nil { log.Panicf("trail run failed: %v", err) @@ -149,6 +151,9 @@ func main() { } printDbDiffs(ctx, branchers, trail.Name, configLoader.GetOutPath(), controlService.Branches, service.Branches, inlineDiff, request.Count) } + if i == expCnt { + break + } } fmt.Println("Exiting program...") diff --git a/bankofanthos_prototype/tester/main.go b/bankofanthos_prototype/tester/main.go index f508d79..c6b3377 100644 --- a/bankofanthos_prototype/tester/main.go +++ b/bankofanthos_prototype/tester/main.go @@ -13,7 +13,7 @@ const reqLog = "reqlog.json" //req log file func main() { var countsList string - flag.StringVar(&countsList, "counts", "6, 9", "Req count per user, must be >= 3, split by,") + flag.StringVar(&countsList, "counts", "5", "Req count per user, must be >= 3, split by,") flag.Parse() var counts []int diff --git a/bankofanthos_prototype/tester/reqlog_demo.json b/bankofanthos_prototype/tester/reqlog_demo.json new file mode 100644 index 0000000..7fcb26c --- /dev/null +++ b/bankofanthos_prototype/tester/reqlog_demo.json @@ -0,0 +1,94 @@ +{ + "HttpReqs": [ + { + "Body": { + "address": [ + "111 8th Avenue, New York" + ], + "birthday": [ + "2024-4-1" + ], + "country": [ + "United States" + ], + "firstname": [ + "hello" + ], + "lastname": [ + "world" + ], + "password": [ + "1234" + ], + "password-repeat": [ + "1234" + ], + "ssn": [ + "111-11-1111" + ], + "state": [ + "NY" + ], + "timezone": [ + "-5" + ], + "username": [ + "demo" + ], + "zip": [ + "10011" + ] + }, + "Method": "POST", + "Url": "http://localhost:9000/signup" + }, + { + "Body": { + "account": [ + "add" + ], + "amount": [ + "500" + ], + "external_account_num": [ + "1234567890" + ], + "external_label": [ + "" + ], + "external_routing_num": [ + "123456789" + ], + "uuid": [ + "8387987a-9785-45bd-ada5-89f2a91a9135" + ] + }, + "Method": "POST", + "Url": "http://localhost:9000/deposit" + }, + { + "Body": { + "account_num": [ + "add" + ], + "amount": [ + "100" + ], + "contact_account_num": [ + "3109957291" + ], + "contact_label": [ + "" + ], + "external_routing_num": [ + "678089733" + ], + "uuid": [ + "a3cb5ada-66b9-4b0a-9976-d7e6d273b02d" + ] + }, + "Method": "POST", + "Url": "http://localhost:9000/payment" + } + ] +} \ No newline at end of file